Programmatically creating <DIV>s and problems arise - javascript

I am new to javascript and have written a piece of code (pasted below). I am trying to build a little game of Battleship. Think of that game with a grid where you place your ships and start clicking on opponents grid blindly if it will hit any of the opponents ships. Problem is I need to get a function called with the ID of the DIV to be passed as a parameter. When the DIV is programmatically created like below, what will work. This? : --///<.DIV id='whatever' onclick='javascript:function(this.ID)' /> .. I saw sth like that somewhere .. this inside html :S
the js code is: (there are two grids, represented by the parameter - who - ... size of grid is also parametric)
function createPlayGround(rows, who)
{
$('#container').hide();
var grid = document.getElementById("Grid" + who);
var sqnum = rows * rows;
var innercode = '<table cellpadding="0" cellspacing="0" border="0">';
innercode += '<tr>';
for (i=1;i<=sqnum;i++)
{
var rowno = Math.ceil(i / rows);
var colno = Math.ceil(i - ((rowno-1)*rows));
innercode += '<td><div id="' + who + '-' + i +'" class="GridBox'+ who +'" onmouseover="javascript:BlinkTarget(' + i + ',' + who +');" onclick="javascript:SelectTarget('+ i + ',' + who +');" >'+ letters[colno - 1] + rowno +'</div></td>';
if (i % rows == 0)
{
innercode += '</tr><tr>';
}
}
innercode += '</tr></table>';
grid.innerHTML = innercode;
$('#container').fadeIn('slow');
}

It sounds like what you really want is to get the div element that was just clicked on. If you just want to return the div that was clicked on, all you have to do is use "this":
<div id="whatever" onclick="function(this)"></div>
If you're actually more interested in getting the id of the div clicked on, you can do this:
<div id="whatever" onclick="function(this.id)"></div>
However, it sounds like you just want the id so that you can get the div using getElementById, and the first code snippet will help you skip that step.

Instead of creating the inner html from strings you can create it with jQuery and add event listeners like so:
$("<div></div>")
.click(function(e) {
selectTarget(i, who);
})
.appendTo(container);

Related

How do I add data into html table using jquery?

I'm trying to add data from my firebase realtime database into a html table using jquery and javascript. I'm new to jquery, so I more or less have no idea what I'm doing.
I can retrieve the data but I can't add it to the table on the html page.
Is something wrong with this line?:
$("#table_body tbody").append("<tr><td>" + name.Name + "</td><td>" +
user.Email + "</td></td></td></tr>");
the table_body is just the table's id. The table remains empty.
pls help
You can add things to a table like this:
function productsAdd() {
$("#productTable tbody").append(
"<tr>" +
"<td>My First Item</td>" +
"<td>6/11/2019</td>" +
"<td>www.itemsite.com</td>" +
"</tr>"
);
}
Is this code running on load? Is this code wrapper in:
$(document).ready(function(){});
The document must be loaded before jQuery code can run properly, the function above ensures jQuery inside of it runs after the DOM has loaded
Example:
$(document).ready(function() {
let arr = [{n:'test', e:'ing'}, {n:'stuff', e:'ok'}];
for(let i = 0; i < arr.length; i++) {
$("#table_body tbody").append("<tr><td>" + arr[i].n + "</td><td>" + arr[i].e + "</td></tr>");
}
});

Passing argument to on click event of dynamically generated element

