Nesting a function returning NaN - javascript

I am running into an error when I try nesting a simple counter function inside an existing function. I know some people frown upon this, so if there is any other way of doing this, it would be greatly appreciated. Basically, I am calling a function to parse a JSON string to get 3 numbers. I would like to animate those 3 numbers with a counter every time a new calculation is made. My instinct is to place this counter function inside of the same for loop that runs to get the numbers themselves. Doing so returns NaN. I'm sure there is something very little that I am missing here that I am hoping someone can pick up on.
Code:
var text = '{JSON data}'
var obj = JSON.parse(text);
function calculate() {
var e = document.getElementById("ltSpecialtyList");
var selectedSpec = e.options[e.selectedIndex].text;
console.log(selectedSpec);
var x = document.getElementById("ltLocationList");
var selectedState = x.options[x.selectedIndex].text;
console.log(selectedState);
for (i = 0; i < obj.values.length; i++)
{
if (obj.values[i].State == selectedState && obj.values[i].Specialty == selectedSpec)
{
// DISPLAY RESULTS DIV (JQUERY)
var $resultsDiv = $("#ROI-results");
$resultsDiv.fadeIn();
// CAPTURE HEADER SPAN NAMES
var headerState = document.getElementById("header-state-name");
var headerSpec = document.getElementById("header-specialty-name");
// CLEAR STATE AND SPECIALTY FROM SPAN
headerState.innerHTML = "";
headerSpec.innerHTML = "";
// ADD SELECTED STATE AND SPECIALTY
headerState.innerHTML += selectedState;
headerSpec.innerHTML += selectedSpec;
// CAPTURE RESULT DATA DIVS
var permResults = document.getElementById("ROI-results-perm-data");
var locumResults = document.getElementById("ROI-results-locums-data");
var uncollectedResults = document.getElementById("ROI-results-uncollected-data");
// CLEAR DATA DIVS
permResults.innerHTML = "";
locumResults.innerHTML = "";
uncollectedResults.innerHTML = "";
//POPULATE DIV WITH DATA
permResults.innerHTML += "<p class='ROI-results-data-number univers-bold'>" + obj.values[i].Permanent + "</p>";
locumResults.innerHTML += "<p class='ROI-results-data-number univers-bold'>" + obj.values[i].Locums + "</p>";
uncollectedResults.innerHTML += "<p class='ROI-results-data-number univers-bold'>" + obj.values[i].Gross + "</p>";
}
// COUNTER
$('.ROI-results-data-number').each(function () {
$(this).prop('Counter',0).animate({
Counter: $(this).text()
}, {
duration: 4000,
easing: 'swing',
step: function (now) {
$(this).text(Math.ceil(now));
}
});
});
}
}

Related

Cant call Jquery function in if loop

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

Array is not accessible outside of Casper repeat function

