How to Detect Dynamically generated ROWS in TABLE - javascript

I have a Table and its rows are created dynamically.
I want to prompt a message [alert] when the tr or td is generated.
At first it will be like
<table class="tab"></table>
After that the rows will be added dynamically.
<table class="tab">
<tr class="row">
<td> Message1</td>
<td> Message2</td>
<tr>
</table>
The Class names for Table and TR will always same but message in TD will change.
I want to display the messages in ALERT when TD is added.
EDIT
It seams my question is not clear.
I'm trying to implement this JSF thing from following link
CLICK HERE
Its a File Upload thing,when you upload wrong file then it will throw a error message in Table row, I want to alert a message when it happens.
ANSWER
Hello Every one Thanks for All of you answers. I got the Answer.
$(document).bind('DOMNodeInserted', function(e) {
var element = e.target;
if($(element).is("tr.tab")) {
alert("New ROW ADDED");
}
});

I think the solution to this can be simplified somewhat by using jqueries .on() event
Using this allows you to specify the event and selector in one statement:
$(document).on( "DOMNodeInserted", "tr.row", function() {
alert( "New ROW ADDED" );
});
Here's a working JSFiddle

I suggest you a solution based on this discussion: How to detect new element creation in jQuery?
$(document).ready(function(){
$(document).bind('DOMSubtreeModified',function(){
$('.template-upload.ui-state-error').each(function( index ){
alert( "The file '"+$(this).find('.name').html()+" is not valid" );
$(this).find('.ui-icon-cancel').click();
});
})
});
Unfortunally I'm not a jquery expert, so check my code and do your experiments. Let me know if you need more help.

Take a look at DOM Events
https://en.wikipedia.org/wiki/DOM_events
"DOMNodeInserted - Fires when a node has been added as a child of another node"
Failing that, you could poll the DOM with a timeout, and add a class to everything you've already processed
setatimeout...
function timeouthandler (
var newitems = $.(".tab td").not('.processed');
if newitems {
alert('new stuff!');
newitems.addClass('processed')
}
setanothertimeout...
)
this is off the top of my head and needs some work. Feel free to edit this answer with something that actually works ;-)

You can use setinterval and write a function in such a way that if html for table is changed. then find the appended td and alert the message for user.
var previous_tr_html='';
setInterval(function() { $checkError(); }, 1000);
function checkError(){
var current_tr_html=$('.row').html();
if(previous_tr_html!=current_tr_html){
//new td added
newerrortds=$('.row').find('td:not(.displayed)');
$(newerrortds).each(function(){
alert($(this).html();)
//add already displayed error class to current td
$(this).addClass('displayed');
});
//change previous html value to current
previous_tr_html=current_tr_html;
}
}

Extend the uploader script to report this by its own by event callback - the best way for me.

Related

jQuery click event on dynamically generated elements for calendar?

