AJAX / JQuery - Print each nested child on new table row - javascript

I've been tearing my hair out over this seemingly simple problem, but I can't wrap my head around it.
I'm trying to generate a table in HTML using AJAX and some JQuery. The XML holds the data that I want rendered, each Child Node being rendered on a new line. The AJAX does all of the heavy lifting and generates the table.
XML Code:
<?xml version="1.0" encoding="utf-8"?>
<shows>
<show>
<title>Title</title>
<light>
<rule>Rule 1</rule>
<rule>Rule 2</rule>
</light>
<medium>
<rule>Rule 3</rule>
<rule>Rule 4</rule>
</medium>
<hard>
<rule>Rule 5</rule>
<rule>Rule 6</rule>
</hard>
<extreme>
<rule>Rule 7</rule>
</extreme>
</show>
</shows>
Obviously, I'll have more than this tiny bit of data down but that's besides the point.
Pertinent HTML
<table id="rules"></table>
And the Javascript:
$(xml).find('shows > show').each(function () {
var title = $(this).find('title').text();
title = "<tr>" + "<th>" + "</th>" + "<th>" + "<h1>" + title + "</h1>" + "</th>" + "</tr>";
category = "<tr>" + "<th>" + "</th>" + "<th>" + "Category Title: " + "</th>" + "</tr>";
rule = $(this).find('light > rule').text(); //problem is here?
punish = punish + "<tr>" + "<td>" + ruleCount + "</td>" + "<td>" + rule + "</td>" + "</tr>";
There's much more to the Javascript than this, but the line with the comment above I believe is the culprit of my headache. It's also essentially copied and pasted 3 more times in the script and modified to generate rules for medium, hard and extreme.
Here's the problem:
The Title, Category labels (table headers), rows, cells all generate just fine, but the data needs to be rendered so that each node (rule) is created on a new line (or new table row, essentially). Instead, the rule = $(this).find('light > rule').text(); line is cramming Rule 1 and 2 together, 3 and 4 together, etc (when reused further in the script obviously). The resulting HTML is a bit like this:
<table id="rules">
<tr><th></th><th><h1>Title</h1></th></tr>
<tr><td>1</td><td>Rule1Rule2</td></tr>
</table>
What I really want is for each rule to be on it's own table row. Like this:
<table id="rules">
<tr><th></th><th><h1>Title</h1></th></tr>
<tr><td>1</td><td>Rule1</td></tr>
<tr><td>2</td><td>Rule2</td></tr>
</table>
Any idea what I'm doing wrong??
Thanks in advance.

rule = $(this).find('light > rule').text();
This selects the two rule elements in light. text() returns a concatenation of the text of all elements in the wrapped set. You'll need to iterate over each rule using each()
$(this).find('light > rule').each(function() {
punish += "<tr><td>" + ruleCount + "</td><td>" + $(this).text() + "</td></tr>";
});

You need to use a loop to iterate through each rule
$(this).find('light > rule').each(function () {
punish = punish + "<tr>" + "<td>" + (ruleCount++) +"</td>" + "<td>" + $(this).text() + "</td>" + "</tr>";
})

Related

Chaging innerHTML of DIV changes table properties

I have to show dynamically checkboxes in a HTML page and get their value from database.
The trick I used is to create the whole table HTML in java and then using AJAX I do this
var div = document.getElementByID("div").innerHTML = htmlCode;
but issue is
in htmlCode variable, the html is like
<table width="100%">
<tr>
<td width="50%">......
but when I check div.innerHTML it shows like
<TABLE width="100%">
<TBODY>
<TR>
<TD width="50%">
<?xml:namespace prefix = ....
Why they become uppercase and why is xml:namaesapce prefix added ?
This causes issue as table is not properly displayed.
Is there any other better way to do this without using innerHTML ?
The code for generation of table is
String html = "<table width=\"100%\">";
for (Iterator it = lookupList.iterator (); it.hasNext ();)
{
HashTree lookupElement = (HashTree) it.next ();
String code = lookupElement.getChildTagValue ("CODE");
String text = lookupElement.getChildTagValue ("TEXT");
String labelText = "";
if(indexLookupElement == 0)
labelText = "First Checkbox label";
html = html + "<tr><td width=\"50%\" >" +
+
"<input type=\"checkbox\" id=\"item" + code + "\" />" +
"<html:label " +
"id=\"_Description\"" +
"name=\"_Description\"" +
">" + text +
"</html:label>" +
"<td width=\"50%\" >" +
"</td></tr>";
indexLookupElement += 1;
}
html = html + "</table>";
Thanks,
Aiden
It's not a best practice to create the HTML code server-side. If you are sure you'll have the table in your document it's better to make it part of the structure of the document and feed only the variables from your Java code. Even if the table is conditional you may consider hide/unhide it with a variable. I believe this approach will solve your problem if the HTML code of your webpage is correct.
Update
Test it like this:
html = html + "<tr><td width=\"50%\"><input type=\"checkbox\" id=\"item" + code + "\" /><label id=\"_Description\" name=\"_Description\">" + text + "</label></td><td width=\"50%\"></td></tr>";
In your code you have missing TD closing tag and I made some changes. See if this will fix your problem.

Dynamically add "select" with "default Text" in table through javascript

How can I add dynamical drop down selects(set default selecte!) in dynamically table by using javascript and JSON.
I want to add many selects (dropdown) to every row in my table, and set the default text in the select. The table is created by using javascript append and has dynamic content imported from JSON files using Jquery.
I can import all content successfully, however the dropdowns can not set selected . I would appriciate if you guys can assist me to have the dropdown select. Thank you very much!
<script type="text/javascript">
...
$(target).append("<tr style='height:150px'>" +
"<td><input type='checkbox'></td>" +
"<td>pics</td>" +
"<td>" + menuItemName + "</td>" +
"<td id='"+menuItemId+"'>" +
"</td>" +
"<td class='menuItemPrice'>" + menuData.Categories[c].Items[i].Price + "</td>" +
"<td>mount</td>" +
"</tr>"
);
...
for (var o = 0; o < menuData.Categories[c].Items[i].Options.length; o++) {
var inputs = {isFirst: firstOption,
optionId: menuData.Categories[c].Items[i].Options[o].MenuItemOptionId,
optionName: menuData.Categories[c].Items[i].Options[o].MenuItemOptionName,
price: menuData.Categories[c].Items[i].Options[o].Price
};
$('#'+menuItemId).append("<div><select"+
"<option value='1'>small</option>" +
"<option value='2'>mid</option>" +
"<option value='3'>big</option>" +
"<option value='4'>very big</option>"+
"</select></div>"
);
here I want to set the default Select but can not success,please help me,Thank You!
$('#'+menuItemId).children(':selected').text(inputs.optionName);//here just can show the last size.
HTML
...
<tbody id="sortable">
First, your select tag does not have a closing angle bracket (>) so the HTML is malformed. It should be something like this:
$('#'+menuItemId).append("<div><select>"+
Second, you should use find instead of children because what you are looking for is multiple levels below the element identified by your selector, like so:
$('#'+menuItemId).find(':selected').text(optionName);
Here is a working example: https://jsfiddle.net/tLddsL2p/1/

Changing element background color with jQuery .append

so my javascript code is creating a list of table items, however I want it to able to change the color of the row according to what selections were made, each time a new item is added. Here's my code
if ( valid ) {
$( "#tasks2 tbody" ).append( "<div id='taskList'><ul class='taskScreen2'><tr>" +
"<td><h1>" + type.val() + "</h1></td>"+"<td class='title'><h3>"+ title.val() + " </td>" +"<td>"+ wordcount.val() + "</h3></td>" +"<td><p>"+ description.val() + "</p></td>" + "<td>"+ deadline.val() + "</td>"+
"</tr></ul></div>"
+ "<script> if ($('#type').val()=='Dissertation')"
+ "{document.getElementById('taskList').style.backgroundColor = 'red';} </script>"
);
This only changes the color of the top item while any new ones remains the same. I want it to change the bg colour of new item whenever it is added. I tried including the function both inside and outside the .append but it did not work. Any help would be greatly appreciated.
You are appending divs all with same ID's(which is wrong).Use class instead and it should work.
Try this:
if (valid) {
var ids=$("#tasks2, #taskList, #type");
for (var x=0; x<ids.length; x++) {
ids.get(x).className=ids.get(x).id;
}
ids.attr("id", "");
$(".tasks2 tbody").append("\
<div class='taskList'><ul class='taskScreen2'><tr>"
+"<td><h1>"
+type.val()
+"</h1></td>"
+"<td class='title'><h3>"
+title.val()
+"</td>"
+"<td>"
+wordcount.val()
+"</h3></td>"
+"<td><p>"
+description.val()
+"</p></td>"
+"<td>"
+deadline.val()
+"</td>"
+"</tr></ul></div>"
// Reply to Egidijus Poškus's comment: Here's how to do it!
+"<script>$(\".type[value='Dissertation']\").css('background-color', 'red');$(\".type[value='Report']\").css('background-color', 'blue');\
");
}

How to nest table withing table read from json

I got this json object which its structure similar to this:
vendor have name, phone, fax, contacts
contacts have firstName, lastName, title, phone, email
I have created the first level in the table, but i didn't how to create the second nested level
function getData(vType) {
$.getJSON('/LocalApp/VendorController', {
vendorType : vType,
time : "2pm"
}, function(vendorsJson) {
$('#vendors').find("tr:gt(0)").remove();
var vendorTable = $('#vendors');
$.each(vendorsJson, function(index, vendor) {
$('<tr>').appendTo(vendorTable).append(
$('<td>').text(vendor.name)).append(
$('<td>').text(vendor.phone)).append(
$('<td>').text(vendor.fax)).append(
'<table class="contactTable"><tr><th>First Name</th><th>Last Name</th><th>Title</th><th>Phone</th><th>E-Mail</th></tr></table>');
});
});
}
So how can i add vendor.contacts as a nested table in jQuery code?
i know my code is not clean, jquery is confusing to me compared to Java
Not sure if you want the table in a cell of the vendor or not, but try something like this...
var contactTableHtml = '<table class="contactTable"><tr><th>First Name</th><th>Last Name</th><th>Title</th><th>Phone</th><th>E-Mail</th></tr></table>';
var vendorTableContent = $.map(vendorsJson,function (index, vendor) {
var contactTableContentHtml = $.map(vendor.contacts,function (index, contact) {
return "<tr><td>" + contact.firstName + "</td><td>" + contact.lastName + "</td><td>" + contact.title + "</td><td>" + contact.phone + "</td><td>" + contact.email + "</td></tr>";
}).join("");
return '<tr>' +
'<td>' + vendor.name + '</td>' +
'<td>' + vendor.phone + '</td>' +
'<td>' + vendor.fax + '</td>' +
'<td>' + contactTableHtml + contactTableContentHtml + '</td>' +
'</tr>';
}).join("");
vendorTable.append(vendorTableContent);
First I create a subtable as a string and then add it to the main table. I also suggest to create one big html string and add it once to the DOM. This is a lot quicker then calling $('...') everytime.
PS. Haven't been able to test it, but let me know if you get an error.
Unless you're very constrained for how much you can send with the page (that is, every single K of data counts against you), I don't think jQuery is a good fit for this kind of thing.
I think of JSON + something => HTML as templating, so I usually use a JavaScript templating tool like Handlebars to do that kind of thing. It's a more natural fit. Plus you can try right now with a site like Try Handlebars.js to interactively craft a template that takes some of your sample JSON and output the HTML you desire.
In all likelihood, a {{#each}} with another {{#each}} inside of it could probably handle the conversion of a nested JSON to whatever HTML you're after.

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>

Categories

Resources