javascript reading an object as parameter of a function - javascript

Im making a kind of template for all usual mouse events in canvas.
so we have a class to define words, and all events must be launched when mouse is over the word.
then I´d declared a test object (pal) in the "universal" ( but now enclosed in a spacename) part of the code.
the function contains(pal)uses this test object declared as parameter, however the console saids "TypeError: Cannot read property 'posX' of undefined at contains"
as posX is an object "pal" atribute, the function contains(pal) cannot read this object I gess.
the question is ... why?
see the complete code at https://jsfiddle.net/evy182bp/

Looking at your code the line 141 is the one that causes the issue
console.log( "pincha dentro = ", contains());
Issue is that you call the contains method without passing a parameter of pal object, meaning that it automatically passes 'undefined' (take a look here)
function contains(pal) {
if((pal.posX <= mouse.x)&&
(pal.posX + pal.largoPalabra >= mouse.x)&&
(pal.posY <= mouse.y)&&
(pal.posY + pal.altoPalabra>= mouse.y))
{return true;}
else { return false;}
// if ((100 <= mouse.x)&&
// (100 + 150 >= mouse.x)&&
// (200 <= mouse.y)&&
// (200 + 40>= mouse.y)) // this works
}
As soon as you remove that line, you are without errors.
Hope this helps

Related

Return the array elements arranged from outermost elements to the middle element, traveling clockwise

I'm trying to solve a task called Snail: given an n x n array, return the array elements arranged from outermost elements to the middle element, traveling clockwise - as you can see in the attached image.
I've already written the function but come across an error. Function works fine for while(result.length<=3) - it returns [1,2,3,4]. But for bigger numbers it shows an error -Uncaught TypeError: Cannot read properties of undefined (reading '2').
I've tried to rewrite the functions in a few different ways but keep seeing this error.
I don't have any idea what could be the problem. The function down() is able to to return 4 but somehow it can't reach to 5 and beyond.
Thank you in advance for any help
function snail(array){
let arr=[...array] //copy of a passed array
let result=[] //here function will add next blocks
const y=arr.length; const x=arr[0].length //this is to measure size to stop while
let cY=0,cX=0;//current Y axis and current X axis
/*For the purpose of this function both axes start as 0(top left corner) and when going down is +1 instead of -1 as normally in math*/
while(result.length<=x*y){//this should go throw all of the blocks
result.push(...arr[cY].splice(cX,1,null))//take block and replace it with null
right()//search for a block - by default starts from right function
}
function right(){//goes right(next index of current array)
if(arr[cY][cX+1])
{cX+=1}
else{down()}
}
function down(){//goes down(next array of current index)
if(arr[cY+1][cX])
{cY++}
else{left()}
}
function left(){//goes left(previous index of current array)
if(arr[cY][cX-1])
{cX--}
else{up()}
}
function up(){//goes up(previous array of current index)
if(arr[cY-1][cX])
{cY--}
else{right()}
}
return result
}
console.log(snail([ [1,2,3],[8,9,4],[7,6,5]]))
You are trying to access an array's element that doesn't exist :
arr[x + 1][y]
You concidere this code will return false (undefined in fact) if indexes [x+1][y] doesn't exist
This is true only if arr[x + 1] exist but, when arr[x + 1] doesn't exist you also try to access the y'th element of this array which raises an error.
You should try something like this :
arr[x + 1] && arr[x + 1][y]
Which will return if first statement is false (undefined is interpreted as false) so it only check if [y] when [x + 1] exists.
Using array method .at() :
arr.at(x + 1).at(y) // (may) raise an error
arr.at(x + 1)?.at(y) // return undefined instead
Hope it's clear enought ;)

Creating an Arithmetic Task Runner