The answer to the following question,
var counter = 0;
$("button").click(function() {
$("h2").append("<p class='test'>click me " + (++counter) + "</p>")
});
$("h2").on("click", "p.test", function(){
alert($(this).text());
});
I have a dynamically generated calendar that when you click on an individual day, instead of opening a new web page, it swaps the calendar for the events of the day. The events are listed in a table and I want to be able to click on a row and and have it trigger a function which uses location.assign(). So each row looks like the following,
<tr id="message-7">
New page in calendar loads and creates,
<tr id="message-132">
Clicking does not trigger the function. In the example from the other question, it accesses the text of the element in order to make the element unique as opposed to giving the element a unique id # as in my situation.
Am I approaching the problem the wrong way? Could I add something like a "title=132" tag that I could reference?
Ideally try not to make too much meaning out of the ID. Instead use data as shown here.
So instead of
<tr id="message-7">
use
<tr id="1234567" data-message="7">
Then in code you can address the data as:
var messageVal = $("#1234567").data("message")
And if you need to add a generic click event then you might want to use a dummy css class assignment for all appropriate TR's:
<tr id="1234567" data-message="7" class="messageRow">
so that you can write
$(".messageRow").on("click", function(event){
event.preventDefault()
var messageVal = $(this).data("message")
This is useful in the case where only some TR's will contain clickable content - just don't assign the class to the others.

Sending an array in a javascript function with append

So here is the situation, im creating a clickable dynamic table by adding row with a button. Each row have informations and can be clicked (the entire row). I look for a way to send the information of the row I clicked to another js function who will copie the row in another dynamic table. But here is the trick : to create a clickable row, I use the function .append and I create the row in a < a> tag which will use href="function_to_add_the_copied_row" to call the other function.
The problem is I cant find out the good syntax. Any suggestion for syntax or other way to do the trick would be appreciated. Here is my code :
//javascript function to make clickable rows
{
var infos = modules_found[i].split("\\t");
rowNum++;
//word ="'Row number : "+infos[0]+"'";
$(".targets").append('<li> <div class="ui-grid-a"><div class="ui-block-a ui-grid-b"><div class="ui-block-a">'+infos[0]+'</div><div class="ui-block-b">'+infos[1]+'</div><div class="ui-block-c">'+infos[2]+'</div></div><div class="ui-block-b ui-grid-b"><div class="ui-block-a">'+infos[3]+'</div><div class="ui-block-b">'+infos[4]+'</div><div class="ui-block-c">'+infos[5]+'</div></div></div></li>');
}
//javascript function who receive the array and add the copied row
function transferArray(infos)
{
alert("in transferArray function");
$(".copied").append('<li> <div class="ui-grid-a"><div class="ui-block-a ui-grid-b"><div class="ui-block-a">'+infos[0]+'</div><div class="ui-block-b">'+infos[1]+'</div><div class="ui-block-c">'+infos[2]+'</div></div><div class="ui-block-b ui-grid-b"><div class="ui-block-a">'+infos[3]+'</div><div class="ui-block-b">'+infos[4]+'</div><div class="ui-block-c">'+infos[5]+'</div></div></div></li>');
}
Here is a high level approach (assuming you know jQuery): instead of wrapping your row inside A tag, better way is to have register a click event listener on your table (via jQuery APIs and not in HTML). In that click handler you can get the index of row clicked easily (make use of jQuery APIs) and once you have the rowindex, you can easily clone the row and move it to somewhere else.
typically how this is handled - if you are not using some type of javascript library like Angular or Knockout is to just store data in the actual HTML with data attributes. you can make as many data attributes as you want as long as they start with data-
ex.
$(".targets").append('<li data-id="xx" data-name="xx" data-custom=""> <a href="...
then I would recommend using jQuery click handler on every row by giving them all a class , ex.
$(".targets").append('<li class="rowClick" data-id="xx" data-name="xx" data-custom=""> <a href="...
then handle the click like this
$(document).on('click' , 'rowClick' , function(e){
var $this = $(this);
//get data of row clicked
var idClicked = $this.attr('data-id');
var nameClicked = $this.attr('data-name');
// you also have the full HTML of the clicked row if you need to copy somewhere
var rowHtml = $(".copied").append($this);
});
You're already using jQuery , so use it to handle the click and then you have the element clicked as a jQuery object right there . You can use native javascript function to handle the click and pass data like you were , but you already are using jQuery and that will automatically bring in a lot more data for you.
Finally, I used native javascript function since the suggested solution didn't work, even if it looks all legit. So here is what I have done:
(...)
//append the js function
$(".FindTable").append('<li id="addedFindRow"><div class="ui-grid-a"><div class="ui-block-a ui-grid-b"><div class="ui-block-a">'+infos[0]+'</div><div class="ui-block-b">'+infos[1]+'</div><div class="ui-block-c">'+infos[2]+'</div></div><div class="ui-block-b ui-grid-b"><div class="ui-block-a">'+infos[3]+'</div><div class="ui-block-b">'+infos[4]+'</div><div class="ui-block-c">'+infos[5]+'</div></div></div></li>');
}
function copyrow(info0,info1,info2,info3,info4,info5)
{
//use data
}
This is quite heavy, but that will do. Would be more chaotic if there was more parameters thought.

How to get td values from dynamically created table

I see a lot of similar questions but not one that directly targets my problem. The business logic of my problem is that I allow the user to open a jQuery Dialog where I create table loaded with a data from a database and when the user make a choise I load the selected data info fields from the main screen.
My current problem is with collecting the data from the <tr> which happens on button click. If it was a hard coded table I would just:
$(selector).on('click', function(){
var $item = $(this).closest("tr").find('td');
})
and then do something with $item however the table is created dynamically (from Ajax request) everytime the Ajax request is made the table is destroyed and recreated so basically I can't or at least I don't know a way to use some sort of selector to which to bind the event so I can reproduce the above code.
Instead in the dynamic table I have this:
<td><button onclick="getData();return false">Select</button>
The problems with this (at least how I see it) are two - first, the using of onclick inside HTML element. From what I know it's not a good practice and there are better alternatives and I would appreciate answer showing this. Also, even though I go with this code I'm yet unable to extract the text from each <td> in:
function getData() {
...
}
I tried several approaches including the one which was working with the static table and the binded event handler.
At the end here is a JS Fiddle example where I think I made it clear what I can and what I can not do, so you can refer to it.
Check this fiddle
$(selector).on('click', function(){
var $item = $(this).closest("tr").find('td');
})
Using the above code you are binding a direct event but the one which you want is delegated event
To use delegated event you should use like
$(document).on('click',selector, function(){
var $item = $(this).closest("tr").find('td');
})
so your final code will look something like
$(document).on('click','.get-data' ,function(){
var $item = $(this).closest("tr").find('td');
$.each($item, function(key, value){
alert($(value).text());
})
});
document can be anything which is parent to the table which is going to be created.
Dont forget to add the selector while adding a new table element
I had the same problem and solved it that way.
You can create your table with the database results like this:
for (var i = 0; i < results.length; i++) {
// create table row and append it to the table using JQuery
// next create a td element, append it to the created tr
// and attach a listener to it
$('<td/>').html(results[i].textProperty)
.appendTo($(tr))
.on('click', getData);
}
where getData() is your function.
You can pass arguments to your getData like this:
.on('click', {info: results[i].data}, getData);
Then you can access them in your function:
function getData(event) {
console.log(event.data.info);
}
Hope this helps!
Edit: This way you are creating a listener for each td. An optimization could be to create a listener for the whole class of td elements and to pass data to it via HTML attributes or text value like in the approved answer.
or you can use this pass object in getdata method
$('#build-table').on('click', function(){
$('#temp-table').append('<table><thead><tr><th>Select</th><th>Name</th> </tr></thead>' +
'<tbody><tr><td><button class onclick="getData(this);return false">Select</button></td><td>Name1</td></tr>' +
'<tbody><tr><td><button onclick="getData(this);return false">Select</button></td><td>Name2</td></tr>' +
'</tbody></table>')
});
function getData(ob) {
var $item = $(ob).closest("tr").find('td');
$.each($item, function(key, value){
alert($(value).text());
})
}

Alternative to jQuery replaceAll()?

I have some code that removes a tr from a dynamically built table as a jQuery object (each tr has a unique id: trid):
tri = $("#"+trid+"");
var newrow = '<tr id="newr"><td colspan="4" align="center"><div id="nrow"> </div></td></tr>';
tri.after(newrow);
tri.detach();
I then put a form in the div 'nrow' using innerHTML... There's a jQuery ui datepicker in the form that works this first time.
When the form is cancelled I put the list back to the way it was:
setTimeout("tri.replaceAll( $('#newr') )", 400);
This all works beautifully, except that it kills the jquery ui datepicker in the form if I try to edit that (or any) row after that. I've trouble shot it down to being the replaceAll line. If I take that out and replace the list by building it again it works just fine (it's not the timeout either).
So is there another way to replace the tr 'newr' with the jquery object 'tri' without using replaceAll (replaceWith doesn't work either)?
EDIT:
OK so this is how I move the form from the div elsewhere on the page:
eP = $('#eP');
eP.replaceAll( $('#nrow') );
$("#editPast").show('blind','',500,'');
eP contains the hidden div editPast...
then in the cancel function I put eP back:
setTimeout(function() {eP.appendTo($('#ePreplace')); }, 500); (thanks adeneo!)
before I tri.replaceAll, though with the setTimeout it happens after...
So I guess my problem is that eP doesn't carry the datepicker state after it's been used in #nrow, just the html.
FIXED!
changed eP.appendTo to $('#eP').appendTo so that it takes it from the dom instead of the original variable. Oops! Thanks for making me re-think this with your just detach() comment!
FIXED!
changed eP.appendTo to $('#eP').appendTo so that it takes it from the dom instead of the original variable. Oops! Thanks adeneo for making me re-think this with your 'just detach()' comment!
Thanks NiftyDude for suggesting I do this too...

Manipulating row data with Javascript

I have a specific question, I have a link in a table in the third column of each row, when the user clicks that link he loads some ajax and updates the page, what I want to also happen is that in the 2nd column of the row where the link is, change the td's class from false to true, and the value from No to Yes.
Thanks!
Update!
Code Example:
The 2nd column still doesn't get updated on click, perhaps this is because the div where the table is located gets hidden onclick? Anyways here's what I've tried:
<tr>
<td>00839</td>
<td class="false" style="text-align:left;">No</td>
<td>
<a href="#"
onclick="Element.hide('ajax-instruction-view');;
new Ajax.Updater('ajax-instruction-view', '/tasks/show_ajax/839', {asynchronous:true, evalScripts:true, onComplete:function(request){new Effect.Appear("ajax-instruction-view",{});window.scrollTo(0,0);
link = $(link);
var row = link.up('tr');
var cell = row.down('td').next('td');
cell.update('Yes');},
parameters: 'authenticity_token='encodeURIComponent('SYWsdBTWlz17u9HmPXA2R9WmBfZn67g/IAMGyhHEwXw=')}); return false;"
>
Instructions-Notice Board
</a>
</td>
<td>19/04/10</td>
<td class="false">21/04/10</td>
<td class="false" style="text-align:left;">None.</td>
</tr>
It sounds as though at some point, you have a reference to the link the user clicked (either because you have a click handler on it or because you're using event delegation and finding it after a click on the table). Starting with a reference to that link, you can use Prototype's DOM traversal stuff to find the second table cell:
Edit Based on your response to rahul, I would change your link onclick to:
onclick="handleLinkClick(this); return false;"
...and this would be handleLinkClick:
function handleLinkClick(link) {
// Original code (mostly unchanged)
Element.hide('currentdiv');
new Ajax.Updater('someajax', 'ajax.html', {
asynchronous:true,
evalScripts:true,
onComplete: function(request) {
new Effect.Appear("newdiv",{});
window.scrollTo(0,0);
// New code starts here
// Extend the link element
link = $(link);
// Find the row
var row = link.up('tr');
// Find the second column
var cell = row.down('td').next('td');
// Change the cell's "class" and "value" -- I've had to guess a bit at
// what you want to do here
if (cell.hasClassName("true")) {
cell.removeClassName("true").addClassName("false");
cell.update("No");
}
else {
cell.removeClassName("false").addClassName("true");
cell.update("Yes");
}
// End of new code
},
parameters:'authenticity_token=' + encodeURIComponent('SYWsdBTWlz17u9HmPXA2R9WmBfZn67g/IAMGyhHEwXw=')
});
}
That uses Element#up, Element#next, Element#hasClassName, Element#addClassName, Element#removeClassName, and Element#update; docs for them here.
Optional things to consider:
The above is fragile in that if you change the location of that cell (make it the third column rather than the second), it fails. You might use a marker class to find it.
Rather than an onclick attribute, you could use Element#observe.
You can use event delegation to have just one handler on the table, rather than a handler on each link.
But the above should work.
I dont recall how to write it in Scriptaculous but in jQuery it would be:
$(element).click(function(){
// invoke your ajax routine
// change class
$($(this).parent('tr').children().get(1)).attr('class', 'my-classname');
});
Maybe someone can translate :-)

Categories