My goal is to get each job link of a job site, go to each Job detail page by following Job link, download and save the detail in html through CASPERJS.
As id of each Job link change each time we back & forth between job link and job detail page, I need to get all the Job id each time under casper.repeat . But NoOfLink array is become empty outside of repeat function [I comment that part in code]. What is the problem?
var casper = require('casper').create();
var noOfRecordsToLoop = 0;
var TotalNoofNullElement = 0;
var NoOfLink = [];
var x = require('casper').selectXPath;
casper.echo('\nStart loding site......');
//---------------------------------------------Load and Scroll the site---------------------------------------//
casper.start('https://........../...../.......Careers/');
casper.wait(10000, function () {
//---------Total no of Job posting------//
var noOfRecords = this.fetchText(x('//*[#id="...........................jobProfile......"]'));
noOfRecordsToLoop = noOfRecords.replace(/[^0-9]/g, "");
var totalNoOfPage = Math.ceil(parseInt(noOfRecords) / 50);
casper.echo('\nStart scrolling site......');
casper.repeat(totalNoOfPage, function () {
this.scrollToBottom(); //-----------------------Scroll down
casper.wait(10000, function () {})
})
})
//------------------------------------------------Load and Scroll the site---------------------------------------//
casper.then(function () {
//-----------------------------------------Get all the link elements --------------------------//
var countForLink = 0;
var numTimesForRpt = noOfRecordsToLoop;
var numTimes = noOfRecordsToLoop;
casper.repeat(numTimesForRpt, function () {
RetElement = this.evaluate(function () {
var startingRow = '//*[contains(#id, "...-uid-")]'
var element = __utils__.getElementByXPath(startingRow).getAttribute('id');
return element;
});
var count = RetElement.replace(/[^0-9]/g, "");
casper.repeat(numTimes, function () {
var MatchElements = this.evaluate(function (count) {
var xp = '//*[contains(#id, "...-uid-' + count + '")]'
var element = __utils__.getElementByXPath(xp).getAttribute('id');
return element;
}, count++);
if (!MatchElements) {
TotalNoofNullElement = TotalNoofNullElement + 1
} else {
NoOfLink.push(MatchElements);
}
//**Here array elements are accessible**
for (var k = 0; k < NoOfLink.length; k++) {
this.echo(NoOfLink[k]);
}
});
//**But here array elements are not accessible outside of repeat** function
this.echo("Size of array is" + NoOfLink.length);
for (var q = 0; q < NoOfLink.length; q++) {
this.echo(NoOfLink[q]);
}
//-----------------------------------------Get all the link elements----------------------------//
//------------------------------------Go to the Job Detail Page Extract HTML and Save---------------------------//
this.echo("\n Inside repeat to Generate HTML");
var num = NoOfLink[countForLink];
this.echo("\nLink id is " + NoOfLink[countForLink]);
num = parseInt(num.replace(/[^0-9]/g, ""));
this.echo("\nNum is " + num);
//-----------------Click to go to the Job Detail Page------------------//
casper.thenClick(x('//*[#id="..-uid-' + num + '"]/div/div'));
casper.wait(5000, function getJobDetail() {
var content = this.getElementInfo(x(".//*[contains(#id,'......t-uid-')]")).html;
var divStart = '<div id="extrdHtml">'
var divEnd = '</div>'
var body = divStart + content + divEnd
this.echo("\nContent of Job detail :" + body);
var fs = require('fs');
fs.write('extractedJob' + NoOfLink[countForLink] + '.html', body, 'w');
this.echo("\nFile saved");
//------------------------------------Go to the Job Detail Page Extract HTML and Save---------------------------//
}); //casper.wait
casper.back();
casper.wait(5000);
countForLink++
}); //casper.repeat
}); //casper.then
//-------------------------------------------Get all the link elements------------------------------//
casper.run();
There are two repeat loops.
casper.repeat(numTimesForRpt, function () { - This is main outer loop , where the 2nd loop resides.
casper.repeat(numTimes, function () – Where I am getting the link and populating NoOfLink array. I am trying to get the array element value outside of this 2nd loop(within main outer loop) but it is not working.
All then* and wait* functions are asynchronous step functions. If you call them, you're scheduling a step that is executed at the end of the current step. casper.repeat() is a function that uses casper.then() and is therefore also asynchronous. Every synchronous code that comes after casper.repeat() will be executed before the contents of the repeat callback.
You have two options:
Wrap everything that comes after casper.repeat() in a casper.then() to make it asynchronous or
Use a normal synchronous loop instead of repeat, if the callback of repeat doesn't need to be evaluated asynchronously like in your case.
By the way, you can oftentimes reduce your code a bit by utilizing the helper functions that CasperJS provides. For example, you don't need to use evaluate() only to get the id attributes of some elements by XPath. You can do that with casper.getElementsAttribute().
Example:
var count = RetElement.replace(/[^0-9]/g, "");
for(var i = count; i < (numTimes + count); i++) {
var MatchElements = this.getElementsAttribute(x('//*[contains(#id, "...-uid-' + i + '")]'), 'id');
if (!MatchElements) {
TotalNoofNullElement = TotalNoofNullElement + 1
} else {
NoOfLink.push(MatchElements);
}
//**Here array elements are accessible**
for (var k = 0; k < NoOfLink.length; k++) {
this.echo(NoOfLink[k]);
}
}

Updating Integer on the Page

I'm creating something which shows a list of cats and then increments a counter when the image is clicked. I've got everything working so when the image is clicked it increments the integer when I log it to the console. The only problem is that on the page the counter doesn't increment, it stays static at zero.
Here is my code. I've tried to create an update function which takes everything with the class tag and then loops through it replacing the HTML with the same thing so it redraws the text.
However it doesn't work. Any help would be appreciated!
var HTMLcatName = '<h1>%data%</h1>';
var HTMLcatImage = '<img id="cat" src="%data%">';
var HTMLcatCounter = '<p class="counter">Number of clicks: %data%</p>';
var noCats = 'No cats selected m8';
var cats = {
"name": ["Monte", "Jib"],
"image": ["images/monte.jpg", "images/jib.jpg"],
"clicks": [0, 0],
display: function () {
for (i = 0; i < cats.image.length; i++) {
formattedCatNames = HTMLcatName.replace("%data%", cats.name[i]);
var catNames = formattedCatNames;
formattedCatImages = HTMLcatImage.replace("%data%", cats.image[i]);
var catImages = formattedCatImages;
formattedCatCounter = HTMLcatCounter.replace("%data%", cats.clicks[i]);
var catCounter = formattedCatCounter
var elem = document.createElement('div');
elem.innerHTML = catNames + catImages + catCounter;
elem.querySelector('img').addEventListener('click', (function(catCountUp) {
return function() {
cats.clicks[catCountUp]++;
update();
};
})(i));
document.body.appendChild(elem);
}
},
}
cats.display();
var getCounterClass = document.getElementsByClassName("counter");
var update = function() {
for (j = 0; j < getCounterClass.length; j++) {
getCounterClass[j].innerHTML = '<p class="counter">Number of clicks: ' + cats.clicks[j] + '</p>';
}
}
I cannot see the click event, but this can be the error:
getTags.innerHTML = '<p class="counter">Number of clicks: ' + cats.clicks[j] + '</p>';
replace with
getTags[j].innerHTML = 'Number of clicks: ' + cats.clicks[j];
you are missing the counter in the for loop for targeting the right element

using checkboxes and counting them in Lightswitch HTML

I am currently using this code to display checkboxes as a custom control, and it works perfect:
// Create the checkbox and add it to the DOM.
var checkbox = $("<input type='checkbox'/>")
.css({
height: 20,
width: 20,
margin: "10px"
})
.appendTo($(element));
// Determine if the change was initiated by the user.
var changingValue = false;
checkbox.change(function () {
changingValue = true;
contentItem.value = checkbox[0].checked;
changingValue = false;
});
contentItem.dataBind("value", function (newValue) {
if (!changingValue) {
checkbox[0].checked = newValue;
}
});
however now I want to extend this a little, and I am wondering if anyone knows how I can count values based on whether they are true or false.
What im looking for:
I have 2 checkboxes below, the 1st is "TRUE" and the 2nd is "FALSE"
I want to be able to count up these values using something like var count then put it in a while loop, or an array and then display it back on a button like the following for testing purposes: window.alert("add in text here" + add_code_here)
so example data would be:
var trueCount = 0;
var falseCount = 0;
window.alert("There are: " + trueCount + " values that are true and " + falseCount + " that are false");
and the above example trueCount = 1 and falseCount = 1
Thanks for any input people can give me, it is most appreciated
I couldn't get it to work with the custom control check boxes but for the standard switches this code worked for me:
var trueCount = 0;
var falseCount = 0;
myapp.TableName.ColumnName_postRender = function (element, contentItem) {
// count the true or false values
contentItem.dataBind("value", function (newValue) {
if (contentItem.value == true) {
trueCount ++;
falseCount--;
} else if (contentItem.value == false) {
falseCount++;
trueCount--;
}
});
//count 3 sets both trueCount and falseCount to 0 as they would already be affected by the
//post render method. This works by adding or subtracting the amount of false values non
//screen (works my my scenario)
var count3 = 0;
if (contentItem.value == false) {
count3++;
}
falseCount = falseCount - count3;
trueCount = trueCount + count3;
};
myapp.TableName.Save_execute = function (screen) {
window.alert("True Count: " + trueCount + " | falseCount: " + falseCount);
//set both count values back to 0 for when the screen is next run
trueCount = 0;
falseCount = 0;
}

Multiplying Variables Not Alerting

I have a script which calls variable values from input fields and multiplies them,
At the minute my function isnt executing, Im getting no alert neither, I think this is because of my if statement, can anybody see whats going wrong?
function Calculate() {
var ContentMinutes = document.getElementById ("ContentMinutes").value;
var ContentMinutesSelect = document.getElementById('ContentMinutesDD')
.options[document.getElementById('ContentMinutesDD').selectedIndex].value
if (ContentMinutesSelect == 0.0166)
{
var RenderingHours = 10;
var VideoHours = 5;
var VideoSeconds = 1;
document.getElementById("RenderHours").innerHTML=RenderingHours;
document.getElementById("VideoHours").innerHTML=VideoHours;
document.getElementById("VideoSeconds").innerHTML=VideoSeconds;
}
else if (ContentMinutesSelect == 0.0003)
{
var RenderingHours = 1540;
var VideoHours = 54;
var VideoSeconds = 1;
document.getElementById("RenderHours").innerHTML=RenderingHours;
document.getElementById("VideoHours").innerHTML=VideoHours;
document.getElementById("VideoSeconds").innerHTML=VideoSeconds;
}
else
{
var RenderingHours = 6410;
var VideoHours = 345;
var VideoSeconds = 124;
document.getElementById("RenderHours").innerHTML=RenderingHours;
document.getElementById("VideoHours").innerHTML=VideoHours;
document.getElementById("VideoSeconds").innerHTML=VideoSeconds;
}
var NoOfFrames = document.getElementById ("NoOfFrames").value;
//var EstimatedCoreHours = document.getElementById ("EstimatedCoreHours").value;
var ServiceLevel = document.getElementById('SerivceLevelDD')
.options[document.getElementById('SerivceLevelDD').selectedIndex].value;
var RenderHours = 1;
var CoresInTest = document.getElementById ("CoresInTest").value;
var EstimatedCoreHours = GetNumeric(NoOfFrames)
* GetNumeric(RenderingHours)
* GetNumeric(CoresInTest);
var EstimatedTotal = GetNumeric(ServiceLevel)
* GetNumeric(EstimatedCoreHours);
alert('Estimated Cost = '
+EstimatedTotal.toFixed(2)
+ 'Estimated Core Hours = '
+EstimatedCoreHours);
document.getElementById("EstimatedCoreHours").innerHTML =
EstimatedCoreHours.toFixed(2);
document.getElementById("EstimatedTotal").innerHTML =
EstimatedTotal.toFixed(2);
document.getElementById("EstimatedCoreHours").style.backgroundColor="yellow";
document.getElementById("EstimatedTotal").style.backgroundColor="yellow";
}
function GetNumeric(val) {
if (isNaN(parseFloat(val))) {
return 0;
}
return parseFloat(val);
}
if (ContentMinutesSelect == 0.0166) i think when you do .value you will get string result.
So your comparision should be
if (ContentMinutesSelect == "0.0166")
Your code will display no alert if any line before it results in an error , like if there isn't an element with the id 'ContentMinutes' in your document . The best way to debug would be to use something like firebug , or you could always put in a bunch of alerts and figure out what goes wrong.

Categories

Resources