I created a function for reusing the splice feature for javascript arrays however, after I run it once, it cannot be reused.
var removePerson = function(d, person_id) {
var person_index = d.findIndex(i => i.id == person_id);
d.splice(person_index, 1);
return d;
};
I am not getting console errors. I do not know how to debug it. Here is my JSFiddle.
If you run the example, you will see you can remove any 1 person from the list, but when you try to remove either of the remaining 2, nothing happens (e.g. console errors, console response). Any idea how I can support reuse for my removePerson() function?
Your solution doesn't work because of how your populateList works.
In your populateList, you have a line:
$('#load').empty();
This line empties the table and removes the buttons attached with click event listener.
Then, you add completely new button.delete, which aren't attached with any event listener.
To solve this, you can put your .on() into populateList function.
var populateList = function(d) {
$("#load").empty();
var new_rows;
for(var i = 0; i < d.length; i++) {
new_rows += "<tr>" +
"<td>" + d[i].id + "</td>" +
"<td>" + d[i].name + "</td>" +
"<td>" + d[i].phone + "</td>" +
"<td><button class='delete' data-id='" + d[i].id + "'>delete</button></td>" +
"</tr>";
}
$("#load").append(new_rows);
// delete event
$(".delete").on("click", function() {
var delete_sel = $(this).attr("data-id");
populateList(removePerson(d, delete_sel));
});
};
Here's a working jsFiddle.
Alternatively, you can use solution from this answer (which is a cleaner solution imo).
$("table").on("click",".delete", function() {
var delete_sel = $(this).attr("data-id");
populateList(removePerson(data, delete_sel));
});
More explanation on why his answer works on jQuery documentation (Look at the selector parameter).
Try this code:JSFiddle
or the code snippet:
var removePerson = function(d, person_id) {
var person_index = d.findIndex(i => i.id == person_id);
d.splice(person_index, 1);
return d;
};
var populateList = function(d) {
$("#load").empty();
var new_rows;
for(var i = 0; i < d.length; i++) {
new_rows += "<tr>" +
"<td>" + d[i].id + "</td>" +
"<td>" + d[i].name + "</td>" +
"<td>" + d[i].phone + "</td>" +
"<td><button class='delete' data-id='" + d[i].id + "'>delete</button></td>" +
"</tr>";
}
$("#load").append(new_rows);
};
$(document).ready( function() {
// initial list
var data = [
{
"id": 1001,
"name": "Andy Roy",
"phone": "555-555-5551"
},
{
"id": 1002,
"name": "Bob Dillon",
"phone": "555-555-5552"
},
{
"id": 1003,
"name": "Carl Sagan",
"phone": "555-555-5553"
}
];
//initial populate list
populateList(data);
// delete event
$("table").on("click",".delete", function() {
var delete_sel = $(this).attr("data-id");
populateList(removePerson(data, delete_sel));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border>
<thead>
<tr><th>ID</th><th>Name</th><th>Phone</th></tr>
</thead>
<tbody id="load"></tbody>
</table>
$("table").on("click",".delete", function() {
var delete_sel = $(this).attr("data-id");
populateList(removePerson(data, delete_sel));
});
Related
Is there a way to use callback functions in Python with requests? This is from a here API example im trying to copy using python. This is the request and the function used at the end in the parameters is defined jsoncallback=parseResponse.
If i can replace the functionality of the callback in a other way would be fine too, is it possible to just take the response and do everything thats done in parseRespone?
"https://route.api.here.com/routing/7.2/calculateroute.json?jsonAttributes=1&waypoint0=50.7799,6.08425&waypoint1=50.77988,6.08288&waypoint2=50.78144,6.07794&representation=overview&routeattributes=sc,sm,sh,bb,lg,no,shape&legattributes=li&linkattributes=sh,nl,fc&mode=fastest;car;traffic:enabled&app_id=inCUge3uprAQEtRaruyaZ8&app_code=9Vyk_MElhgPCytA7z3iuPA&jsoncallback=parseResponse"
var parseResponse = function (resp)
{
if (resp.error != undefined)
{
alert (resp.error);
feedbackTxt.innerHTML = resp.error;
return;
}
if (resp.response == undefined)
{
alert (resp.subtype + " " + resp.details);
feedbackTxt.innerHTML = resp.error;
return;
}
//add Routing Release number if not already done
if (releaseRoutingShown == false){
releaseInfoTxt.innerHTML+="<br />HLP Routing: "+resp.response.metaInfo.moduleVersion;
routerMapRelease = resp.response.metaInfo.mapVersion;
mapReleaseTxt.innerHTML = "HLP Routing Service based on "+routerMapRelease+ " map release";
releaseRoutingShown = true;
}
var strip = new H.geo.Strip(),
shape = resp.response.route[0].shape,
i,
l = shape.length;
for(i = 0; i < l; i++)
{
strip.pushLatLngAlt.apply(strip, shape[i].split(',').map(function(item) { return parseFloat(item); }));
}
polyline = new H.map.Polyline(strip,
{
style:
{
lineWidth: 5,
strokeColor: "rgba(18, 65, 145, 0.7)",
lineJoin: "round"
}
});
group.addObject(polyline);
var links = [];
for(var i = 0; i < resp.response.route[0].leg.length; i++)
links = links.concat(resp.response.route[0].leg[i].link);
pdeManager.setLinks(links);
pdeManager.setBoundingBoxContainer(group);
pdeManager.setOnTileLoadingFinished(pdeManagerFinished);
pdeManager.start();
}
function pdeManagerFinished(finishedRequests)
{
feedbackTxt.innerHTML = "Done. Requested " + finishedRequests + " PDE tiles for " + numLinksMatched + " route links. ";
var resultHTML = '<table class="pde_table" cellpadding="2" cellspacing="0" border="1" width="90%">' +
'<thead>' +
'<tr>' +
'<th width="80%">Sign</th>' +
'<th width="20%">#</th>' +
'</tr>' +
'</thead>' +
'<tbody id="maps_table_body">';
for(var sign in signs)
{
resultHTML += "<tr>" + "<td>" + sign + "</td>" + "<td>" + signs[sign] + "</td>" + "</tr>";
}
resultHTML += "</tbody>" + "</table>";
document.getElementById("resultArea").innerHTML = resultHTML;
document.getElementById("resultArea").style.display = "block";
map.addObject(group);
map.setViewBounds(group.getBounds());
}
You don't need to use any callback (since there's nothing that would execute it anyway); elide the parameter and call response.json().
The below code does raise
Unauthorized. The request is not from an authorized source.
so you may need some additional headers or such (possibly an Origin header if the credentials are matched to a site address).
import requests
resp = requests.get(
url="https://route.api.here.com/routing/7.2/calculateroute.json",
params={
"jsonAttributes": "1",
"waypoint0": "50.7799,6.08425",
"waypoint1": "50.77988,6.08288",
"waypoint2": "50.78144,6.07794",
"representation": "overview",
"routeattributes": "sc,sm,sh,bb,lg,no,shape",
"legattributes": "li",
"linkattributes": "sh,nl,fc",
"mode": "fastest;car;traffic:enabled",
"app_id": "inCUge3uprAQEtRaruyaZ8",
"app_code": "9Vyk_MElhgPCytA7z3iuPA",
},
)
# Uncomment this to see the actual error.
# print(resp.content)
resp.raise_for_status()
print(resp.json())
I am unsure why my getCereal variable id using the find("td:first").html() is not working. I have been able to create my table, however my click event will not work. I am stumped. Any input will be greatly appreciated.
<div id="cer"></div>
<script type="text/javascript">
// jQuery onClick event
// the click function MUST BE USED CANNOT BE ALTERED OR REMOVED
$(function () {
$("table tr").click(function (event) {
function getCereal(id) {
for (var cerId = 0; cerId < cereals.length; cerId++){
if(cereals[cerId].id == id){
alert(cereals[cerId].id +" " + cereals[cerId].name + " " +
cereals[cerId].like);
break;
}
}
}
var id = $(this).find("td:first").html();
getCereal(id)
// This creates an cereal constructor object
function cereal(id, name, like) {
this.id = id;
this.name = name;
this.like = like;
}
// This creates 5 new objects with cereal information.
const cereals = [
new cereal(1, 'Captain Crunch', 'Yes'),
new cereal(2, 'Frosted Wheats ', 'Yes'),
new cereal(3, 'Shredded Wheat', 'No'),
new cereal(4, 'Trix', 'No'),
new cereal(5, 'Count Chocula', 'No'),
];
var output = "<h1>Cereal Listing</h1><table><thead>"+"<tr>"+"<th>"+"Id"+"</th>"+"<th>"+"Cereal Name"+"</th>"+"<th>"+"Like?"+"</th>"+"</tr>"+"</thead>"
for (var x = 0; x < cereals.length; x++) {
output +='<tr>' + "<td>" + cereals[x].id + "</td>" +"<td>" + cereals[x].name + "</td>" + "<td>" + cereals[x].like +"</td>" + '</a>' + "</tr>";
}
output += "</table>";
document.getElementById('cer').innerHTML = output;
})
});
</script>
It's really unclear what the goal is here. Maybe this will help, consider the following code.
$(function() {
function cereal(id, name, like) {
this.id = id;
this.name = name;
this.like = like;
}
const cereals = [
new cereal(1, 'Captain Crunch', 'Yes'),
new cereal(2, 'Frosted Wheats ', 'Yes'),
new cereal(3, 'Shredded Wheat', 'No'),
new cereal(4, 'Trix', 'No'),
new cereal(5, 'Count Chocula', 'No'),
];
var output = "<h1>Cereal Listing</h1>";
output += "<table class='cereal-table'><thead>";
output += "<tr><th>Id</th><th>Cereal Name</th><th>Like?</th></tr>";
output += "</thead><tbody>";
$.each(cereals, function(k, c) {
var row = $("<tr>", {
"data-c-id": k
});
$("<td>").html(c.id).appendTo(row);
$("<td>").html(c.name).appendTo(row);
$("<td>").html(c.like).appendTo(row);
output += row.prop("outerHTML");
});
output += "</tbody></table>";
$("#cer").html(output);
$(".cereal-table").on("click", "tr", function(e) {
var cId = parseInt($(this).data("c-id"));
console.log("Row C-ID: " + cId);
var data = "";
data += "ID: " + cereals[cId].id;
data += ", Name: " + cereals[cId].name;
data += ", Like: " + cereals[cId].like
alert(data);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="cer"></div>
Since jQuery is a JavaScript Framework, you can mix and match both, yet I try to remain in one or the other. This is all in jQuery.
The function creates an Object. You have 5 objects in an Array and we're going to iterate the Array using $.each(). This is a functioned designed for this. See:
jQuery.each()
Each Object has parameters we can call and insert into the Table Cell elements <td>. jQuery give us the ability to quickly create elements as jQuery Objects: $("<td>").
Since the goal appears to be to create an output string of HTML text, we can convert all the jQuery Objects we've create into HTML by asking for the outerHTML property.
The result of running the code is:
<h1>Cereal Listing</h1><table><thead><tr><th>Id</th><th>Cereal Name</th><th>Like?</th></tr></thead><tbody><tr><td>1</td><td>Captain Crunch</td><td>Yes</td></tr><tr><td>2</td><td>Frosted Wheats </td><td>Yes</td></tr><tr><td>3</td><td>Shredded Wheat</td><td>No</td></tr><tr><td>4</td><td>Trix</td><td>No</td></tr><tr><td>5</td><td>Count Chocula</td><td>No</td></tr></tbody></table>
Once the table is constructed and outputted, you can bind a click event to the Row with .on() or .click(). I advise the .on() since it more tolerate of dynamic content.
We bind the click event to each row and then collect the data from the row and create an alert.
Hope this helps.
refreshFileList = function() {
$("#filedetails tr").remove();
for (i = 0, j = fileDetails.length; i < j; ++i) {
$("#filedetails").append("<tr data-filesize='" + fileDetails[i].SIZE + "' data-filename='" + fileDetails[i].KEY + "'><td><strong>" + fileDetails[i].FILENAME + "</strong></td><td class='nodesize'>" + fileDetails[i].SIZE + " MB</td><td>" + fileDetails[i].EXT + "</td>" + fileDetails[i].TAG + "</tr>");
}
},
fileDelete = function(e) {
e.preventDefault();
var parentRow = jQuery(this).closest('tr')
, fileName = fileDetails[i].KEY
, fileSize = fileDetails[i].SIZE;
ajaxFileDelete(fileName, parentRow, fileSize);
},
Into the fileDelete function I don't want to use data-filename and data-filesize but when I am going to use fileName = fileDetails[i].KEY or fileSize = fileDetails[i].SIZE its always deleting the first value of the array instead of specific value but with data-attributes it working as expected.
Add i to the <tr> as a data attribute.
refreshFileList = function() {
$("#filedetails tr").remove();
for (var i = 0, j = fileDetails.length; i < j; ++i) {
$("#filedetails").append("<tr data-index='" + i + "'><td><strong>" + fileDetails[i].FILENAME + "</strong></td><td class='nodesize'>" + fileDetails[i].SIZE + " MB</td><td>" + fileDetails[i].EXT + "</td>" + fileDetails[i].TAG + "</tr>");
}
},
fileDelete = function(e) {
e.preventDefault();
var parentRow = jQuery(this).closest('tr')
, i = parentRow.data('index')
, fileName = fileDetails[i].KEY
, fileSize = fileDetails[i].SIZE;
ajaxFileDelete(fileName, parentRow, fileSize);
},
I'm currently using the jQuery get method to read a table in another page which has a list with files to download and links to others similar webpages.
$.get(filename_page2, function(response, status){
var data = $("<div>" + response + "</div>");
var target_element = data.find(target_element_type_page2 + '#' + target_element_id_page2)[0];
var container = document.getElementById(element_change_content_page1);
if (typeof target_element !== "undefined"){
var rows = target_element.rows;
for (var i = 1, n = rows.length; i < n; i++) {
var table = rows[i].cells[1].getElementsByTagName("TABLE")[0];
var isFolder = table.getAttribute("CType") == "Folder";
var elem = table.rows[0].cells[0];
var text = elem.innerText || elem.textContent;
var link = elem.getElementsByTagName("A")[0].getAttribute("href");
if (!isFolder) {
container.innerHTML += "<li class=\"mainfolderfile\">" + "<a class=\"filelink\" href=\"" + link + "\">" + text + "</a></li>";
} else {
container.innerHTML += "<li class=\"folderlist\">" + "<a class=\"folderlink\" onclick=\"open_submenu(this)\" href=\"#\">" + text + "</a><ul></ul></li>";
var elem_page1 = container.getElementsByTagName("li");
var container_page1 = elem_page1[elem_page1.length - 1].getElementsByTagName("ul")[0];
create_subfolder(container_page1, link);
}
}
} else {
container.innerHTML += "<li class=\"mainfolderfile\">" + "<a class=\"filelink\" href=\"" + "#" + "\">" + "Error..." + "</a></li>";
}
}, page2_datatype);
This is working fine, and all the folders and files are being listed. But when I try to do the same thing with the folders (calling the create_subfolder function) and create sublists with their subfolders and files, I'm getting a weird behavior.
function create_subfolder(container2, link1) {
$.get(link1, function(response, status){
var data = $("<div>" + response + "</div>");
var target_element = data.find("table" + "#" + "onetidDoclibViewTbl0")[0];
if (typeof target_element !== "undefined"){
var rows = target_element.rows;
for (var i = 1, n = rows.length; i < n; i++) {
var table = rows[i].cells[1].getElementsByTagName("TABLE")[0];
var elem = table.rows[0].cells[0];
var text = elem.innerText || elem.textContent;
var link2 = elem.getElementsByTagName("A")[0].getAttribute("href");
//nothing is changed in the webpage. The modifications in the html don't appear
container2.innerHTML += "<li>" + text + "</li>";
}
}
alert(container2.innerHTML); // Print the html with all the modifications
}, "html");
}
The second get(), inside the create_subfolder() function are not changing anything in the webpage, so no sublist is created. But, when I call the alert() function at the end of the get() function, it prints the code with all the modifications it should have made in the html at the second get callback. I believe the problem is related with the asynchronous behavior of the get function but I don't know exactly why. Any guess?
I'm working on a project where I have a json file that contains a list of companies, their phone numbers, addresses, etc. Currently I have it loading a list into a table with no real order. It works to list the companies, and displays their location on a map with a pin. I have it limited to display on 10 as its almost 5000 entries - at least until I get a sort/search function working. The issue I'm having is that the only way I can get the map to load and the pins to work is if I include them as part of the $.getJSON. If I create functions to load outside of this, I'm unable to call the information out of the JSON any longer, but likewise am not able to include the functions inside as they don't work.
Here is the code I'm working with:
$.getJSON('MapDatabroke.json', function (data) {
var output = "<table class = sample>";
tableHeadings = "<thead>" +
"<tr>" +
"<th></th>" +
"<th><u>Name:</u></th>" +
"<th><u>Address:</u></th>" +
"<th><u>City:</u></th>" +
"<th><u>State:</u></th>" +
"<th><u>Phone Number:</u></th>" +
"<th><u>PO:</u></th>" +
"<th><u>Towing:</u></th>" +
"<th><u>Tires:</u></th>" +
"<th><u>MC:</u></th>" +
"<th><u>RoadSvc:</u></th>" +
"<th><u>Notes:</u></th>" +
"</tr>" +
"</thead>";
output += tableHeadings;
for (var i = 0; i < length; i++) {
var lat = data[i]["Lat"];
var lon = data[i]["Lon"];
var dist = 41.5;
if (lat < dist) {
output += "<tr>";
if (data[i]["Website"] == '---') {
output += "<td>" + ' ' + "</td>";
} else {
output += "<td>W</td>";
}
output += "<td>" + i + data[i]["Business Name"] + "</td>" + "<td>" + data[i]["Address"] + "</td>" + "<td>" + data[i]["City"] + "</td>" + "<td>" + data[i]["StateListing"] + "</td>" + "<td>" + data[i]["Phone"] + "</td>";
if (data[i]["PO"] == 'FALSE') {
output += "<td>" + data[i]["Notes"] + "</td>";
output += "</tr>";
}
}
output += "</table>";
document.getElementById("placeholder").innerHTML = output;
});
function GetMap() {
var map = null;
var pinInfobox = null;
// Initialize the map
var map = new Microsoft.Maps.Map(document.getElementById("mapDiv"), {
credentials: "AqtpRoPv2sfmrgf9VhyvDV8hCOVGPJi0-9heYhxmB-WU24OzpTIOIR0-C4fD0jc-",
center: new Microsoft.Maps.Location(45.5, -122.5),
zoom: 7
});
// Creates a collection to store multiple pins
var pins = new Microsoft.Maps.EntityCollection();
// Create Pins
for (var i = 0; i < length; i++) {
//pushpin location
var position = new Microsoft.Maps.Location(data[i]["Lat"], data[i]["Lon"]);
//Create the pin
var pin = new Microsoft.Maps.Pushpin(position);
//add pin to collection
pins.push(pin);
}
//add pins
map.entities.push(pins);
//create the info box
pinInfobox = new Microsoft.Maps.Infobox(pin.getLocation(), {
title: 'My Pushpin',
description: 'It works!',
visible: false,
offset: new Microsoft.Maps.Point(0, 15)
});
//add click event
Microsoft.Maps.Events.addHandler(pin, 'click', displayInfobox);
//hide box on map move
Microsoft.Maps.Events.addHandler(map, 'viewchange', hideInfobox);
}
function displayInfobox(e) {
pinInfobox.setOptions({
visible: true
});
}
function hideInfobox(e) {
pinInfobox.setOptions({
visible: false
});
}
The way it shows above, doesn't work. It will load the map, but will not load the information as well as give me a error of data not defined w/in the create pin. Any ideas how to assign the information so that way I can use it in functions later on?
Try asigning a variable to the $.getJSON (var JSONData = $.getJSON...). In that way you can have the data outside the query.
On the other hand, you could also use $.ajax to do the query. It's just another way of doing things, a little more "tweakable". This example have some error handlers that will help you identify the problem.
Something like this:
var JSONdata = $.ajax({
type : "GET",
url : "MapDatabroke.json",
cache : false,
dataType: "json", // Use when retrieving
success: function(data) {
// do something here after retrieving the "data".
},
error: function (xhr, ajaxOptions, thrownError) {
//Add these parameters to display the required response
console.log( 'xhr.status: ' + xhr.status );
console.log( 'thrownError: ' + thrownError );
}
});
Also, check your json data (http://jsonlint.com/). Sometimes there is a comma where should not, or a missing bracket.