check out my code
It works but jsfiddle hates it for some reason.
but when it's ran in a browser i get NaN upon calculation
for some reason regardless of the parse it won't return an integer to perform calculations on.
any one have an idea why?
also
// JavaScript Document
var payment
/* requirement #2* Each input (years, loan amount, interest rate)
will have its own number pad for entry */
function getNum(id,span) {
var a;
a = parseInt(document.getElementById(id).value);
document.getElementById(span).innerHTML += a;
}
function clear1(span) {
document.getElementById(span).innerHTML = "";
}
/* requirment #7 Mortgage object with three variables: years, amount, rate */
function Mortgage(years, amount, rate) {
this.years = years;
this.amount = amount;
this.rate = rate;
/*Requirment #8. Object must have an internal function that resets all
values/variables to default and clears amounts displayed to user */
this.clearAll = function() {
document.getElementById(years).innerHTML = "";
document.getElementById(amount).innerHTML = "";
document.getElementById(rate).innerHTML = "";
}
/*gets the mortgage from spans*/
this.getCalc = function() {
/*Requirment # 9 Object must call at least 1 external function */
get();
}
}
function test() {
/*uses the params to call the spans id*/
var c = new Mortgage('yInput','lInput','rInput');
c.clearAll();
}
/* an external cunction to calculate mortgage*/
function get() {
var m = new Mortgage(parseInt(document.getElementById('yInput').innerHTML),
parseInt(document.getElementById('lInput').innerHTML),
parseInt(document.getElementById('rInput').innerHTML)
);
/* this is NaN?*/
document.write(m.years-m.rate);
}
function calculate() {
var c = new Mortgage();
c.getCalc();
}
http://jsfiddle.net/5qf7f/6/#run
In the part:
> /* this is NaN?*/
> document.write(m.years-m.rate);
Note that if the document has finished loading, a call to document.write will first call document.open, which clears the entire content of the document (including all scripts and the HTML element itself).
http://jsfiddle.net/5qf7f/6/#run
That "fiddle" doesn't work at all for me. Better to reduce your code to an absolute minimum that displays the issue and post that. The exercise will likely lead you to your problem.
It might help your investigation to know that parseInt('') returns NaN.
Related
I'm creating a reusable function to monitor how frequently a button is clicked and wait until the user stops clicking it to continue and it seemed to work great until i tried creating 2 buttons (which will be how it will be in production)
I am using objects to store the data while the user is clicking.
If the timer is not reset and runs out, it will post the data.
If you try just spamming the lemon button a few times you will see how it works. The same if you spam the diamond button.
var arr = {};
var SC={};
function SpamControl(u, i) {
this.ui = u+i;
this.Sp = SC[ui];
if (!SC[ui]){
SC[ui] = arr;
SC[ui].timer= "";
SC[ui].count = 0;
}
clearTimeout(SC[ui].timer);
SC[ui].count = SC[ui].count + 1;
SC[ui].timer = setTimeout(function(){
$('#count').prepend(u+" gave "+ SC[ui].count +" "+i+"'s in a controlled fashion!<br>");
delete SC[ui];
}, 1000);
}
The problem comes when you spam between the two buttons. I had hoped it would handle the two users attached to the buttons separately but it seems not and im not sure why.
I realize this is a bit unclear but all i can say is try it out to understand what i mean
Here is a fiddle: https://jsfiddle.net/gbe7dv1r/1/
Don't use global variables, use local ones:
let ui = u + i;
let Sp = SC[ui];
Also all entries in Sp will reference the same arr object, when initualizing an entry you might want to create a new object for each:
SC[ui] = { };
Finally some wise words: Cryptic abbreviations like u, i, ui, SC, Sp, arr will really cause you headaches when maintaining this piece of code.
const controls = { /*[name]: { timer, count } */ };
function spamControl(user, item) {
const name = user + item;
const control = controls[name] || (controls[name] = { timer: 0, count: 0 });
control.count += 1;
clearTimeout(control.timer);
control.timer = setTimeout(function(){
$('#count').prepend(
`${user} gave ${control.count} ${item}"s in a controlled fashion!<br>`
);
delete controls[name];
}, 1000);
}
I have been working all day trying to pass the value of "returnData.salary" inside the "readData" function to
the object inside the "calculateTax" function which is suppose to take the salary value and calculate state and federal taxes. I am stumped, I can't find anything on the internet which provides a good example for me to work with. The examples are either way to simple or super complex. Any help would be appreciated.
I apologize in advance if I did not submit this question in the correct format. This is my first time asking for help on stackoverflow.
function readForm() {
var returnData = {};
returnData.name = $("#name").val();
returnData.lastName = $("#lastName").val();
returnData.age = $("#age").val();
returnData.gender = $("[name=gender]:checked").val();
returnData.salary = $("#salary").val();
returnData.isManager = $("#isManager").val();
returnData.myTextArea = $("#myTextArea").val();
$("#name2").text(returnData.name);
$("#lastName2").text(returnData.lastName);
$("#age2").text(returnData.age);
$("#gender2").text(returnData.gender);
$("#salary2").text(returnData.salary);
$("#myTextArea2").text(returnData.myTextArea);
if ($(isManager).is(':checked')) {
$("#isManager2").text("Yes");
}
else {
$("#isManager2").text("No");
}
//$("#employeeForm")[0].reset();
} //end of readForm function
function calculateTax() {
console.log("Button Works");
var calculateTax = {
state: function(num) {
num *= 0.09;
return num;
}
, federal: function(num) {
if (num > 10000) {
num *= 0.2;
return num;
}
else {
num * 0.1;
return num;
}
}
, exempt: true
};
}
//Invoke readForm function when the submit button is clicked.
$(document).ready(function () {
$("#btnSubmit").on("click", readForm);
$("#btnCalculate").on("click", calculateTax);
})
</script>
Well, simply put; you can't. Not like this anyway. Or, at least not pass the value to the function directly.
You are using global functions right now, which are not inside a class. If it was inside a class, you could instantiate the class and save it to this (which would be the class' instance). However, I'm assuming classes are a bit over complicated in this case. What you could do, is set variables globally so all functions can use them, like this;
//declare the global variable so it exists for every function
var returnData = {};
function readForm() {
//We do NOT redeclare the "var" again. It's global now.
returnData = {}; //Reset the global variable when this function is called
returnData.name = $("#name").val();
returnData.lastName = $("#lastName").val();
returnData.age = $("#age").val();
returnData.gender = $("[name=gender]:checked").val();
returnData.salary = $("#salary").val();
returnData.isManager = $("#isManager").val();
returnData.myTextArea = $("#myTextArea").val();
//Rest of your function
}
function calculateTax(){
console.log(returnData) //works here
}
Note that you do overwrite global variables, so it's best to reset them on every function call. You might get old data stuck in there, otherwise.
EDIT: Thank you to all who responded. I'm in the process of checking it with just console.log for the desired output, but at the moment I do know that it is not doing what I want with HTML. Anyone else know what could be wrong?
Thanks!
EDIT 2: The function "functions" when I define "television" directly within the console, but other than that, I can't figure out how to have television defined in the code. I took it out of the start(); function because I thought it might be out of scope. That didn't work either.
// Program Name: Television Store
// Television Store Website.
/* Constructor Function: */
function TelInput(ret, man, scr, conf, dis) {
this.ret = parseInt(ret, 10);
this.man = man;
this.scr = parseInt(scr, 10);
this.discount = this.ret * 0.9;
this.dis = dis;
this.conf = conf
};
var start = function(){
/* Initial Variables */
var screen = prompt("Enter the screen size of TV in inches: ");
var manufacturer = prompt("Enter the manufacturer of TV: ");
var retail = prompt("Enter the retail value of TV: ");
var priceConf = confirm("Apply the 10% discount?");
var dispValues = confirm("Display Values when Finsihed?");
/* Display the Values */
console.log(television.ret);
console.log(television.man);
console.log(television.scr);
console.log(television.discount);
if(television.conf){
document.getElementById("l4").innerHtml = "Discounted Price: " + television.dis;
}
};
console.log("Program Completed."); // Confirm Javascript functions.
start(); // Start function.
var television = new TelInput(retail, manufacturer, screen, priceConf, dispValues); // Create object
If telInput is supposed to be constructor function:
Call it with new: var television = new telInput(retail, manufacturer, screen, priceConf, dispValues);. Right now the properties ret, man, etc will be assigned to window and television will be undefined.
Pascal-case constructor functions: TelInput. This is a very strong convention. See this.
A few other issues:
You are not assigning dis and conf to any property: add this.dis = dis; this.conf = conf.
this.discount = ret * 0.9; this should probably be this.discount = this.ret * 0.9; as this.ret contains the parsed value.
I'm trying to "animate" a div's css by choosing a random class at random intervals. Currently i'm using a recursive function that looks like this:
$scope.spin = function() {
console.log('spinning');
var maxCycle = 100;
var currentCycle = 0;
recursiveRandomChange();
function recursiveRandomChange() {
if (currentCycle <= maxCycle) {
currentCycle += 1;
console.log(currentCycle);
$interval(blockOne(), getRandomTime());
recursiveRandomChange();
}
}
function blockOne() {
var currentClass = getRandomClass();
$scope.engine.one = currentClass;
console.log('changing color ', currentClass);
}
};
As you can see it only allows for 100 cycles but it's supposed to set "blockOne"s class ($scope.engine.one) to a random class everytime the interval finishes. I can see in the console log the code running correctly but instead of cycling through 100 random classes at random times it only changes once (from the original color to the class randomly picked on the 100th iteration).
Any advice is appreciated. Thanks!
check this: http://jsfiddle.net/pfgkna8k/4/
Inside recursiveRandomChange, you were recursively calling recursiveRandomChange & using $interval too. $interval is itself recursive.
angular.module('lists', []).controller('ProductList', function($scope, $interval) {
var getRandomTime = function() {
return 1000;
};
$scope.spin = function() {
console.log('spinning');
var maxCycle = 100;
var currentCycle = 0;
recursiveRandomChange();
function recursiveRandomChange() {
if (currentCycle <= maxCycle) {
currentCycle += 1;
console.log(currentCycle);
$interval(blockOne, getRandomTime());
//recursiveRandomChange();
}
}
function blockOne() {
var currentClass = getRandomClass();
//$scope.engine.one = currentClass;
var element = document.querySelector("#test");
element.className = currentClass;
console.log('changing color ', currentClass);
}
function getRandomClass() {
var classes = ["abc", "abc1", "abc2", "abc3"];
return classes[Math.round(Math.random() * 3)];
}
};
$scope.spin();
});
What's needed is $timeout not $interval as you want to change the color-changing delay period differently each time. And you want to repeat this randomness for 100 times.
$timeout is to do it once. $interval is to do it multiple times at a fixed interval.
$interval(blockOne, getRandomTime()); in Ayush's answer doesn't specify how many times blockOne will run. Thus, it will run forever..
I put some logging in Ayush code, you will see the random delay period is never changed.
What you really want is chaining 100 $timeout so that it runs one after another but not in parallel.
You will need to wrap function around each $timeout and then chain them later.
var changes = [];
changes[0] = function() {
return $timeout(setColor,getRandomTime());
}
changes[1] = function() {
return $timeout(setColor,getRandomTime());
}
...
// Chain them
changes[0]()
.then(changes[1])
.then(changes[2]);
In this case, you want to chain 100 times. We don't have to type .then() 100 times as each $timeout.then() is still a promise.
var executeChanges = changes[0]().then(changes[1]);
executeChanges = executeChanges.then(changes[2]);
I created a working demo
I'm trying to use a yui plugin that pulls from a json file and populates a div on the page. Everything should be a go, however, since the plugin never gets to the render stage, the rest of it does not run. It is successfully loaded otherwise (if I stick an alert or console.log at the beginning of the event, it works fine).
Here's the code:
YUI.add('events', function(Y) {
var urlEvents = //"/cgi-bin/eventview-json/?cal=admissions/events&days=10";
"/admissions/events/events.json";
//var eventContainer = $("#insert-events");
/* EventList class constructor */
var EventList = function(config) {
EventList.superclass.constructor.apply(this, arguments);
};
/*
* Required NAME static field, to identify the class and
* used as an event prefix, to generate class names etc. (set to the
* class name in camel case).
*/
EventList.NAME = "EventList";
/*
* Required NS static field, to identify the property on the host which will,
* be used to refer to the plugin instance ( e.g. host.feature.doSomething() )
*/
EventList.NS = "EventList";
/*
* The attribute configuration for the plugin. This defines the core user facing state of the plugin
*/
EventList.ATTRS = {};
var convertYYYYMMDDtoJS = function(s) {
var a, jsdate = null;
try {
a = /^(\d\d\d\d)(\d\d)(\d\d)$/.exec(s);
if (a) {
jsdate = new Date(a[1], a[2]-1, a[3]);
}
} catch (ex) {
/* Nothing */
}
return jsdate;
};
var insertEvents = function(id, response, e) {
alert('hello');
var i, resp, events, event, html, jsdate, label, seenevent, yyyymmdd;
var maxevents = 5, eventcount;
try {
resp = Y.JSON.parse(response.responseText);
events = resp.results;
html = "";
seenevent = {};
eventcount = 0;
yyyymmdd = "";
for (i = 0; i < events.length; i++) {
event = events[i];
if (seenevent[event.title]) {
continue;
}
seenevent[event.title] = true;
if (event.date !== yyyymmdd) {
// This is the first event on this date.
// If we've seen maxevents events, then bail before starting a new day.
if (eventcount >= maxevents) {
break;
}
// Put out a new label for this day.
jsdate = convertYYYYMMDDtoJS(event.date);
label = Y.DataType.Date.format(jsdate, {format: "%b %e %a"});
/*
* The first empty div below, "<div class='clear'></div>" is only needed for IE 7.
* IE 7 does not properly clear both left and right floats when "clear: both" is specified
* if the element itself is floated. The extra div clears the floats, but isn't floated
* itself. The extra div doesn't cause any grief in newer browsers, so I add it always.
*/
html += "<div class='clear'></div><div class='event-datelabel'>" + label + "</div>\n";
yyyymmdd = event.date;
}
html += "<div class='event-text'>" + event.html + "</div>\n";
eventcount++;
}
this.get('host').setContent(html + "<div id='events-footer'><a href='/calendar/'>all events</a></div>");
} catch(ex) {
console.log("Error", ex);
this.get('host').setContent("Event list not available");
return;
}
};
var insertEventList = function(yyyy, mm, dd) {
var url = urlEvents;
if (yyyy) {
url += '&yyyy=' + yyyy;
}
if (mm) {
url += '&mm=' + mm;
}
if (dd) {
url += '&dd=' + dd;
}
Y.io(url, {on: {success: insertEvents}, context: this});
};
/* EventList extends the base Plugin.Base class */
Y.extend(EventList, Y.Plugin.Base, {
render: function() {
insertEventList.call(this);
}
});
//console.log("assigning", EventList);
Y.namespace("Plugin").EventList = EventList;
}, '1.0.0' ,{requires:['node', 'base', 'plugin', "json-parse", "datatype-date"]});
Here's the excerpt from the code with the render bit:
Y.extend(EventList, Y.Plugin.Base, {
render: function() {
insertEventList.call(this);
}
Admittedly, YUI3 confuses me, and I would prefer other libraries, but I don't have a choice in this situation. There's likely one thing that I've just completely looked over.
Thanks guys
I've used YUI3 plugins before and they are a bit difficult to grasp, but I'll try to help if I can. Once you've created the plugin, which, from what I can tell, you've already done so successfully, you plug it into an object somewhere else in your code:
someObj.plug(Y.Plugin.EventList, cfg);
After that, you can access the plugin's methods from within the object's plugin namespace. In your case you'd do this like so:
someObj.EventList.render();
Hopefully I'm understanding your question correctly and I hope that helps clear some stuff up for you. Good luck! :)