I am trying to pass arguments to onclick event of dynamically generated element. I have already seen the existing stackoveflow questions but it didn't answer my specific need.In this existing question , they are trying to access data using $(this).text(); but I can't use this in my example.
Click event doesn't work on dynamically generated elements
In below code snippet, I am trying to pass program and macroVal to onclick event but it doesn't work.
onClickTest = function(text, type) {
if(text != ""){
// The HTML that will be returned
var program = this.buffer.program;
var out = "<span class=\"";
out += type + " consolas-text";
if (type === "macro" && program) {
var macroVal = text.substring(1, text.length-1);
out += " macro1 program='" + program + "' macroVal='" + macroVal + "'";
}
out += "\">";
out += text;
out += "</span>";
console.log("out " + out);
$("p").on("click" , "span.macro1" , function(e)
{
BqlUtil.myFunction(program, macroVal);
});
}else{
var out = text;
}
return out;
};
console.log of out give me this
<span class="macro consolas-text macro1 program='test1' macroVal='test2'">{TEST}</span>
I have tried both this.program and program but it doesn't work.
Obtain values of span element attributes, since you include them in html:
$("p").on("click" , "span.macro" , function(e)
{
BqlUtil.myFunction(this.getAttribute("program"),
this.getAttribute("macroVal"));
});
There are, however, several things wrong in your code.
you specify class attribute twice in html assigned to out,
single quotes you use are not correct (use ', not ’),
quotes of attribute values are messed up: consistently use either single or double quotes for attribute values
var out = "<span class='";
...
out += "' class='macro' program='" + program + "' macroVal='" + macroVal + ;
...
out += "'>";
depending on how many times you plan to call onClickTest, you may end up with multiple click event handlers for p span.macro.

How to Prevent TD from ending up on a new line?

I am dynamically creating a table through Javascript and I DO want the table to continue off the right side of the page. Doing this manually lets the table continue off, but once I feed this into a for loop the <td>s wrap into a second line in the rendered HTML, creating two or more table rows when they reach the end of the page.
<div id="panelindex" style="overflow:scroll;text-align:center;">
<table border="0">
<tr></tr>
</table>
</div>
This is inside a table of its own (no style formatting). Then the Javascript:
var q = Math.floor((1/numpanels)*500);
if(q>50) q=50;
panelindex.innerHTML = "<table border='0'><tr>"
for(i=0; i<numpanels; i=i+1)
{
panelindex.innerHTML = panelindex.innerHTML + "<td><div id='panel" + i + "' onclick='jumppage(" + i + ")' style='float:left;text-align:center;margin:8px;border-width:3;border-color:white;border-style:none;'><a href='#" + i + "'><img src='thumbnails.php?image=blowem" + zeroFill(i,2) + ".gif&GIF&tw=128&th=128&quality=" + q + "'>\n" +
"<br />" + i + "</a></div></td>\n";
}
panelindex.innerHTML = panelindex.innerHTML + "</tr></table>"
You may notice that there is a <div> in the <td> and that is so I can apply a border marking the panel. Without the <div> it seems I cannot do that, and there are some other undesired effects. Any ideas what I can do so that all the <td>s end up on one line rather than split to a new line?
Example of what I want: http://edwardleuf.org/comics/jwb/009-conmet
What is happening: https://jsfiddle.net/w4uh0a3j/7/
Click the Show link.
innerHTML does not hold the string value you assign to it.
It parses the value as HTML, creates a DOM from it, inserts it into the document and then, when you read it back, it converts that DOM back into HTML.
This means that the string you assign is subject to error recovery and normalisation. In particular, the end tags you omitted are fixed.
panelindex.innerHTML = "<table border='0'><tr>"
console.log(panelindex.innerHTML);
<div id="panelindex" style="overflow:scroll;text-align:center;">
<table border="0"><tr>
</tr></table>
</div>
So when you start appending more data to it:
panelindex.innerHTML = panelindex.innerHTML + "<td>etc etc
You end up with:
<table border="0"><tbody><tr></tr></tbody></table><td>etc etc
Store your data in a regular variable. Only assign it to .innerHTML once you have the complete HTML finished.
A better approach then that would be to forget about trying to build HTML by mashing strings together (which is error prone, especially once you start dealing with characters that need escaping in HTML) and use DOM (createElement, appendChild, etc) instead.
OK,here is fixed html and js code. It seems like innerHTML fixes missing closing when updating html before all the code is building the rest of innerHTML. This code works :
<div id="panelindex" style="overflow:scroll;text-align:center;">
</div>
and js code :
var numpanels = 100;
var q = Math.floor((1/numpanels)*500);
if(q>50) q=50;
panelindex.innerHTML = "<table border='0'><tr>";
var html = "<table border='0'><tr>";
for(i=0; i<numpanels; i=i+1) {
html += "<td><div id='panel" + i + "' onclick='jumppage(" + i + ")' style='float:left;text-align:center;margin:8px;border-width:3;border-color:white;border-style:none;'><a href='#" + i + "'><img src='thumbnails.php?image=blowem" + ".gif&GIF&tw=128&th=128&quality=" + q + "'>\n" +
"<br />" + i + "</a></div></td>";
}
html += "</tr></table>";
document.getElementById("panelindex").innerHTML = html;

Append to end of a div through Jquery

I have this div which has a table and i want to add a row to that table dynamically based on a scenario. how this can be done with jquery ?
<div style="margin-bottom: 4px;" id="div_outgoing_call_dates_rows">
<table id="tbl_dynamic_call_dates">
<tbody><tr><td>Appointment date</td><td>Client time window</td></tr>
<tr id="client_app_0"><td>04/10/2013</td><td><select name="CSSAtapsClient[client_time_window_arr][0]" id="client_time_window_0">undefined<option value="5702">07am - 10am</option><option value="5703">10am - 1pm</option><option value="5704">12pm - 3pm</option><option value="5705">03pm - 06pm</option><option value="5706">06pm - 09pm</option><option value="5707">07pm - 10pm</option><option value="5708">09pm - 12am</option><option value="5709">12am - 7am</option></select></td>
</tr>
</tbody>
</table>
</div>
I tried this and it didint work at last row instead adds inside the div and old contents gets cleared.
$("#div_outgoing_call_dates_rows").append(dynamicRow);
Appreciate an early response.
Fiddle Here
EDIT 2
$.each(array,function(i){
if($("#client_app_tr_" + array[i]).length == 0) {
console.log("yes not exisit so adding a new one");
dynamicRow += "<tr id=\'client_app_tr_" + array[i] + "\'><td>" + array[i] + "</td><td>" + "<select id=\'client_time_window_" + i + "\' name=\'CSSAtapsClient[client_time_window_arr][" + i + "]\'>" + dynamicDD + "</select>" + "</td></tr>";
}
});
I have tr id's like this -> client_app_tr_07/10/2013, client_app_tr_08/10/2013, client_app_tr_09/10/2013 ... so if that id is not there i need to add a new row. it doesnt work because the way i am checking it always goes inside this loop. if($("#client_app_tr_" + array[i]).length == 0) {}
EDIT 3
This also doesnt seem to be working. i must be missing something or isnt there any way to check weather a element id exisit or not in jquery ?
if($("#client_app_tr_" + array[i])[0] !== true) {}
Try this, this will help you.
var old_item =$('#div_outgoing_call_dates_rows').html();
old_item=old_item+'New Content';
$('#div_outgoing_call_dates_rows').append(old_item);
Fiddle here.
div_outgoing_call_dates_rows is the div element, you need to append the row to the table inside the div, so use the descendant-selector
$("#div_outgoing_call_dates_rows table").append(dynamicRow);
You must select table in order to append a dynamic row, so change selector:
$("#div_outgoing_call_dates_rows table").append(dynamicRow);

jQuery append not completing before next statement?

I have a survey-type form that's being populated from a web database on the client. I can populate the questions fine, but then I try to go through and trigger the click event where there is an existing answer (edit scenario), I'm finding that the new elements are not yet in the DOM so this doesn't work. Here's the code:
$(function() {
var db = openDatabase(...);
db.transaction(function(tx) {
tx.executeSql("select ....", [surveyId], function(tx, results) {
var items = "", answers = [];
for (var i = 0; i < results.rows.length; i++) {
var id = results.rows.item(i).id;
items += "<div><input type='radio' name='q-" + id + "' id='q-" + id + "-1' /><label for='q-"+id+"-1'>Yes</label><input type='radio' name='q-" + id + "' id='q-" + id + "-2' /><label for='q-"+id+"-2'>No</label></div>";
if (result.rows.item(i).answer) {
answers.push('#q-'+id+'-'+results.rows.item(i).answer);
}
}
$('#questions-div').append(items);
$.each(answers, function(i, e) { $(e).click(); });
});
});
});
Any tips how I can make this work, or better generally?
I think here:
answers.push('#q-'+id+'-'+result);
You meant to push this:
answers.push('#q-'+id+'-'+result.rows.item[i].answer);
Otherwise you're getting '#q-XX-[object Object]' as a selector, where I think you're after the 1 or 2 version of '#q-XX-1'.
I suspect this is actually a race condition. My bet is that if you execute your each statement after a tiny delay, things will work as expected. Is so, the reason for this is that you can't be 100% sure when the browser will actually get around to updating the DOM when you programmaticallly insert new elements. I'm not sure what the best solution would be: if you were attaching events, I'd say you should do it at the same time you are building the elements; but if you are triggering the clicks, I'm leaning toward just continually testing for the existance of the elements and then triggering the clicks as soon as you know they are there.
So I came up with a solution:
I replaced the line items += "<div> ...." with
var item = "<div><input type='radio' name='q-" + id + "' id='q-" + id + "-1' ";
if (results.rows.item(i).answer == 1) item += "checked ";
item += "/><label for='q-"+id+"-1'>Yes</label><input type='radio' name='q-" + id + "' id='q-" + id + "-2' ";
if (results.rows.item(i).answer == 2) item += "checked ";
item += "/><label for='q-"+id+"-2'>No</label></div>";
items += item;
... which means I no longer need the answers array or to trigger click events on the radio buttons.
I was hoping for something a bit neater, but this seems to work OK. Thanks #Nick Craver & #Andrew for helping me arrive at it!

Categories