my first ever question pretty sure I'm being a bit daft here, but am a beginner and would appreciate your help.
Im working on a webpage where there is a html table listing several columns of data.
When the page loads it runs a jquery script which counts the different types of "incidents" and plots them in another table which then another jquery script populates a graph.
I have a third script (javascript) which after a button is clicked, runs an if loop, which looks at the data in the first column and if it does not match the criteria then the row is deleted.
So far so good, the issue is that I want the script which populates the table for the graph to run again, but Im not sure how to call it from my if loop.
Ive put the two scripts below, basically I want to call the 1st script in the second script.
$(function () {
var NumFireAlarms = $("#incidents tr:contains('Fire Alarm')");
$("#result").html(NumFireAlarms.length + " Fire Alarm");
var firealarms = NumFireAlarms.length;
document.getElementById("no_of_incident_type").rows[1].cells[1].innerHTML = firealarms
var NumLockout = $("#incidents tr:contains('Lockout Out of Office Hours')");
$("#result").html(NumLockout.length + " Lockout Out of Office Hours");
var lockouts = NumLockout.length;
document.getElementById("no_of_incident_type").rows[2].cells[1].innerHTML = lockouts
var NumLockoutDayTime = $("#incidents tr:contains('Lockout Day Time')");
$("#result").html(NumLockout.length + " Lockout Day Time");
var lockoutsDayTime = NumLockoutDayTime.length;
document.getElementById("no_of_incident_type").rows[3].cells[1].innerHTML = lockoutsDayTime
var NumSensitiveIncident = $("#incidents tr:contains('Sensitive Incident')");
$("#result").html(NumSensitiveIncident.length + " Sensitive Incident");
var SensitiveIncident = NumSensitiveIncident.length;
document.getElementById("no_of_incident_type").rows[4].cells[1].innerHTML = SensitiveIncident
});
function filterForGraph() {
var incident_category = document.getElementById("Incident_Category").value;
var start_date = document.getElementById("start_date").value;
var end_date = document.getElementById("end_date").value;
var staff_type = document.getElementById("Job_Title").value;
var i;
var count = 0;
var table_length = document.getElementById("incidents").rows;
var TL = table_length.length;
for (i = TL - 1; i >= 1; i--)
{
var category_column = document.getElementById("incidents").rows[i].cells.item(0).innerHTML;
var date_column = document.getElementById("incidents").rows[i].cells.item(1).innerHTML;
var staff_colunm = document.getElementById("incidents").rows[i].cells.item(8).innerHTML;
if (category_column === incident_category)
{
alert("yay")
count++
}
else if (category_column !== incident_category)
{
alert("boo")
document.getElementById("incidents").deleteRow(i);
//CALL FIRST SCRIPT HERE??
}
}
}
I removed a few bits of code that did not seem to do anything, but I'm sure you can put them back. I think you might want something like this:
function updateTable(){
var elResult = document.getElementById("result");
var elNumIncidentType = document.getElementById("no_of_incident_type");
var firealarms: document.querySelectorAll("#incidents tr:contains('Fire Alarm')").length;
var lockouts: document.querySelectorAll("#incidents tr:contains('Lockout Out of Office Hours')").length;
var lockoutsDayTime: document.querySelectorAll("#incidents tr:contains('Lockout Day Time')").length;
var sensitiveIncident: document.querySelectorAll("#incidents tr:contains('Sensitive Incident')").length;
elResult.innerHTML = "";
elResult.innerHTML += "<div>" + firealarms + " Fire Alarm</div>";
elResult.innerHTML += "<div>" + lockouts + " Lockout Out of Office Hours</div>";
elResult.innerHTML += "<div>" + lockoutsDayTime + " Lockout Day Time</div>";
elResult.innerHTML += "<div>" + sensitiveIncident + " Sensitive Incident</div>";
elNumIncidentType.rows[1].cells[1].innerHTML = firealarms;
elNumIncidentType.rows[2].cells[1].innerHTML = lockouts;
elNumIncidentType.rows[3].cells[1].innerHTML = lockoutsDayTime;
elNumIncidentType.rows[4].cells[1].innerHTML = sensitiveIncident;
}
function filterForGraph() {
var elIncidents = document.getElementById("incidents");
var incident_category = document.getElementById("Incident_Category").value;
var table_length = document.getElementById("incidents").rows.length;
for (var i = table_length - 1; i >= 1; i--) {
var currentIncident = elIncidents.rows[i].cells;
var category_column = currentIncident.item(0).innerHTML;
if (category_column != incident_category) { elIncidents.deleteRow(i); }
}
updateTable();
}
$(function(){ updateTable(); });
Hi JonSG tried your code and it didnt work not sure why, but it gave me some ideas to work with and I think Ive cracked it
function Populate_Incident_No_Table() {
//previously function called updateTable
$(function () {
var NumFireAlarms = $("#incidents tr:contains('Fire Alarm')").length;
document.getElementById("no_of_incident_type").rows[1].cells[1].innerHTML = NumFireAlarms
var NumLockout = $("#incidents tr:contains('Lockout Out of Office Hours')").length;
document.getElementById("no_of_incident_type").rows[2].cells[1].innerHTML = NumLockout
var NumLockoutDayTime = $("#incidents tr:contains('Lockout Day Time')").length;
document.getElementById("no_of_incident_type").rows[3].cells[1].innerHTML = NumLockoutDayTime
var NumSensitiveIncident = $("#incidents tr:contains('Sensitive Incident')").length;
document.getElementById("no_of_incident_type").rows[4].cells[1].innerHTML = NumSensitiveIncident
});
}
function filterForGraph() {
var incident_category = document.getElementById("Incident_Category").value;
var i;
var TL = document.getElementById("incidents").rows.length;
for (i = TL - 1; i >= 1; i--)
{
var category_column = document.getElementById("incidents").rows[i].cells.item(0).innerHTML;
if (category_column !== incident_category)
{
document.getElementById("incidents").deleteRow(i);
}
}
Populate_Incident_No_Table();
drawGraph();
}
I think the issue was how I was trying to call the functions. So what I've done to achieve what I wanted (please excuse any bad terminology / phrasing).
First I tried to name the function $(function updateTable(){ this did not work when I then tried to call the function like this updateTable();
Second thing I tried was putting the updateTable() function "inside" a function and call that function. This has worked for me I dont know why.
Thanks for your help without it I would not have thought to try what I did
I've been stuck for a few days now on this. I can get my albums to write to the console but I can't figure out how to get them to write into an array. The code works so when I click "Show Albums" button, it returns nothing other than [Object, object]. Can anyone help me figure out how to write the new albums to the array so it displays properly? Thanks in advance.
(function() {
var name = document.getElementById("name");
var year = document.getElementById("year");
var showbutton = document.getElementById("showlist");
var submitbutton = document.getElementById("submit");
var validate = document.getElementById("validate");
var albumlist = [];
var albums = function album(name, year) {
this.name = name;
this.year = year;
this.album = function() {
return ((this.name + ", " + this.year));
};
}
albums.prototype.genre = "rock";
var album1 = new albums("album1", "1999");
var album2 = new albums("album2", "2000");
var album3 = new albums("album3", "2001");
var album4 = new albums("album4", "2002");
var album5 = new albums("album5", "2003");
albumlist.push(album1, album2, album3, album4, album5);
showbutton.onclick = function() {
for (var i = 0; i < albumlist.length; i++) {
console.log(albumlist[i]);
}
document.getElementById("myalbums").innerHTML = albumlist.sort() + "<br/>";
}
document.getElementById("myalbums").innerHTML = albumlist.sort() + "<br/>";
Take a look at what this line does. This takes an array, which is an object with many functions, keys, etc, and tries to plot in on the page.
It will not be possible, since javascript doesn't know how to turn that array into a string.
For you to do that, you have to first create the string you want and than plot it on the page.
You need to iterate through the items and generate a string, for example:
var names = "";
for(var i = 0; i < albumlist.length; i++){
names += albumlist[i].name + ' ';
}
and then replace it on the html:
document.getElementById("myalbums").innerHTML = names + "<br/>";
I have an object "Driver" defined at the beginning of my script as such:
function Driver(draw, name) {
this.draw = draw;
this.name = name;
}
I'm using this bit of JQuery to create new drivers:
var main = function () {
// add driver to table
$('#button').click(function ( ) {
var name = $('input[name=name]').val();
var draw = $('input[name=draw]').val();
var draw2 = "#"+draw;
var name2 = "driver"+draw
console.log(draw2);
console.log(name2);
if($(name2).text().length > 0){
alert("That number has already been selected");}
else{$(name2).text(name);
var name2 = new Driver(draw, name);}
});
That part is working great. However, when I try later on to access those drivers, the console returns that it is undefined:
$('.print').click(function ( ) {
for(var i=1; i<60; i++){
var driverList = "driver"+i;
if($(driverList.draw>0)){
console.log(driverList);
console.log(driverList.name);
}
If you're interested, I've uploaded the entire project I'm working on to this site:
http://precisioncomputerservices.com/slideways/index.html
Basically, the bottom bit of code is just to try to see if I'm accessing the drivers in the correct manner (which, I'm obviously not). Once I know how to access them, I'm going to save them to a file to be used on a different page.
Also a problem is the If Statement in the last bit of code. I'm trying to get it to print only drivers that have actually been inputed into the form. I have a space for 60 drivers, but not all of them will be used, and the ones that are used won't be consecutive.
Thanks for helping out the new guy.
You can't use a variable to refer to a variable as you have done.
In your case one option is to use an key/value based object like
var drivers = {};
var main = function () {
// add driver to table
$('#button').click(function () {
var name = $('input[name=name]').val();
var draw = $('input[name=draw]').val();
var draw2 = "#" + draw;
var name2 = "driver" + draw
console.log(draw2);
console.log(name2);
if ($(name2).text().length > 0) {
alert("That number has already been selected");
} else {
$(name2).text(name);
drivers[name2] = new Driver(draw, name);
}
});
$('.print').click(function () {
for (var i = 1; i < 60; i++) {
var name2 = "driver" + i;
var driver = drivers[name2];
if (driver.draw > 0) {
console.log(driver);
console.log(driver.name);
}
I am trying to create a helper file that will return the top track(s) of any artist's related artists. All I want to do use 1 artist URI to surface their related artists' name, popularity, and top track. And I want to separate out the top track functionality into a separate file that I can call whenever.
But, I can't seem to figure out how to properly return the top track of the related artists.
In my "get-toptrack.js" file:
require([
'$api/models',
'$api/toplists#Toplist'
], function(models, Toplist) {
'use strict';
var doGetTopTrack = function(uri, num) {
var artistURI = uri;
var artist = models.Artist.fromURI(artistURI);
var artistTopList = Toplist.forArtist(artist);
artistTopList.tracks.snapshot().done(function(snapshot){
snapshot.loadAll('name').done(function(tracks) {
var i, num_toptracks;
num_toptracks = num;
for(i = 0; i < num_toptracks; i++){
console.log("top track: " + tracks[i].name);
// WHERE DO I RETURN THE TOP TRACKS??
}
});
});
};
exports.doGetTopTrack = doGetTopTrack;
});
In my "artist.js" file":
require([
'$api/models',
'scripts/get-toptrack'
], function(models, getTopTrack) {
'use strict';
var showRelated = function() {
var artist_properties = ['name', 'popularity','related', 'uri'];
models.Artist
.fromURI('spotify:artist:11FY888Qctoy6YueCpFkXT')
.load(artist_properties)
.done(function(artist){
artist.related.snapshot().done(function(snapshot){
snapshot.loadAll('name').done(function(artists) {
for(var i = 0; i < artists.length; i++){
var u, p, n, t, listItem;
// store artist details
p = artists[i].popularity;
n = artists[i].name;
u = artists[i].uri;
// am I missing something here?
t = getTopTrack.doGetTopTrack(u, 1);
listItem = document.createElement("li");
listItem.innerHTML = "<strong>Name</strong>: " + n.decodeForText() + " | <strong>Popularity: </strong> " + p + " | <strong>Top Track: </strong>" + t;
// undefined name
$('#artistsContainer').append(listItem);
}
});
});
});
};
exports.showArtists = showArtists;
});
And in the 'main.js' file, I call the artists function to begin.
require([
'$api/models',
'scripts/artist'
], function(models, initArtist) {
'use strict';
initArtist.showRelated();
});
can't comment on the multiple .js files as I haven't yet refactored my app into multiple files.
As far as returning goes, you're working in an asynchronous application, so you can't. You have to use a callback, or a Spotify Promise might make your api more congruous with Spotify's. Look at the documentation for Promise.each().
Here is an implementation of the callback method. Changed a few things to make it easier for me to test. Made life a bit easier to pass the artist in instead. Also, there is no guarantee of the order they will come out since the second artist's toplist could come back faster than the first. You'll need to add more code if you want to keep order.
function doGetTopTrack(artist, num, callback) {
var artistTopList = Toplist.forArtist(artist);
artistTopList.tracks.snapshot(0,num).done(function (snapshot) { //only get the number of tracks we need
snapshot.loadAll('name').done(function (tracks) {
var i, num_toptracks;
num_toptracks = num; //this probably should be minimum of num and tracks.length
for (i = 0; i < num_toptracks; i++) {
callback(artist, tracks[i]);
}
});
});
};
function showRelated() {
var artist_properties = ['name', 'popularity', 'related', 'uri'];
models.Artist
.fromURI('spotify:artist:11FY888Qctoy6YueCpFkXT')
.load(artist_properties)
.done(function (artist) {
artist.related.snapshot().done(function (snapshot) {
snapshot.loadAll('name').done(function (artists) {
for (var i = 0; i < artists.length; i++) {
// am I missing something here?
doGetTopTrack(artists[i], 1, function (artist, toptrack) {
console.log("top track: " + toptrack.name);
var p = artist.popularity;
var n = artist.name;
var u = artist.uri;
//listItem = document.createElement("li");
console.log("<strong>Name</strong>: " + n.decodeForText() + " | <strong>Popularity: </strong> " + p + " | <strong>Top Track: </strong>" + toptrack.name);
//// undefined name
//$('#artistsContainer').append(listItem);
});
}
});
});
});
};
showRelated();
edit #3
in the interest of getting better help (THANK YOU for the patience) i want to combine these two scripts:
SCRIPT 1:
//get csv file and set up array
d3.csv('../mapdata/mapdatatest.csv', function (csv) {
var rid = [],
lat = [],
lon = [],
pinclr = [],
name = [],
str = [],
citystzip = [],
phone = [],
lastinspturl = [],
lastinspctdt = [];
csv.map(function (d) {
rid.push(d.rid).toString();
lat.push(d.lat).toString();
lon.push(d.lon).toString();
pinclr.push(d.pinclr).toString();
name.push(d.name).toString();
str.push(d.str).toString();
citystzip.push(d.citystzip).toString();
phone.push(d.phone).toString();
lastinspturl.push(d.lastinspturl).toString();
lastinspctdt.push(d.lastinspctdt).toString();
for (i = 0; i < rid.length; i++) {
var points = ('"' + lat[i] + "," + lon[i] + '"');
}
});
});
SCRIPT 2:
deCarta.Core.Configuration.clientName = Config.clientName;
deCarta.Core.Configuration.clientPassword = Config.clientPassword;
var center = new deCarta.Core.Position(Config.position);
var pinOverlay = new deCarta.Core.MapOverlay({
name: "Pins"
});
window.map = new deCarta.Core.Map({
id: "mapContainer",
autoResize: true,
zoom: 11,
center: center,
onReady: function (map) {
map.addLayer(pinOverlay);
postPins();
}
});
function postPins() {
var points = {
"points": [
//i have typed in these values for testing purposes only
"47.15211, -97.570039",
"48.625045, -101.375369",
"48.39679, -101.052669"]
};
for (var i = 0; i < points.points.length;) {
pos = new deCarta.Core.Position(points.points[i]);
pin = pin = new deCarta.Core.Pin({
position: center.clone(),
text: 'pin: ' + (points.points[i]),
position: pos
// imageSrc: 'img/pin.png'
});
pinOverlay.addObject(pin);
i++;
}
var view = new deCarta.Core.BoundingBox(points.points);
var centerAndZoom = view.getIdealCenterAndZoom(window.map);
map.zoomTo(centerAndZoom.zoom);
map.centerOn(centerAndZoom.center);
}
THE RESULT I AM TRYING TO ACHIEVE:
instead of using typed in values as i'm doing in SCRIPT 2 -- i want those values to be fed in from SCRIPT 1.
so
var points = {
"points": [
//i have typed in these values for testing purposes only
"47.15211, -97.570039",
"48.625045, -101.375369",
"48.39679, -101.052669"]
};
needs to be
var points = {
"points": [
THE "point" VALUES FROM THE SCRIPT 1 loop]
};
i get the concept, can't seem to get the syntax right...tried all the suggestions, the push();, read a lot of articles, samples...i needed this 10 hours ago, any assistance will be greatly appreciated. i'd vote you up if i had enough rep yet :) thank you, thank you, thank you.
I'm having a hard time understanding your questions. Does this help at all:
var points = {
"points": [
"47.15211, -97.570039",
"48.625045, -101.375369",
"48.39679, -101.052669"
]
};
console.log(points.points);
var array = points.points;
var array_len = array.length;
for(var i = 0; i < array_len; ++i)
{
var str = array[i];
console.log(str);
}
--output:--
[ '47.15211, -97.570039',
'48.625045, -101.375369',
'48.39679, -101.052669' ]
47.15211, -97.570039
48.625045, -101.375369
48.39679, -101.052669
======
i built on another page:
That is troublesome. Are you aware that the web is stateless? That means that once a user leaves a page, no data is saved on the user's computer. There are some ways around that: you can save small bits of information in cookies, or a page can send the data to a server side script, and then the server side script can save the data in a file or a database.
On the other hand, if by "on another page" you mean another javascript file, then start simpler. Combine both javascript files into one file and get that to work, e.g.:
func1(a, b) = {
....
return results;
}
func2(x, y, z) = {
info = func1(x, y) + z
//do something with info
}
Then it's a just a matter of putting func1 and func2 into separate files and including both of them in an html page:
<script type='text/javascript' src='js2.js'></script>
<script type='text/javascript' src='js1.js'></script>
Just make sure you get the order right: if function in js1.js calls a function defined in js2.js, then js2.js needs to be included first.
====
html.html
<html>
<head>
<title>Test</title>
<script type='text/javascript' src='js2.js'></script>
<script type='text/javascript' src='js.js'></script>
<style type='text/css'>
.colorText {
color: blue;
}
.surprise {
background: red;
}
</style>
</head>
<body>
<div id="show_results" class="colorText">Hello world</div>
</body>
</html>
js.js
function do_stuff(x, y, z) {
//send two of this function's arguments to another function
//defined in another script:
var results = do_other_stuff(x, y);
return results + z;
}
//This function will execute once the html page loads:
window.onload = function() {
var my_results = do_stuff(10, 20, 30);
alert("Inserting results in <div>");
//The following div won't exist until after the page loads:
var div = document.getElementById('show_results');
div.innerHTML = my_results;
}
If the window.onload thing is too confusing, just get rid of it and use alert()'s to show the results (or any other info you are interested in).
js2.js
function do_other_stuff(x, y) {
return x+y;
}
Now, if you want to pass just one thing to the do_other_stuff() function, e.g. your object (things with braces around them are called 'objects'), you can rewrite your scripts like this:
js.js
function do_stuff() {
var points = {
"points": [
"47.15211, -97.570039",
"48.625045, -101.375369",
"48.39679, -101.052669" ]
};
do_other_stuff(points);
}
do_stuff();
Then rewrite do_other_stuff() to look like this:
js2.js
function do_other_stuff(points_obj) {
//do stuff with points_obj, e.g.
alert( points_obj.points[0] );
}
In this example, the scripts aren't operating on any of the html elements, so there is no need to wait for the page to load.
====
See if the following comments help:
1) This loop:
for (i = 0; i < rid.length; i++) {
var points = ('"' + lat[i] + "," + lon[i] + '"');
}
is equivalent to:
var points = '"' + lat[rid.length] + "," + lon[rid.length] + '"';
2) The thing you are doing with the quotes there is really ugly. If you are just trying to turn some numbers into a string, you can do this:
var point = lat[i] + ", " + lon[i];
js can't add a number and a string together, so js makes the assumption that you are trying to create a string, and js converts the number to a string then adds the strings together. Check this out:
var str = 3 + ', ' + 2;
var arr = [str];
console.log(arr);
--output:--
[ '3, 2' ]
3) You probably want to do something like this:
var points = []
for (i = 0; i < rid.length; i++) {
points.push( lat[i] + ", " + lon[i] );
}
4) Then to pass the points array to your deCarta stuff, you can do this:
var points = []
for (i = 0; i < rid.length; i++) {
points.push( lat[i] + ", " + lon[i] );
}
do_stuff(points);
And then you would define do_stuff() like this:
function do_stuff(the_points) {
//Do all your deCarta stuff here
window.map = new deCarta.Core.Map({
id: "mapContainer",
autoResize: true,
zoom: 11,
center: center,
onReady: function (map) {
map.addLayer(pinOverlay);
postPins();
}
});
function postPins() {
console.log(the_points); //You have access to the points array
obj = {"points": the_points};
=======
1) When you call a function, js lines up the function call with the function definition:
do_stuff(10, 20, 30) <----function call
function do_stuff( x, y, z) {...} <---function definition
Then javascript does these assignments:
var x = 10;
var y = 20;
var z = 30;
2) Then inside the function, you use the variables x, y, and z to refer to those values.
3) In the code I posted, the function call and function definition look like this:
do_stuff(points)
function do_stuff(the_points) {...}
So js does this assignment:
var the_points = points;
And points is just some array like ['10, 20', '100, 200'], so that assignment is equivalent to:
var the_points = ['10, 20', '100, 200']
And inside the function you use the_points to refer to the array.
You can use something like this to run through each pair in the array:
var points = [ "47.15211, -97.570039", "48.625045, -101.375369", "48.39679, -101.052669"];
points.forEach(function (point) {
point = point.match(/^"([0-9\.]+)\s*,\s*([0-9\.]+)"$/);
console.log('"' + point[0] + '", "' + point[1] + '"');
});
Or something like this if you're wanting to put them in their own arrays:
var points = [ "47.15211, -97.570039", "48.625045, -101.375369", "48.39679, -101.052669"],
lat = [], lon = [];
points.forEach(function (point) {
point = point.match(/^"([0-9\.]+)\s*,\s*([0-9\.]+)"$/);
lat.push(point[0]);
lon.push(point[1]);
});
lat.forEach(function (lat, id) {
console.log('"' + lat + '", "' + lon[id] + '"');
});
Or even:
lon.forEach(function (lon, id) {
console.log('"' + lat[id] + '", "' + lon + '"');
});
Also, someone commented on here and said that I shouldn't be using split for this when you're joining it back together. If you're not looking to have them separated like this, you can always use:
points.points = points.points.map(function (point) {
return point.replace(/^"([0-9\.]+)\s*,\s*([0-9\.]+)"$/, '"$1", "$2"');
});
Maybe this will work but I don't know what your variables rid, lat and long are. Maybe you could post it. To see the variable in Chrome or Firefox you can do:
console.log(JSON.stringify(rid);
Press F12 to see the console.
var points={};
points.points=[];
for (i = 0; i < rid.length; i++) {
points.points.push('"' + rid[i].lat + "," + rid[i].lon + '"');
}