I have been tasked to create an Arithmetic Task Runner as part of my assignment.
Up until today I've never used NodeJS or even the terminal to execute a script.
I have been working on this for the past 5 hours and still no luck. I have avoided coming here and asking as I'd like to figure it out for myself, however, I have succumbed to desperately needing help.
This is the code I have so far:
class ArithmeticTaskRunner {
static set taskCount(counter) {
throw new('This is a readOnly accessor, the value is ${value}');
}
add(y) {
this.y = y || 0
console.log(y)
}
minus(x) {
this.x = Math.abs(this.y) * -1;
console.log(this.x);
};
multiply(z) {
this.z = z * this.x;
console.log(this.z)
}
execute(startValue) {
this.startValue = startValue + this.y
this.y = this.startValue
console.log(this.startValue)
this.startValue = this.minus
console.log(this.startValue)
this.startValue = this.multiply(this.startValue)
console.log(this.startValue)
}
}
tasks = [
function() { minus()},
function() { multiply(z)},
function() { add(x)},
function() { execute(x)}
]
This is nowhere near perfect, but it's 80%-90% near completion.
This is the task I have been given:
You should implement a class called ArithmeticTaskRunner with the following:
- An instance variable named tasks which is initialised to an empty array upon
creation.
- A method named addNegationTask which adds an anonymous function to the
tasks array. This anonymous function should take one argument, x, and return the
negation, -x.
- A method named addAdditionTask which takes a single argument y, and adds
an anonymous function to the tasks array. This anonymous function should take
one argument, x, and return the result x + y.
- A method named addMultiplicationTask which takes a single argument y,
and adds an anonymous function to the tasks array. This anonymous function
should take one argument, x, and return the result x * y.
- A read-only accessor named taskCount which returns the number of queued tasks.
- A method named execute, which takes a single argument named startValue.
If omitted, startValue defaults to zero. Starting at startValue, this method should iterate over the tasks array executing each function on the current value. It then returns the resulting number after all arithmetic operations have been executed.
I'd be grateful for any help I could get.
The issues I have are the following: The execute method (trying to make the startValue, after the addition, a negative), the multiplication method and the fact I cannot call the addition method twice without overriding the value. The examples of the program fully working have shown I should allow for a method to be called multiple times without overriding the previous value.
I know there's a rule where it's one question per issue, I concede that. But if anyone can help me out with any of the issues I will truly be grateful and I will compensate people for their efforts.
Thank you.
Edit - This is an example of both the expected inputs/outputs
> let taskRunner = new ArithmeticTaskRunner()
undefined
> taskRunner.addAdditionTask(2)
undefined
> taskRunner.addMultiplicationTask(4)
undefined
> taskRunner.addAdditionTask(10)
undefined
> taskRunner.execute(2)
26
> taskRunner.execute(-2)
10
I don't want to provide the whole answer because this is an assignment for you, but here's some code that might help you out. This starts with 5 then calls doubleIt and then calls addOne to arrive at 11.
It does this by creating an array of functions, each one performs a simple task and returns the result of its input modified in some way.
Then it creates a function called execute that uses Array.reduce to call the first function in the array with a given initial value, then repeatedly calls each function in the array on the result. Check the documentation for Array.reduce if you're confused about how it works.
doubleIt = x => x * 2;
addOne = x => x + 1;
tasks = [doubleIt, addOne];
execute = (initial) => tasks.reduce((x,fn) => fn(x), initial)
document.write(execute(5))
Hint #2
class ArithmeticTaskRunner {
constructor() {
this.tasks = [];
}
addAdditionTask(arg) {
this.tasks.push(x => x + arg);
}
addMultiplicationTask(arg) {
this.tasks.push(x => x * arg);
}
execute(startValue) {
return this.tasks.reduce((x, fn) => fn(x), startValue);
}
}
let taskRunner = new ArithmeticTaskRunner()
taskRunner.addAdditionTask(2)
taskRunner.addMultiplicationTask(4)
taskRunner.addAdditionTask(10)
document.write(taskRunner.execute(2));
document.write(', ');
document.write(taskRunner.execute(-2));

Slideshow stopped working console shows no related errors? But this one unrelated

