How to access via jquery to select controls created dynamically - javascript

I have created dynamically some select controls(a.k.a. groupbox) but every time that I try to access to one of them if get the followig error:
Uncaught TypeError: undefined is not a function
Here is the code:
var method =$("#slt" + (parseInt(buttonElementId + 1))).children("option").is("selected").text();
Where parseInt(buttonElementId + 1 is always a number so the error is not there
<html>
<head lang="en">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
<style>
body { padding-top:80px; }
html, body, #wrapper
{
width: 100%;
height: 100%;
}
</style>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div class="container">
<div id="information"></div>
<div id="tableInformation"></div>
<div id="goBack"></div>
<br/>
<div id="inputDiv"></div>
<br/>
<br/>
<div id="UserGuide"></div>
</div>
<script src="js/jquery-1.11.js"> </script>
<script>
var apiUrl = 'http://localhost/devices';
$( document ).ready(function() {
// Handler for .ready() called.
jsonGETRequest(apiUrl, jsonExampleData);
});
$(document).on('click', ':button' , function() {
// reference clicked button via: $(this)
$("#UserGuide").empty();
var buttonElementId = $(this).attr('id');
if(buttonElementId.indexOf("btnShowFunc") > -1) {
buttonElementId = buttonElementId.replace("btnShowFunc","");
deviceUID = document.getElementById("mytable").rows[(parseInt(buttonElementId) + 1)].cells[1].innerHTML;
goBack = "firstAPIRequest";
$("#tableInformation tbody").remove();
jsonGETRequest(apiUrl + "/" + deviceUID + "/functions", jsonExampleDataFunctions);
} else if(buttonElementId.indexOf("btnGoBack") > -1 ) {
switch (goBack) {
case "firstAPIRequest":
goBack = "";
$("#tableInformation tbody").remove();
jsonGETRequest(apiUrl, jsonExampleData);
removeGoBackInputDiv();
break;
case "secondAPIRequest":
goBack = "firstAPIRequest";
$("#tableInformation tbody").remove();
jsonGETRequest(apiUrl + "/" + deviceUID + "/functions", jsonExampleDataFunctions);
removeGoBackInputDiv();
break;
}
}else if(buttonElementId.indexOf("btnRunFunc") > -1) {
goBack = "secondAPIRequest";
buttonElementId = buttonElementId.replace("btnRunFunc","");
var functionUID = document.getElementById("mytable").rows[(parseInt(buttonElementId) +1)].cells[2].innerHTML;
var method =$("#slt" + (parseInt(buttonElementId + 1))).children("option").is("selected").text();
$("#tableInformation tbody").remove();
$("#inputDiv").empty();
// /jsonPOST(apiUrl '/functions/' + functionUID )
}
});
function loadDataIntoDeviceGrid(jsonData) {
//$("#tableInformation").addClass("table table-responsive table-bordered");
var tbl=$("<table/>").attr("id","mytable");
$("#tableInformation").append(tbl);
$("#mytable").append("<tr>" + "<th>dal.device.status</th>" + "<th>dal.device.UID</th>"
+ "<th>dal.device.driver</th>" + "<th>service.id</th>" +"<th></th>" + "</tr>");
for(var i=0;i<jsonData.length;i++)
{
var tr = "<tr>";
var td1 = "<td>"+jsonData[i]["dal.device.status"]+"</td>";
var td2 = "<td>"+jsonData[i]["dal.device.UID"]+"</td>";
var td3 = "<td>"+jsonData[i]["dal.device.driver"]+"</td>";
var td4 = "<td>"+jsonData[i]["service.id"]+"</td>";
//#Deprecated var dataList = fillSelectControl(jsonData[i]["objectClass"]); #Deprecated
var btn = "<td>" + "<button id='btnShowFunc"+ i + "' class='btn btn-success btn-lg'>See function</button>" + "</td></tr>";
$("#mytable").append(tr + td1 + td2 + td3 + td4 + btn );
}
$("#mytable").addClass("table table-responsive table-bordered");
}
function loadInformationDeviceGrid() {
$("#UserGuide").addClass("alert alert-info");
$("#UserGuide").html("<h3>Getting devices list:</h3><br/> "+
"Using this request, you can retrieve a list of all the available devices."+
"For every device, among other info, there is the indication of the device unique ID, which" +
"can be used to directly access to the device and the indication of the device driver (ZigBee, Bluetooth, etc.).<br/>If you want see some request response example please visit this <a href='#'>site</a>");
}
function removeGoBackInputDiv() {
$("#inputDiv").empty();
$("#btnGoBack").remove();
}
function loadDataIntoFunctionsGrid(jsonData) {
$("#mytable").append("<tr>" + "<th>function.device.UID</th>"
+ "<th>service.id</th>" + "<th>function.UID</th>" + "<th>operation.names</th>" + "<th></th>" + "</tr>");
var tr, td2, td3, td4, dt2, btn;
for(var i = 0; i < jsonData.length; i++) {
tr = "<tr>";
//#Deprecated td1 = "<td>" + jsonData[i]["CLASS"] + "</td>";
td2 = "<td>" + jsonData[i]["al.function.device.UID"] + "</td>";
td3 = "<td>" + jsonData[i]["service.id"] + "</td>";
td4 = "<td>" + jsonData[i]["dal.function.UID"] + "</td>";
//#Deprecated dt1 = fillSelectControl(jsonData[i]["objectClass"]);
dt2 = fillSelectControl(jsonData[i]["dal.function.operation.names"], i);
btn = "<td>" + "<button id='btnRunFunc"+ i + "' class='btn btn-success btn-lg'>Run</button>" + "</td></tr>";
$("#mytable").append(tr + td2 + td3 + td4 + dt2 + btn );
}
createGoBackButton();
createInputTextParameters();
}
function loadInformationFunctionsGrid() {
$("#UserGuide").addClass("alert alert-info");
$("#UserGuide").html("<h3>Getting device functions:</h3><br/>"
+ "This API is used to retrieve the list of the available functions supported by the device. For"
+ "example a Smart Plug has two functions: one to retrieve the energy consumption and another"
+ "'boolean' function useful to change the status of the smart plug (ON/OFF). Every function"
+ "indicates the id, which can be used to access directly the function and the list of the operation"
+ "that can be invoked on the function.<br/>"
+ "P.S. If he want use a function that want some parameters he must write these into the dedicated textbox. If the API needs more parameters separate these using comma. <br/>"
+ "Example of parametes: <br/> <code>'type':'java.math.BigDecimal'</code><br/> <code>'value':1</code> <br/> etc...");
}
function createGoBackButton() {
var btn = '<button id="btnGoBack" class="btn btn-warning btn-lg">Go Back</button>';
$("#goBack").append(btn);
}
function createInputTextParameters() {
var lbl ="<label>Paramters</label>";
var txt ='<input type="text" class="form-control" name="email">';
$("#inputDiv").addClass("form-group");
$("#inputDiv").append(lbl);
$("#inputDiv").append(txt);
}
function fillSelectControl(obj, id) {
var dataList = "<td><select id='slt"+ id +"'>";
for(var j = 0; j < obj.length; j++)
dataList = dataList + "<option value='" + obj[j] + "'>" + obj[j] + "</option>";
return dataList = dataList + "</select></td>";
}
var json = "";
var goBack = "";
var deviceUID;
function jsonGETRequest(url, dataExample){
$.getJSON(apiUrl, function(data) {
alert(JSON.stringify(data));
this.json = data;
})
.done(function() {
$("#information").addClass("alert alert-success");
$("#information").text("getJSON request succeeded!");
if(goBack == "") {
loadDataIntoDeviceGrid(jsonExampleData);
loadInformationDeviceGrid();
} else if (goBack=="firstAPIRequest") {
loadDataIntoFunctionsGrid(jsonExampleDataFunctions);
loadInformationDeviceGrid();
}
})
.fail(function(jqXHR, textStatus, errorThrown) {
//alert('getJSON request failed! ' + textStatus);
$("#information").addClass("alert alert-danger");
$("#information").text("Impossible get data from API, it will be use example data" + errorThrown);
if(goBack == "") {
loadDataIntoDeviceGrid(jsonExampleData);
loadInformationDeviceGrid();
} else if (goBack=="firstAPIRequest") {
loadDataIntoFunctionsGrid(jsonExampleDataFunctions);
loadInformationFunctionsGrid();
} else if(goBack=="secondAPIRequest") {
}
})
.always(function() { });
}
function jsonPOST(url, method, paramters, dataExample) {
}
var jsonExampleData = [
{
"dal.device.status": 2,
"dal.device.UID": "ZigBee:test123",
"dal.device.driver": "ZigBee",
"service.id": 28,
"objectClass": [
"org.osgi.service.dal.Device"
]
},
{
"dal.device.status": 2,
"dal.device.UID": "ZigBee:test456",
"dal.device.driver": "ZigBee",
"service.id": 29,
"objectClass": [
"org.osgi.service.dal.Device"
]
},
{
"dal.device.status": 2,
"dal.device.UID": "ZigBee:test789",
"dal.device.driver": "ZigBee",
"service.id": 30,
"objectClass": [
"org.osgi.service.dal.Device"
]
}
];
var jsonExampleDataFunctions = [
{
"CLASS": "ismb.pert.jemma.dummydevice.DummyFunction",
"dal.function.device.UID": "ZigBee:test123",
"service.id": 27,
"dal.function.UID": "ZigBee:test123:testButton",
"objectClass": [
"org.osgi.service.dal.Function"
],
"dal.function.operation.names": [
"getData",
"reverse",
"setFalse",
"setTrue"
]
},
{
"CLASS": "ismb.pert.jemma.dummydevice.DummyFunction",
"dal.function.device.UID": "ZigBee:test456",
"service.id": 26,
"dal.function.UID": "ZigBee:test456:testButton",
"objectClass": [
"org.osgi.service.dal.Function"
],
"dal.function.operation.names": [
"getData",
"reverse",
"setFalse",
"setTrue"
]
},
{
"CLASS": "ismb.pert.jemma.dummydevice.DummyFunction",
"dal.function.device.UID": "ZigBee:test789",
"service.id": 25,
"dal.function.UID": "ZigBee:test789:testButton",
"objectClass": [
"org.osgi.service.dal.Function"
],
"dal.function.operation.names": [
"getData",
"reverse",
"setFalse",
"setTrue"
]
}
];
</script>
</body>
</html>

.is() returns a true/false value, it does not continue the jQuery chain, therefor there is no .text() function to call
As DevishOne points out in the comments to get the selected option's text do:
=$("#slt" + (parseInt(buttonElementId + 1))).children("option:selected").text();

Split that in to multiple steps and check for the particular result:
button = $("#slt" + (parseInt(buttonElementId + 1)));
if ( button )
{
childs = button.children("option");
if ( childs .....
Whenever there's no option selected, you are unable to catch that since you refer directly to a method .text() of null.

Related

how do i get the total count of rows in a Json

I have JSON data like this:
[0:{name:"jason",height:"150cm"},
1:{name:"henry",height:"178cm"}]
I'm trying to do a for loop in my function, which is
function DrawTable(output) {
var general = output;
var sb = new StringBuilder();
for (var i = 0; i < *total row in the json*; i++)
sb.append("<td>" + general[0][i]["name"] + "</td>");
sb.append("<td>" + general[0][i]["height"] + "</td>");
}
I don't know the way to do it..
First off: that data isn't JSON.
For the sake of argument, let's pretend it was formatted as such:
[{
"name": "jason",
"height": "150cm"
}, {
"name": "henry",
"height": "178cm"
}]
Which would be valid JSON.
You could then do something more like this:
If using jQuery:
function DrawTable(jsonString) {
var stuff = JSON.parse(jsonString);
var table = createElement('table')
.append(
createElement('thead')
.append(
createElement('tr')
.append(
createElement('th').text('Name'),
createElement('th').text('Height')
)
)
);
var body = createElement('tbody');
stuff.forEach(function(item) {
body
.append(
createElement('tr')
.append(
createElement('td').text(item.name),
createElement('td').text(item.height)
)
);
});
//append body to table and show on page somewhere
}
Or, based on your existing code:
function DrawTable(output) {
var general = JSON.parse(output);
var sb = new StringBuilder();
for (var i = 0; i < general.length; i++) {
sb.append("<td>" + general[i].name + "</td>");
sb.append("<td>" + general[i].height + "</td>");
}
}
If your data happens to be formatted like:
{
0: {name:"jason",height:"150cm"},
1: {name:"henry",height:"178cm"}
}
instead of wrapped in an array. Then looping through Objects.values(yourData) might be what you are looking for:
function DrawTable(objectsData) {
var htmlString = '';
Object.values(objectsData).forEach((object) => {
htmlString += "<td>" + object.name + "</td>";
htmlString += "<td>" + object.height + "</td>";
});
return htmlString;
}

Class Method As Event Handlers Javascript

This is my assignment : " the modif_function, view_function and add_function methods are launched when the corresponding ACTION button is clicked. The corresponding buttons are only visible if the methods have been supplied by the user by a function. "
I've been trying for many hours without success.
class Table {
id_zone = "";
class_table = "";
data = "";
header = "";
class_modif = "";
class_supp = "";
class_vue = "";
icone_modif = "";
icone_supp = "";
icone_vue = "";
constructor(
id_zone = "",
class_table = "",
data = "",
header = "",
class_modif = "",
class_supp = "",
class_vue = "",
icone_modif = "",
icone_supp = "",
icone_vue = ""
) {
this.id_zone = id_zone;
this.class_table = class_table;
this.data = data;
this.header = header;
this.class_modif = class_modif;
this.class_supp = class_supp;
this.class_vue = class_vue;
this.icone_modif = icone_modif;
this.icone_supp = icone_supp;
this.icone_vue = icone_vue;
}
generer = () => {
if (this.id_zone == "") {
throw new Error(
"Pour générer une table, il faut préciser la proprieté id_zone."
);
} else {
var table =
"<table class='" +
this.class_table +
"'>" +
"<tbody>" +
"<tr>" +
"<th>" +
donneesHeader[0] +
"</th>" +
"<th>" +
donneesHeader[1] +
"</th>" +
"<th>" +
donneesHeader[2] +
"</th>" +
"</tr>" +
"<tr></tr>";
$(this.data).each(function () {
table +=
"<tr>" +
"<td>" +
$(this)[0] +
"</td>" +
"<td>" +
$(this)[1] +
"</td>" +
"<td>" +
"<button type='button' class='" +
tableFils.class_vue +
" " +
tableFils.icone_vue +
"' " +
"value=" +
$(this)[0] +
"*" +
$(this)[1] +
"></button>" +
"<button type='button'" +
" class='" +
tableFils.class_modif +
" " +
tableFils.icone_modif +
"' value=" +
$(this)[0] +
"*" +
$(this)[1] +
"></button>" +
"<button type='button' class='" +
tableFils.class_supp +
" " +
tableFils.icone_supp +
"' value=" +
$(this)[0] +
"*" +
$(this)[1] +
">" +
"</button></td>";
});
table += "</tr></tbody></table>";
$("#zoneTable").html(table);
}
};
fonction_modif = () => {};
//What to write here
fonction_supp = () => {};
fonction_vue = () => {};
}
function supprRegion() {
alert("hello world 1");
}
function modifRegion() {
alert("hello world 2");
}
function vueRegion() {
alert("hello world 3");
}
let donnees = [
[1, "Ain"],
[2, "Aisne"],
[3, "Allier"],
[4, "Alpes-de-Haute-Provence"],
[5, "Hautes-Alpes"],
[6, "Alpes-Maritimes"],
[7, "Ardèche"],
[8, "Ardennes"],
[9, "Ariège"],
[10, "Aube"],
[11, "Aude"],
[12, "Aveyron"],
];
let donneesHeader = ["Code", "Nom du département", "Actions"];
let tableFils = new Table();
$(document).ready(function () {
tableFils.id_zone = $("#zoneTable");
tableFils.class_table = "table table-dark table-hover";
tableFils.data = donnees;
tableFils.class_modif = "mod_region";
tableFils.class_supp = "supp_region";
tableFils.class_vue = "vueRegion";
tableFils.icone_modif = "btn btn-info btn-sm fas fa-pencil-alt fa-sm";
tableFils.icone_supp = "btn btn-danger btn-sm fas fa-trash-alt fa-sm";
tableFils.icone_vue = "btn btn-success btn-sm fas fa-eye fa-sm";
tableFils.fonction_modif = modifRegion;
tableFils.fonction_supp = supprRegion;
tableFils.fonction_vue = vueRegion;
tableFils.generer();
});
HTML:
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<!-- CDN CSS de BOOTSTRAP -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<!-- CDN de FONTAWSOME pour les ICONES -->
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />
</head>
<body>
<div id="zoneTable"></div>
<!-------------------------------------
CDN JS pour BOOTSTRAP
--------------------------------------->
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Popper JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
<!-------------------------------------
Nos fichiers JS
--------------------------------------->
<script src="assets/main.js">
</script>
</body>
</html>
So, when there's a click on the modif, supp or vue icons, I get a simple alert.
But I cannot change this : " fonction_modif = modifRegion; "
Delete this:
fonction_modif = () => {};
//What to write here
fonction_supp = () => {};
fonction_vue = () => {};
And add this to properties of the class:
fonction_modif = null;
fonction_supp = null;
fonction_vue = null;
Now, you already can assign a funtion to the properties of the tableFils object, and type the call inside class code, example, as onclick inside a html element of generer function:
this.fonction_modif()

DOM createElement() dynamically with click event to div specific url element

I am attempting to build a 9 divs (cards) dynamically containing information about store branch locations. Each card has a unique URL associated with it that links to each branches specific URL.
This approach, within the function, appends the first (0) URL to all the cards:
$("div").click(function() {
window.location = $(this).find("a").attr("href");
return false;
});
This approach appends the last URL (8) to all the cards:
branch.addEventListener("click", function(e){
e.preventDefault();
window.open(prop.pages_url);
})
Code I'm working with:
function buildLocationList(data) {
for (i = 0; i < 9; i++) {
var currentFeature = data.features[i];
var prop = currentFeature.properties;
//Create Card
var branches = document.getElementById('branches');
var url = branches.appendChild(document.createElement('a');
url.setAttribute('href', prop.pages_url);
)
var branch = branches.appendChild(document.createElement('div'));
branch.className = 'card';
branch.id = "branch-" + i;
branch.url = prop.pages_url;
branch.addEventListener("click", function(e){
e.preventDefault();
window.open(prop.pages_url);
})
//Append Branch Card Details
v
var company = branch.appendChild(document.createElement('h5'));
company.innerHTML = prop.name + '<br />';
var distancePhone = branch.appendChild(document.createElement('p'));
if (prop.distance) {
var roundedDistance = Math.round(prop.distance * 100) / 100;
distancePhone.innerHTML = '<span class="miles">Approx. ' + roundedDistance + ' miles</span>' + '<span class="location-phone">' + prop.phone_number + '</span>';
}
else {
distancePhone.innerHTML = prop.phone_number;
}
var address = branch.appendChild(document.createElement('p'));
if (prop.address_line_2) {
address.innerHTML += prop.address_line_1 + ', ' + prop.address_line_2 + '<br />';
}
else {
address.innerHTML += prop.address_line_1 + '<br />';
};
address.innerHTML += prop.address_city + ', ' + prop.address_state + ' ' +prop.address_postal_code + '</p>';
}
}
I would like the card to be clickable with a redirect to each branch's unique URL.
You're storing the URL on the card element:
branch.url = prop.pages_url
All you need to do in the click handler is access the property:
branch.addEventListener("click", function(e){
e.preventDefault();
window.open(e.currentTarget.url);
})
In the context of the event handler, e.currentTarget is the element to which the handler is attached. If you were interested in which element fired the event, you'd use e.target.
Here's your code snippet modified below. I don't think the links will open on here though due to the sandboxed iframe.
function buildLocationList(data) {
for (i = 0; i < data.features.length; i++) {
var currentFeature = data.features[i];
var prop = currentFeature.properties;
//Create Card
var branches = document.getElementById('branches');
var url = branches.appendChild(document.createElement('a'));
url.setAttribute('href', prop.pages_url);
var branch = branches.appendChild(document.createElement('div'));
branch.className = 'card';
branch.id = "branch-" + i;
branch.url = prop.pages_url;
branch.addEventListener("click", function(e){
e.preventDefault();
console.log(e.currentTarget.url);
window.open(e.currentTarget.url);
})
//Append Branch Card Details
var company = branch.appendChild(document.createElement('h5'));
company.innerHTML = prop.name + '<br />';
var distancePhone = branch.appendChild(document.createElement('p'));
if (prop.distance) {
var roundedDistance = Math.round(prop.distance * 100) / 100;
distancePhone.innerHTML = '<span class="miles">Approx. ' + roundedDistance + ' miles</span>' + '<span class="location-phone">' + prop.phone_number + '</span>';
}
else {
distancePhone.innerHTML = prop.phone_number;
}
var address = branch.appendChild(document.createElement('p'));
if (prop.address_line_2) {
address.innerHTML += prop.address_line_1 + ', ' + prop.address_line_2 + '<br />';
}
else {
address.innerHTML += prop.address_line_1 + '<br />';
};
address.innerHTML += prop.address_city + ', ' + prop.address_state + ' ' +prop.address_postal_code + '</p>';
}
}
buildLocationList({features:[{
properties: {
distance: 100,
name: 'Google',
pages_url: 'https://www.google.com',
phone_number: '123-456-7890',
address_line_1: '1234 Street',
address_city: 'Citytown',
address_state: 'State',
address_postal_code: '12345'
}
},{
properties: {
distance: 200,
name: 'Microsoft',
pages_url: 'https://www.microsoft.com',
phone_number: '123-456-7890',
address_line_1: '1234 Street',
address_city: 'Citytown',
address_state: 'State',
address_postal_code: '12345'
}
}]})
.card {
border: 1px solid #ccc;
padding: 10px;
max-width: 50%;
margin: 10px;
}
<div id="branches"></div>
<div>
w3schools
</div>
<script>
$("div").click(function() {
window.location = $(this).find("a").data("value");
});
</script>

Tablesorter not loaded with dynamically generated content

I am trying to load jQuery tablesorter in a customized infowindow generated by cartodb.js. The idea is that when I click a data point on the map an infowindow will open, loading data dynamically from the database. While the information is loaded correctly and displayed as an ordinary table, the tablesorter is not loaded.
The relevant code:
<script>
$(document).ready(function()
{
$("#bewohner").tablesorter();
}
);
</script>
<script type="infowindow/html" id="infowindow_template">
<div class="infowindow-custom">
x
<div class="cartodb-tooltip-content-wrapper">
<div class="cartodb-tooltip-content" style="padding:2px">
<div id="strasse"></div>
<table id="bewohner" class='tablesorter table table-condensed'>
<thead>
<tr>
<th>
<th>Familienname
<th>Vorname
<th>Beruf</th>
<th>Etage</th>
<th>Tel.</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<div class="cartodb-tooltip-container"></div>
</div>
</script>
....
cartodb.createLayer(map, layerUrl, layerOptions)
.addTo(map)
.on('done', function(layer) {
var infowindow = layer.getSubLayer(0).infowindow
infowindow.set('template', function(data) {
var clickPosLatLng = this.model.get('latlng');
var fields = this.model.get('content').fields;
if (fields && fields[0].type !== 'loading') {
var obj = _.find(fields, function(obj) {
return obj.title == 'strasse_original'
}).value
} // end test of status
$.get("http://******.cartodb.com/api/v1/sql?q=select * from vauban_1 where strasse_original= '" + obj + "' ORDER BY etage, familienname ASC", function(data) {
$('#strasse').append("<h4>" + data.rows[0].strasse_heute + " / " + data.rows[0].strasse_original +"</h4>");
for (var i = 0; i < data.total_rows; i++) {
$('#bewohner tbody').append("<tr><td>" + data.rows[i].zusatz + "<td>" + data.rows[i].familienname + "<td>" + data.rows[i].vorname + "<td>" + data.rows[i].beruf + "<td>" + data.rows[i].etage + "<td>" + data.rows[i].telefon + "</td></tr>");
}
});
return $('#infowindow_template').html();
});
})
It seems that I somehow have to trigger the tablesorter each time the infowindow is loaded, but I don't know how.
I the call for tablesorter was not placed correctly, as it has to be placed inside the function that updates the infowindow. Thus, a working version of the function is:
cartodb.createLayer(map, layerUrl, layerOptions)
.addTo(map)
.on('done', function(layer) {
var infowindow = layer.getSubLayer(0).infowindow
infowindow.set('template', function(data) {
var clickPosLatLng = this.model.get('latlng');
var fields = this.model.get('content').fields;
if (fields && fields[0].type !== 'loading') {
var obj = _.find(fields, function(obj) {
return obj.title == 'strasse_original'
}).value
} // end test of status
$.get("http://******.cartodb.com/api/v1/sql?q=select * from vauban_1 where strasse_original= '" + obj + "' ORDER BY etage, familienname ASC", function(data) {
$('#strasse').append("<h4>" + data.rows[0].strasse_heute + " / " + data.rows[0].strasse_original +"</h4>");
for (var i = 0; i < data.total_rows; i++) {
$('#bewohner tbody').append("<tr><td>" + data.rows[i].zusatz + "<td>" + data.rows[i].familienname + "<td>" + data.rows[i].vorname + "<td>" + data.rows[i].beruf + "<td>" + data.rows[i].etage + "<td>" + data.rows[i].telefon + "</td></tr>");
}
$("#bewohner").tablesorter();
});
return $('#infowindow_template').html();
});
})

Looping through nested array vaues in JSON, appending those values to generated html

EDITED:
I'm (still) having a little trouble getting values from a nested array in JSON and appending them to generated html.
I'm currently using the following JSON (updated):
{
"OuterArray": [
{
"memberId": "01",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "02",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "03",
"key01": "",
"included": "false",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "04",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
}
]
}
And this js:
for (var i = 0; i < outerArray.length; i++) {
if (outerArray[i].included !== "false") {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
// etc.
var nestedArray = outerArray[i]["nestedArray"];
myDiv.innerHTML +=
"<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ "<div class=\"nested-array-stuff\">" // help?
+ "</div>"
+ "</div>"
var nestedArrayStuff = document.getElementsByClassName("nested-array-stuff")[i];
for (var j=0; j<outerArray.length; j++) {
nestedArrayStuff.innerHTML += "<p class=\"keyA\">" + nestedArray[j].keyA + "</p>";
}
}
Note that one of the keys in the outer array has a boolean value which determines whether or not it (the outer array member) is - and its nested array stuff are - included in the page.
So just to reiterate, the goal is:
<div class="outer-array-stuff">
<!-- <snip: some outer array key/values here /> -->
<div class="nested-array-stuff">
<div class="nested-array-stuff">
<p>[e.g., nested array key 1 value]</p>
<p>[e.g., nested array key 2 value]</p>
<p>[etc.]</p>
</div>
</div>
If all the outer array members 'included' are 'true', everything outer & nested loads, but this is not exactly what I want; I need to filter so that only those 'included' !== "false". So now my problem is that despite being inside the if 'included'/else loop, the outer array members stop loading at the first excluded outer array member (actually, the next 'true' outer array member does load, but its nested array stuff doesn't, and then nothing further loads, the entire outer array loop dies.
Any insight as to why this is happening?
Many thanks to dreyescat for the help to this point.
P.S. generally I'm trying to minimize my reliance on jQuery.
Many thanks, svs
You are almost there. Here is your code revised with some comments.
// Generally is not a good practice iterate arrays using for..in
//for (var i in outerArray) {
for (var i = 0; i < outerArray.length; i++) {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
// This should by outerArray array and not jsonData object.
var nestedArray = outerArray[i]["nestedArray"];
myDiv.innerHTML +=
"<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ "<div class=\"nested-array-stuff\">" // help?
+ "</div>"
+ "</div>"
// getElementsByClassName gets a list of elements that have that class.
// I suppose you want to add the elements to the corresponding outer array.
// Let's use the loop index i to get the proper parent element. You could also
// just get the last one.
var nestedArrayStuff = document.getElementsByClassName("nested-array-stuff")[i]; // help?
// Again I recommend you not to use for..in for arrays.
for (var obj in nestedArray) {
nestedArrayStuff.innerHTML += "<p class=\"keyA\">" + nestedArray[obj].keyA + "</p>"; // NOPE
}
}
See demo.
You could also build the entire nested array stuff before adding it to the div element. Then you don't need to query the document to get the nested array stuff element.
for (var i in outerArray) {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
var nestedArray = outerArray[i]["nestedArray"];
var nestedArrayStuff = '<div class=\"nested-array-stuff\">';
for (var obj in nestedArray) {
nestedArrayStuff += "<p class=\"keyA\">" + nestedArray[obj].keyA + "</p>"; // NOPE
}
nestedArrayStuff += '</div>';
myDiv.innerHTML += "<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ nestedArrayStuff
+ "</div>"
+ "</div>";
}
See demo
nestedArray is not a string. your nestedArray array loop should be as follows.
var nestedArray = outerArray[i].nestedArray;
for (var j in nestedArray) {
console.log(nestedArray[j].keyA);
console.log(nestedArray[j].keyB);
}
Here is your complete solution, I used lists to output content. It assumes we have one container:
<div id="mydiv"></div>
Than JS would be:
var myDiv = document.getElementById('mydiv');
var outerArray = [
{
"memberId":"01",
"key01":"",
"key02":"key02 exists, ...",
"included":"true",
"nestedArray":[
{
"keyA":"1",
"keyB":"2"
},
{
"keyA":"3",
"keyB":"4"
}
]
},
{
"memberId":"02",
"key01":"key01 value..",
"included":"true",
"nestedArray":[
{
"keyA":"5",
"keyB":""
},
{
"keyA":"",
"keyB":"8"
}
]
},
{
"memberId":"03",
"key02":"",
"included":"false",
"nestedArray":[
{
"keyA":"",
"keyB":"9"
},
{
"keyA":"",
"keyB":""
}
]
},
{
"memberId":"04",
"key01":"value of key01",
"key02":"key02 value ...",
"included":"true",
"nestedArray":[
{
"keyA":"",
"keyB":"10"
},
{
"keyA":"11",
"keyB":"12"
}
]
}
];
var insertHtml = '';
for (var i = 0; i < outerArray.length; i++) {
if (outerArray[i].included !== "false") {
insertHtml += "<ul class=\"outer-array-stuff\">";
insertHtml += " <li>";
insertHtml += " <p class=\"memberId\">memberId(" + i + "): " + outerArray[i].memberId + "</p>"
insertHtml += " <p class=\"key01\">key01: " + ( ( typeof outerArray[i].key01!='undefined' && outerArray[i].key01 ) ? outerArray[i].key01 : '') + "</p>"
insertHtml += " <p class=\"key02\">key02: " + ( ( typeof outerArray[i].key02!='undefined' && outerArray[i].key02 ) ? outerArray[i].key02 : '') + "</p>"
var nestedArray = outerArray[i]["nestedArray"];
if ( nestedArray.length>0 ) {
insertHtml += " <ul class=\"nested-array-stuff\">"
for (var j=0; j<nestedArray.length; j++) {
insertHtml += "<li class=\"keyA\">keyA(" + j + "): " + nestedArray[j].keyA + "</li>";
insertHtml += "<li class=\"keyB\">keyB(" + j + "): " + nestedArray[j].keyB + "</li>";
};
insertHtml += " </ul>"
};
insertHtml += " </li>";
insertHtml += "</ul>"
}
}
myDiv.innerHTML = insertHtml;

Categories