Using this script i m facing this error Not a number value that i don t understand,
How can I fix this ?
<!DOCTYPE html>
<html>
<head>
<title>The Cube</title>
</head>
<body>
<script>
var cube = function(side) {
this._side = side;
this.volume = function() {
var vol = Math.pow(this.side, 3);
return vol;
};
this.surface = function() {
var totalLength = 12 * this.side;
return totalLength;
};
};
var firstCube = new cube(2);
document.write("Volumul " + firstCube.volume() + "<br>");
document.write("Total length " + firstCube.surface());
</script>
</body>
</html>
You assign the value of side to this._side. Therefore you can access it as side inside of the function and as this._side inside of every method (as your methods are inside the function too, both will work). But this.side does not exist, it is not defined, and multiplying it results in Not a Number.
How I would write that:
class Cube {
constructor(side) { this.side = side; }
get volume() { return Math.pow(this.side, 3); }
get surface() { return 12 * this.side; }
}
const cube = new Cube(3);
console.log(cube.volume, cube.surface);
Related
So the script is really simple, I try to push the dNumber into variable pattern and the results are always "underfined".
when i try to do the same with just push a TEXT for example it's worked.
var level = 0;
var pattern = [];
var userPatern = [];
function dNumber() {
var a = Math.floor((Math.random() * 100 / 25) + 1);
console.log(a);
console.log(pattern);
}
$("body").click(gamestart);
$("body").keypress(gamestart);
function gamestart() {
$("#level-title").text("level " + level);
var x = dNumber();
pattern.push(x);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
var level = 0;
var pattern = [];
var userPatern = [];
function dNumber(){
var a = Math.floor((Math.random()*100/25)+1);
console.log(a);
console.log(pattern);
}
$("body").click(gamestart);
$("body").keypress(gamestart);
function gamestart() {
$("#level-title").text("level " + level);
var x = dNumber();
// pattern.push("alex"); this is work!
pattern.push(x);
pattern.push(dNumber());
//this isn't work what should be number looks like appear as underfined.
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You need to return a from dNumber function so that you can use :)
var level = 0;
var pattern = [];
var userPatern = [];
function dNumber() {
var a = Math.floor((Math.random() * 100 / 25) + 1);
console.log(a);
console.log(pattern);
// return a here if not then it's gonna return undefined by default :)
return a;
}
$("body").click(gamestart);
$("body").keypress(gamestart);
function gamestart() {
$("#level-title").text("level " + level);
var x = dNumber();
pattern.push(x);
console.log(pattern);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Good evening, If someone could help me , I would be glad.I am trying to reach some functions in my Car class. Firstly I am trying to assign inpSpeed input value to Car class function Drive and then I wanna print out to console all cars info when I press the button: btnRace and the problem is I dont really know how to call them , because everytime I call them it says:"undefined".
here is my code so far:
carsArray = [];
btnCarName.onclick = function(){
carsArray.push({/*obj.element1, obj.element2, obj.element3*/});
}
btnRace.onclick = function(){
for(j in carsArray)
{
console.log(Car(carsArray[j]));
}
}
function Car(name,speed)
{
this.carBrand = name;
this.speed = speed;
this.distance = 0;
this.Drive = function(time)
{
if(time > 0)
return this.distance = (this.speed * (time/10));
}
this.printData = function()
{
for(var i = 0; i < Car.length; i++)
{
console.log('Car brand: ' + this.carBrand);
console.log('Speed: ' + this.speed);
console.log('distance: ' + this.Drive());
console.log('---------------------------');
}
}
}
For the this keyword to work, you must instantiate Car() with the new keyword:
var toyota = new Car('toyota', 100)
console.log(toyota.speed);
There may however be a couple other issues. What exactly is expected from Car.length?
I am using d3.js to read data from a tsv file,but I found that there is something strange in the procedure,I read the data and push each line into an array called dataset and then want to calculate the variable total by using a for loop,but it seems to fail(there is no any datum in dataset),maybe it is because the javascript just going on without waiting for finish reading the file.The code is here:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>THis is a te</title>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js" type="text/javascript" charset="utf-8"></script>
<script src="fun.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
var dataset = new Array();
var parseDate = d3.time.format('%Y-%b-%e').parse;
d3.tsv("data.tsv",function(error,data){
for(var i in data){
//console.log(data[i].date);
//console.log(parseDate(data[i].date));
var elapse = (i == 0) ? 0 : dateElapse(parseDate(data[i-1].date),parseDate(data[i].date));
dataset.push({
date : parseDate(data[i].date),
state : data[i].state,
elapse : elapse
});
}
});
var total = 0;
for(var i in dataset){
total =total + dataset[i].elapse;
}
console.log(total);
var tau = Math.PI * 2;
var width = 960,height = 500;
var svg = d3.select("body").append("svg").attr({
"width" : width,
"height": height,
});
var container = svg.append("g").attr({
"transform":"translate(" + width / 2 + "," + height / 2+ ")"
});
var arc = d3.svg.arc()
.innerRadius(180)
.outerRadius(240)
.startAngle(0);
var background = container.append("path")
.datum({endAngle: tau})
.style("fill","#ddd")
.attr("d",arc)
var foreground = container.append("g").append("path")
.datum({endAngle: 0.25 * tau})
.style("fill","#ffa500")
.attr("d",arc)
</script>
</body>
</html>
fun.js:
var month = [31,28,31,30,31,30,31,31,30,31,30,31];
var millseconds_per_day = 86400000;
function getDateParser(specifier) {
return d3.time.format(specifier).parse;
}
function day( ) {
return this.getDate();
}
function month() {
return this.getMonth();
}
function year( ) {
return this.getFullYear();
}
function dateElapse(start,end) {
return Math.ceil((end - start) / millseconds_per_day);
}
function loadtsv(file,arr){
arr = new Array();
d3.tsv(file,function(error,data){
var parser = getDateParser("%Y-%b-%e");
for(var i in data){
var elapse = (i == 0) ? 0 : dataElapse(parser(data[i-1].date,parser(data[i].data)));
arr.push({
date : parser(data[i].data),
state: data[i].state,
elapse : elapse
})
}
});
}
and the data file:
date state
2014-May-12 task1
2014-May-25 task2
2014-Jun-28 tsak3
NOTICE:The tsv file should separate its every datum by tab,assure that your paste code doesn`t change that,that may cause a fail reading.
I kown the skill like:
var reader = new FileReader();
read.onload=...
but I don`t kown what to do in my situation.
The easiest fix is to move the total calculation inside the tsv callback function.
d3.tsv("data.tsv",function(error,data){
for(var i in data) {
...
}
var total = 0;
for(var i in dataset){
total =total + dataset[i].elapse;
}
console.log(total);
});
Note that Javascript is an asynchronized language so the callback function doesn't block the rest of code from running, and since loading data.tsv file needs I/O operations the lines after the callback actually run before the callback function and by that time your array is still empty.
I am having difficulty figuring out what is wrong with these files. Firebug loads the HTML and the .js files but when you push the button on the HTML file it does not do anything. Putting breakpoints in firebug shows that the .js code is not talking to the HTML file. I do not know if Javascript is not working because of something else in the code or I have a really silly mistake in the HTML file. Thanks for any help.
HTML file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Dice Roller</title>
<style type="text/css">
#import "main.css";
</style>
<script type="text/javascript" src="roller.js"></script>
<script type="text/javascript" src="roller_library.js"></script>
</head>
<body>
<div id="content">
<h1>Dice Roller</h1><br/><br/>
Die 1: <span id="die_1"> </span><br /><br />
Die 2: <span id="die_2"> </span><br /><br />
<label>Message: </label>
<span id="message"> </span><br/><br />
<label> </label>
<input type="button" id="roll" value="Roll the Dice" /> <br/>
</div>
</body>
</html>
roller.js
var die = new Die();
var pairofDice = PairofDice();
var $ = function (id) { return document.getElementById(id); }
var update_display = function() {
var specialMsg;
var die_1 = ParseInt(Die.getValue1());
var die_2 = ParseInt(Die.getValue2());
$("die_1").value = die_1;
$("die_2").value = die_2;
var sum = PairofDice.getSum(die_1, die_2);
switch (sum){
case "2":
specialMsg = "Snake eyes"
break;
case "7":
specialMsg = "Craps";
break;
case "12":
specialMsg = "Box Cars";
break;
}
$("message").value = specialMsg;
}
var rollDice_click = function() {
$("die_1").value = "";
$("die_2").value = "";
update_display();
}
window.onload = function() {
$("roll").onclick = rollDice_click;
}
roller_library.js
var Die = function(sides) {
this.sides = 6;
return this;
}
Die.prototype.roll = function(sides) {
this.sides = sides;
do{
number = parseInt (10 * Math.random());
} while (number >this.sides || number <1);
return number;
}
Die.prototype.getValue = function() {
this.roll = Die.roll();
return this;
}
var PairofDice = function(sides) {
this.sides = 6;
return this;
}
PairofDice.prototype.roll = function() {
Die.roll(6);
return number;
}
PairofDice.prototype.getValue1 = function() {
Die.getValue();
return;
}
PairofDice.prototype.getValue2 = function() {
Die.getValue();
return;
}
PairofDice.prototype.getSum = function(d1,d2) {
var sum;
var die1 = parseInt(d1);
var die2 = parseInt(d2);
sum = die1 + die2;
return sum;
}
The other option is that I am not understanding what I should be doing, if that is the case please let me know so I can get more one on one help.
roller.js is being run before roller_library.js is even loaded so neither Die nor PairOfDice are defined when Die is used on line 1 of roller.js. So the roller.js JavaScript aborts with a failure at that point and the window.onload line is never executed.
Ok, so I entirely jumped the gun on the onclick issue, so I took a more indepth look at the code. Theres a couple of problems, the code won't even run nevermind the onclick not working. So, I fixed it and added some comments that might help you figure our where you went wrong if you compare it to your code. This is by no means best practice code, I've just tried to translate your code idea into working code so hopefully you can learn from it.
Please let me know if it helps or you need anything clarified :)
// Can't do this at the start of the script as they are undefined
//var die = new Die();
//var pairofDice = PairofDice();
// This is a good idea
var $ = function(id) {
return document.getElementById(id);
}
// Let's include the model code ahead of the application code
// Our Die, when rolled it should have update it's value
var Die = function(sides) {
// Let's use the parameter to decide how many sides our die has
// " || 6" means that if sides has no value, it will default to 6
// This helps us prevent errors from having no number of sides
// defined when we roll the dice
this.sides = sides || 6;
// We will be able to access the value from elsewhere, but let's give
// it an initial random value!
this.value = this.roll();
return this;
}
// Extending our Die's prototype to allow rolling!
// We don't need the sides parameter anymore, compare this old version
Die.prototype.old_roll = function(sides) {
// This would remove any value we have previously assigned to sides
this.sides = sides;
// This loop will create a bias in the random numbers generated and if
// the number of sides is greater than 10, it will never show it
do {
number = parseInt(10 * Math.random());
} while (number > this.sides || number < 1);
return number;
}
// Cleaner version of roll
Die.prototype.roll = function() {
// Get a random number [ This will be a decimal number between 0 and 1]
var random_number = Math.random()
// Multiply it by (#no of sides - 1)
// [This will be a decimal value between 0 and the (#no of sides - 1)]
var scaled_number = (this.sides - 1) * random_number
// We round the number so it's always an integer number
// We also add one to the result so we get a number between (1..# of sides)
// It should be clear that we had to subtract from the number of sides before
// we multiplied so that whenever we add one here we don't go outside our
// desired range of numbers (else the dice would read 1..7 with only 6 sides
var result = Math.round(scaled_number) + 1
// Assign the result to our die for future reference
this.value = result
// Return the result
return result
}
/* We have no need for getValue as we can access the value of the dice
Die.prototype.getValue = function() {
this.roll = Die.roll();
return this;
}*/
// The PairofDice should help us manage 2 dice
var PairofDice = function(sides) {
// The sides parameter will help us initialise the two dice
this.dice1 = new Die(sides);
this.dice2 = new Die(sides);
return this;
}
// When we roll the pair, it should roll each dice individually
// It will return an array with the value of each roll, for convenience
PairofDice.prototype.roll = function() {
var roll1 = this.dice1.roll();
var roll2 = this.dice2.roll();
return [roll1, roll2];
}
// Return the value of the first dice
PairofDice.prototype.getValue1 = function() {
return this.dice1.value;
}
// Likewise for the second dice
PairofDice.prototype.getValue2 = function() {
return this.dice2.value;
}
// Return the total score for all dices, there is no need to take
// any parameters to this function as we have all the data within
// our PairOfDice instace (referenced by 'this' keyword)
PairofDice.prototype.getSum = function() {
// No need to parseInt on these values as we only store integer values
var sum = this.dice1.value + this.dice2.value;
return sum;
}
// Now we can define our variables
// There is no need to make an instance of Die as we can just use
// PairofDice to manage 2 dice for us, make sure to use the new keyword!
//var die = new Die();
var pairofDice = new PairofDice();
// Updating the display when a roll is made
var update_display = function() {
var specialMsg;
// We can simplify this a lot now
//var die_1 = ParseInt(Die.getValue1());
//var die_2 = ParseInt(Die.getValue2());
// value doesn't set the text on span, so we will use innerText
$("die_1").innerText = pairofDice.getValue1();
$("die_2").innerText = pairofDice.getValue2();
// Get the sum of the roll
//var sum = PairofDice.getSum(die_1, die_2);
var sum = pairofDice.getSum();
// In the switch statement, it should be integer cases instead of string
switch (sum) {
case 2:
specialMsg = "Snake eyes"
break;
case 7:
specialMsg = "Craps";
break;
case 12:
specialMsg = "Box Cars";
break;
// we add a default message incase there is no special, because then it will print 'undefined'
default:
specialMsg = "No luck";
}
// Show the message!
$("message").innerText = specialMsg;
}
var rollDice_click = function() {
// These aren't needed as the value will always be updated
//$("die_1").value = "";
//$("die_2").value = "";
// Roll the dice..
pairofDice.roll();
// Show the results!
update_display();
}
window.onload = function() {
$("roll").onclick = rollDice_click;
}
I am trying to "extend" a DIV via Javascript by using a newly created div as prototype of my object.
As I understand Javascript, on creating a new instance of my Object via "new", the prototype-object is copied, assigned to "this" an then the function is executed (as the constructor).
Everything seems to work, except that whenever I create another object, and add it to the DOM, it "replaces" the original div. To be more exact: The constructor always changes the same div.
Using MyTest.prototype = document.createElement("div"); gives me the described behavior, the two commented lines after that in my code example are what I also tried, but to no avail.
I know trying to extend the DOM is frowned upon, but I want to understand this behavior, because I thought I knew how prototypes work and this simply does not fit my idea.
Here is a minimal example of what I am trying to do:
<!DOCTYPE html>
<html>
<head>
<title>Div-Prototype-Test</title>
<script type="text/javascript">
var height = 20;
var top = 0;
function MyTest() {
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
this.style.backgroundColor = "rgb("+ r +","+ g +","+ b +")";
this.style.position = "absolute";
this.style.width = "500px";
this.style.height = height + "px";
this.style.top = top + "px";
top += height;
document.getElementsByTagName("body")[0].appendChild(this);
}
MyTest.prototype = document.createElement("div");
// MyTest.prototype = document.createElement("div").cloneNode(true);
// MyTest.prototype = new Element();
window.addEventListener(
"load",
function() {
var a = new MyTest();
var b = new MyTest();
var c = new MyTest();
var d = new MyTest();
}
);
</script>
</head>
<body>
</body>
</html>
PS: Because of a certain Javascript-Framework my search for anything that changes the prototype in Javascript always resulted in hundreds of results that had nothing to do with my problem - please tell me if I missed a question that already discusses this.
Edit:
To make my question clearer:
Here is an example where I use an object as prototype - its properties get copied.
function A() {
}
A.prototype = { property: 4 };
A.prototype.set = function(num) {
this.property = num;
}
window.addEventListener(
"load",
function() {
var message = "";
var x1 = new A();
message += "A1 : "+ x1.property +"\n";
x1.set(15);
message += "A1 : "+ x1.property +"\n";
var x2 = new A();
message += "A2 : "+ x2.property +"\n";
alert(message);
}
);
The alert then said:
A1 : 4
A1 : 15
A2 : 4
The Div in my first example however does not seem to be copied, it behaves like a Singleton or Monostate. Should it not go like this?
Protype object is copied into a new object
the new object is assigned to "this"
this is given to the constructor
this is returned by the constructor (if no return statement is specified)
MyTest.prototype = document.createElement("div");
This line is executed only once. It creates a MyTest.prototype object which is also a DOM element <div>. Every MyTest object will receive this same prototype. Therefore, every MyTest object you create will be associated with this single <div> you created only once. You will have to create a new <div> for every MyTest.
Try this pattern:
MyTest = function() {
var myDiv = document.createElement("div");
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
myDiv.style.backgroundColor = "rgb("+ r +","+ g +","+ b +")";
myDiv.style.position = "absolute";
myDiv.style.width = "500px";
myDiv.style.height = height + "px";
myDiv.style.top = top + "px";
top += height;
document.getElementsByTagName("body")[0].appendChild(myDiv);
return myDiv;
}
This function creates a new <div>, using the createElement() call. Then, it sets all the properties you want on that new <div>. Finally, it returns your new <div>. As such, you can call it as
var myNewDiv = MyTest();
var myNewDiv = new MyTest();
Both options would work. In the second case a dummy new object is created by the new keyword, but it doesn't matter, as the new <div> created inside the function is actually returned.
You are mixing all kind of things. First, check my answer to this SO question. Second, Extending the Element Object can be done, but is is not supported by all browsers. Check this SO question.
Seems to me that you are planning to add elements to the document in some standardized way. Your code could be rewritten to (I modified it a bit):
function appendElement(content,id) {
var rgb = 'rgb('+ [Math.floor(Math.random() * 256),
Math.floor(Math.random() * 256),
Math.floor(Math.random() * 256)].join(',') +')';
var top = Math.floor( Math.random() * 300 + 20 );
var left = Math.floor( Math.random() * 100 + 10 );
this.style.backgroundColor = rgb;
this.style.position = "absolute";
this.style.width = "500px";
this.style.height = "200px";
this.style.left = left+"px";
this.style.top = top+"px";
this.innerHTML = content || '';
this.id = id || Math.Random*10000+1
document.getElementsByTagName("body")[0].appendChild(this);
}
Now you can use this to append any element to the document using `appendElement as follows:
appendElement.call(document.createElement('div'),'empty div');
appendElement.call(document.createElement('span'),'new empty span','span1');
Would that be an idea for what you aim at?
I found a workaround, it basically works the other way round - the prototype is a blank object and I copy the new objects data into a div in the constructor:
var height = 20;
var top = 0;
function deepCopy(fromObject, toObject, depth) {
if(typeof(fromObject) != "object" || typeof(toObject) != "object") {
// throw "deepCopy only copies objects"
return;
}
if (typeof(depth) == "undefined") {
depth = 0;
} else if (depth > 100) {
// Recursion depth too high. Abort.
// throw "deepCopy recursion depth cap hit"
return;
}
for (var key in fromObject) {
if (typeof(fromObject[key]) == "object" && fromObject[key] != null) {
if (typeof(fromObject[key].nodeType) != "undefined") {
toObject[key] = fromObject[key].cloneNode(true);
} else {
if (typeof(toObject[key]) != "object") {
toObject[key] = {};
}
deepCopy(fromObject[key], toObject[key], depth + 1);
}
}
toObject[key] = fromObject[key];
}
}
function MyTest() {
// This is ugly...
var self = document.createElement("div");
deepCopy(MyTest.prototype, self);
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
self.style.backgroundColor = "rgb("+ r +","+ g +","+ b +")";
self.style.position = "absolute";
self.style.width = "500px";
self.style.height = height + "px";
self.style.top = top + "px";
top += height;
document.getElementsByTagName("body")[0].appendChild(self);
return self;
}
MyTest.prototype = {};
// MyTest.prototype = document.createElement("div").cloneNode(true);
// MyTest.prototype = new Element();
window.addEventListener(
"load",
function() {
var a = new MyTest();
var b = new MyTest();
var c = new MyTest();
var d = new MyTest();
}
);
Although I have the feeling that my deepCopy-function is a rather inelegant (and possibly very buggy) way to perform the task, but the other way round with using cloneNode() did not work.
My original problem came from this: When the prototype is copied, all scalar values are copied, while all objects are simply referenced (like copying pointers, the pointer value is duplicated, but not the data it points to).
Hope this helps someone.