Here is the error that shows "TypeError: undefined is not an object (evaluating 'tjq("#price-range").data('url-noprice').replace')"
That has nothing to do with the slideshow that I can think of? If you look at the page source you can see the images are there, but the photos tab at the top no longer expands and shows the slide images.
Example bag:
http://www.foreversummer.net/accommodation/villas-pappagallo-3/?adults=1&kids=0&rooms=1&date_from&date_to&child_ages%5B0%5D=0
Here is the part of the script that it is having an issue with.
if (tjq(".filters-container").length > 0) {
// price range
var price_slide_min_val = 0;
var price_slide_step = tjq("#price-range").data('slide-step');
var price_slide_last_val = tjq("#price-range").data('slide-last-val');
var price_slide_max_val = price_slide_last_val + price_slide_step;
var def_currency = tjq("#price-range").data('def-currency');
var min_price = tjq("#price-range").data('min-price');
var max_price = tjq("#price-range").data('max-price');
if (max_price == "no_max") { max_price = price_slide_max_val; }
var url_noprice = tjq("#price-range").data('url-noprice').replace(/&/g, '&');
if ((min_price != 0) || (max_price != price_slide_max_val)) {
tjq('#price-filter').collapse('show');
tjq('a[href="#price-filter"]').removeClass('collapsed');
}
Any help would be appreciated, if you spot something I have missed. This one has me stumped. Could this issue be causing the rest of the query to malfunction?
I've looked into the URL you added and saw the aforementioned js code.
It seems that you're looking for a dom element with the id "price-range", but it does not exist in your document dom. The element itself is missing.
The following line:
var url_noprice = tjq("#price-range").data('url-noprice').replace(/&/g, '&');
raises an error because the script is trying to use the method "replace" on
an undefined object. Step by step:
tjq("#price-range") → returns an empty array of objects
data('url-noprice') → is executed on each of the objects in the empty object array and returns 'undefined'
.replace(/&/g, '&') → is executed on 'undefined'

Recursive function (maze solver) - can't find a bug;(((

I am studying javascript and all is pretty easy to me except for some things like recursive functions. I do understand the way they work but while working with an example, I realized I can't capture the bug that prevents it from functioning...
I have an array (map) below (0 is a closed cell, 1 means path is open) and the recursive function I am trying to use to "find" path out of this "maze" by going from its top left cell to the bottom-right one.. Basically just make the function to "find" this path of 1s. But it fails;(
var map = [
[1,1,0,0],
[0,1,1,0],
[0,0,1,0],
[0,0,1,1]
]
function findpath(x,y) {
if (x<0 || x>3 || y<0 || y>3) return false; //if it is outside of map
if (x==3 && y==3) return true; // if it is the goal (exit point)
if (map[y][x]==0) return false; //it is not open
map[y][x]=9; //here marking x,y position as part of solution path outlined by "9"
if (findpath(x,y-1) == true) return true;
if (findpath(x+1,y) == true) return true;
if (findpath(x,y+1) == true) return true;
if (findpath(x-1,y) == true) return true;
map[y][x]=8; //unmark x,y as part of solution path outlined by "8"
return false;
};
findpath(0,0);
The description of "it fails" is rarely, if ever, a useful error report.
In order for someone to help you, they need much more detail than that.
In this case, the import details came out of the JavaScript error console. You should always include any error messages in your question.
However, since your code was quite short I was able to cut-and-paste it into my console where I got the message:
RangeError: Maximum call stack size exceeded
This means that your function is recursing too deeply. You either
Have bad logic in your puzzle and you are recursing into the same values over and over again
The puzzle is too complicated and you can't solve it recursively like that.
You need to add console.log statements and observe what the code is doing and see why it is going so deep.
If it is a logic error, fix the logic error. (Hint: I'm pretty sure it is -- you never mark on the map where you've been so it freely goes back and forth and back and forth over the same spot).
If it isn't, then you need to use some more advanced trick to work around the recursion, such as using a generator function and storing the changes you do in the map separately.
Quick answer:
Its locking in a loop because the order of the checks.
Start from 0:0 then try 0:1. Then from 0:1 --"Ummm... 0:0 looks promising. Let's go there". So go back to 0:0... so it locks...
Try leaving backtracking last :
if(findpath(x+1,y)) return true;
if(findpath(x,y+1)) return true;
if(findpath(x,y-1)) return true;
if(findpath(x-1,y)) return true;
This get you out of the lock just by swapping the issue around. If you start from 3:3 trying to reach 0:0 you'll be locked again.
Whats missing its a way to mark visited squares.
I think you are trying to implement an a* algorithm
UPDATE:
Here is your idea working. Just added the backtracking checks you almost implemented.
<html>
<head>
</head>
<body>
<script>
var map = [
[1,1,0,0],
[0,1,1,0],
[1,1,1,0],
[1,0,1,1]
]
var goalx = 0;
var goaly = 3;
console.log();
function findpath(x,y) {
// illegal move check
if (x < 0 || x > (map[0].length -1) || y < 0 || y > (map.length - 1)) return false; //if it is outside of map
if (map[y][x]==0) return false; //it is not open
// end move check
if (x== goalx && y== goaly){
console.log('Reached goal at: ' + x + ':' + y);
return true; // if it is the goal (exit point)
}
if(map[y][x] == 9 || map[y][x] == 8)
return false;
console.log('Im here at: ' + x + ':' + y);
map[y][x]=9; //here marking x,y position as part of solution path outlined by "9"
if(findpath(x+1,y))
return true;
if(findpath(x,y+1))
return true;
if(findpath(x,y-1))
return true;
if(findpath(x-1,y))
return true;
map[y][x]=8; //unmark x,y as part of solution path outlined by "8"
return false;
};
findpath(3, 3);
</script>
</body>
</html>

Value from Math.random is causing problems when I call the function inside itself

This script is giving me problems. I've re written it several times but I'm missing something.
'questions' array refers to my objects. These objects are different questions with 'a' always being the correct answer.
The script works fine up to this point. The idea is to increment 'n' from 0 to scroll through my array, and provide the next question when a correct answer is clicked. 'x' is always the correct answer (it always holds 'a').
So I can increment 'n' just fine on correct guess; however, when I call the function 'a()' again, (after my alert 'hi' part), it is causing problems. I want to increment n, and call a() so I get the next question. Then I want to place the correct guess (x) in a random place (ie position 0, 1 or 2.)
Grateful for any help.
var questions = [q0,q1,q2,q3,q4,q5,q6,q7];
var n = 0;
function a(){
var y;
var z;
var x = Math.floor((Math.random() * 3))
if(x == 0){y = 1; z = 2}else if(x == 1){y = 0; z = 2}else{y = 0; z = 1}
$("#question_holder").text(questions[n].q);
$(".answer_holder").eq(x).text(questions[n].a);
$(".answer_holder").eq(y).text(questions[n].b);
$(".answer_holder").eq(z).text(questions[n].c);
$(document).ready(function(){
$(".answer_holder").eq(x).click(function(){
alert("hi");
n++;
a();
/*this area needs to get the next question by incrementing
n, then generate a different value to x, to place it
in a different position. which it does. however,
in subsequent questions, you can click the wrong answer as if
it's correct, ie not 'a' or 'x'.*/
});
});
};
Your logic is a bit strange here.. what you are trying to do is register a new click event every time a() runs. I think you want to register one click event for all answer_holder elements, and in the event handler check which element this is and handle it accordingly
Notice the following:
$(document).ready(function(){ - the function defined in this handler is supposed to run once your page is loaded.. I don't think you want to use it inside a(). It is usually only used in global scope (outside all functions)
$(".answer_holder").eq(x).click(function(){ - this event handler registers your function depending on the value of x. I suggest you register an event handler for all $(".answer_holder"), without depending on x (in the global scope). And inside that event handler (in the function), you check which element triggered the event (using $(this) - it returns the element that was clicked)
You have the $(document).ready() in the wrong place. Try something like this (caveat: this is completely untested):
function setupQuestion(n) {
var x,y,z;
x = Math.floor((Math.random() * 3))
if(x == 0){y = 1; z = 2}else if(x == 1){y = 0; z = 2}else{y = 0; z = 1}
$("#question_holder").text(questions[n].q);
$(".answer_holder").eq(x).text(questions[n].a).data('answer', 'a');
$(".answer_holder").eq(y).text(questions[n].b).data('answer', 'b');
$(".answer_holder").eq(z).text(questions[n].c).data('answer', 'c');
}
$(document).ready(function() {
var n = 0;
$('.answer_holder').click(function() {
if ($(this).data('answer') === 'a') { // Or whatever is the correct answer
n++;
if (n < questions.length) {
setupQuestion(n);
} else {
// Do something else, the test is finished
}
}
return false;
});
setupQuestion(n);
});
Note that I am not comparing on the text() function but rather the data() function. This is because the text as displayed to the user might be decorated in some way, making comparisons difficult. Simply using the answer index 'a' 'b' or 'c' is clearer.

Categories