Cannot access 'isColliding' before initialization/ divs colliding - javascript

I'm trying to make an egg catching game and found some code snippets online and wanted them to work together so the points go up by one when two divs are colliding. I am getting this error Cannot access 'isColliding' before initialization. Also I don't know if the div collision works since I can't test it because of the error, thanks in advance for any help!
Code:
let points = $('#points');
let countpoints = 0;
let overlap = isColliding("#basket", "#egg6");
if (overlap) {
function EggHitsBasket() {
countpoints++;
points.text("points:" + countpoints);
}
}
let isColliding = function (div1, div2) {
let d1Offset = div1.offset();
let d1Height = div1.outerHeight(true);
let d1Width = div1.outerWidth(true);
let d1Top = d1Offset.top + d1Height;
let d1Left = d1Offset.left + d1Width;
let d2Offset = div2.offset();
let d2Height = div2.outerHeight(true);
let d2Width = div2.outerWidth(true);
let d2Top = d2Offset.top + d2Height;
let d2Left = d2Offset.left + d2Width;
return !(d1Top < d2Offset.top || d1Offset.top > d2Top || d1Left < d2Offset.left || d1Offset.left > d2Left);
};

you're calling isColliding before it's been defined, it's the same that would happen in the following code snippet:
let x = y * 2
let y = 42
you need to either declare isColliding before you call it. Or use of a function declaration
function isColiiding(div1, div2) { ... }
rather than a function expression
let isColliding = function (div1, div2) { ... }

Related

I can't make setTimeout() work in my script

I'm making a memory game. It already sort of works, but when I choose two cards that aren't the same picture, they flip back instantly, without showing the user what is on the second card. I think I should use setTimeout(), but for now it only made my flipBack() function not work at all. Maybe, I am using it incorrectly or in the wrong place.
I tried putting both the flipBack() and setTimeout(flipBack, 5000) inside "else if", outside of it, outside of my revealCard() function.
I'm only getting "Uncaught TypeError: Cannot read properties of undefined (reading 'style')
at flipBack (memory game.js:61:35)" in the console. It seems that setTimeout cannot execute flipBack() or something like that.
let board = document.getElementById("board");
let score = document.getElementById("score");
let fails = document.getElementById("fails");
let cards = document.querySelectorAll(".card");
// add eventListener to every card
for (let i = 0; i < 6; i++) {
cards[i].addEventListener("click", revealCard);
}
let revealCounter = 2;
let imgAltArray = [];
let latestTwoRevealedCards = [];
let points = 0;
let wrongGuesses = 0;
function revealCard(event) {
if (revealCounter > 0) {
let cardImg = event.target.firstChild;
// make card "flip", so you can see the picture
cardImg.style.visibility = "visible";
imgAltArray.push(cardImg.alt);
latestTwoRevealedCards.push(cardImg);
console.log(imgAltArray);
revealCounter--;
// check if both cards have the same picture on them by comparing alt parameters
if (revealCounter == 0 && imgAltArray[0] === imgAltArray[1]) {
imgAltArray = [];
latestTwoRevealedCards = [];
points++
score.textContent = `Score: ${points}`;
revealCounter = 2;
}
else if (revealCounter == 0 && imgAltArray[0] !== imgAltArray[1]) {
wrongGuesses++;
fails.textContent = `Failed attempts: ${wrongGuesses}`
imgAltArray = [];
// make cards flip back
setTimeout(flipBack, 5000);
latestTwoRevealedCards = [];
revealCounter = 2;
}
}
}
// TIMEOUT DOESN"T WORK
function flipBack() {
for (let i = 1; i >= 0; i--) {
latestTwoRevealedCards[i].style.visibility = "hidden";
}
}
latestTwoRevealedCards[i] This element may be undefined

How to call identifier loop with nodejs

I'm trying to do this loop but there's something wrong.
Do I need to loop variable c also?
Just to explain, There's a table and child(i) changes every row.
SelectorT receives one sentence like: Now\nIs\n09:00\n4\n7
VariableM splits the sentence in array:
variableM[0] = Now
variableM[1] = is
variableM[2] = 09:00
variableM[3] = 4
variableM[4] = 7
So I need to return the first child(i), then run the next and return again.
const c = [1,2,3,4,5];
for (const property in c) {
const result = await page.evaluate(() => {
const selectorT = '#Main > div > div > div:nth-child(3) > div > div:nth-child('+i+') > section:nth-child(1) > div > div:nth-child(1)';
let variableM = document.querySelector(selectorT).innerText.split("\n")
let variableH = variableM[0];
let variableA[= variableM[1];
let variableT = variableM[2];
let variableS1 = parseInt(variableM[3]);
let variableS2 = parseInt(variableM[4]);
return {
variableH , variableA, variableT, variableS1, variableS2
}
})
console.log(result);
}
This doesn't look like a loop perhaps you mean for (i = 1; i < 5; i++)
there is a typo in this line let variableA=variableM[1];, also you are returning the values inside the loop they should be returned outside the loop

How to dynamically change width of a headline to ensure even line lengths

I'm trying to figure out how The Washington Post website forces the main headline to break so nicely no matter the actual text or screen width. From what I can determine, if the h1 has a class of headline, its width is dynamically calculated to achieve the effect. I know this is done with JavaScript and imagine it's not hard-coded so how is that width actually computed to be somehow cognizant of how the headline will break (preventing highly variable line lengths, orphans, etc.). I just can't track down the JS that's controlling this functionality.
Here is an example of the page loading normally:
And an example with the headline class removed:
(You can also notice the difference right when the page loads, presumabley just before the JavaScript kicks in.)
Thanks!
This is what you want. Obviously, because some words are longer than others, not all the lines have perfectly the same length. This code below preserves the amount of line breaks that are created by the browser. Then, it adjusts the line breaks' position to ensure a more or less even line lengths.
P.S.: Try running the below code without JS and you'll see the difference
let h1 = document.querySelector('h1')
let text = h1.textContent
let splitText = text.split(' ')
let getContentBoxHeight = elem => {
let elemStyle = window.getComputedStyle(elem)
let elemHeightWithPadding = parseInt(elemStyle.getPropertyValue('height'))
let elemPadding = parseInt(elemStyle.getPropertyValue('padding-top')) + parseInt(elemStyle.getPropertyValue('padding-bottom'))
return elemHeightWithPadding - elemPadding
}
let getContentBoxWidth = elem => {
let elemStyle = window.getComputedStyle(elem)
let elemWidthWithPadding = parseInt(elemStyle.getPropertyValue('width'))
let elemPadding = parseInt(elemStyle.getPropertyValue('padding-left')) + parseInt(elemStyle.getPropertyValue('padding-right'))
return elemWidthWithPadding - elemPadding
}
// return the number of line breaks created by the browser
let breakPointAmount = (() => {
let body = document.querySelector('body')
let dummyH1 = document.createElement('h1')
let oneLineHeight
let totalLineHeight = getContentBoxHeight(h1)
dummyH1.appendChild(document.createTextNode('M'))
body.appendChild(dummyH1)
oneLineHeight = getContentBoxHeight(dummyH1)
dummyH1.remove()
return Math.round(totalLineHeight / oneLineHeight) - 1
})()
// refine the number of line breaks created by the browser
let breakPoints = (() => {
let denominator = breakPointAmount + 1
let points = []
let h1Length
h1.style.width = 'max-content'
h1Length = getContentBoxWidth(h1)
h1.style.width = ''
for (let i = 0; i < breakPointAmount; i++) {
points.push(Math.round(h1Length * (i + 1) / denominator))
}
return points
})()
// determine where that same number of break points should go in text
let indexesToBreak = Array(breakPointAmount).fill(1)
let cumulativeLength = 0
let cumulativeText = ''
for (let i = 0; i < splitText.length; i++) {
let word = splitText[i]
let calculateLength = word => {
let body = document.querySelector('body')
let dummyH1 = document.createElement('h1')
let length
dummyH1.appendChild(document.createTextNode(word))
dummyH1.style.width = 'max-content'
body.appendChild(dummyH1)
length = getContentBoxWidth(dummyH1)
dummyH1.remove()
return length
}
cumulativeText += word + ' '
cumulativeLength = calculateLength(cumulativeText)
for (let j = 0; j < indexesToBreak.length; j++) {
if (indexesToBreak[j] === 1) {
indexesToBreak[j] = {
index: i,
currentMin: Math.abs(cumulativeLength - breakPoints[j])
}
} else {
if (cumulativeLength - breakPoints[j] < indexesToBreak[j].currentMin) {
indexesToBreak[j] = {
index: i,
currentMin: Math.abs(cumulativeLength - breakPoints[j])
}
}
}
}
}
// insert break points at updated locations into text
let newText = (function() {
let final = ''
let itbIndex = 0
for (let i = 0; i < splitText.length; i++) {
final += `${splitText[i]} `
if (indexesToBreak[itbIndex] && i === indexesToBreak[itbIndex].index) {
final += '<br>'
itbIndex += 1
}
}
return final.trim()
})()
// add text with new break points to page
h1.innerHTML = newText
h1 {
text-align: center;
}
<h1>Some Long Title that Requires Line Breaking To Ensure Even Line Lengths</h1>

Return a line of code

So I'm using JavaScript to make something to solve simple algebraic expressions. I've got everything for the math part done but I need to run a line of code again. So I've used a conditional branch to determine if the first side of the equation is equal to the second side. If it's equal then the value of the variable is given but if it isn't the same, then the variable is increased by one.
function Command() {
var FirstSide = document.getElementById("FirstLine").value;
var SecondSide = document.getElementById("SecondLine").value;
var evalLineOne = FirstSide;
var evalLineTwo = SecondSide;
var X = 1;
var MathLineOne = eval(evalLineOne);
var MathLineTwo = eval(evalLineTwo);
if (MathLineOne == MathLineTwo)
document.getElementById("Reply").innerHTML = X;
else {
X + 1;
}
So this is the code I've used. When using an algebraic expression where the value of X is not 1 the code simply doesn't work. I was assuming this was because I would need to rerun the code from the line of code which defines the value of "X". How would I go back to run this code?
Without making a lot of changes to your code, you could call the same function recursively like so:
var max = 9999999; //set this to whatever you want
function Command(X) {
if (typeof X === 'undefined') X = 1;
if (X > max) return;
var FirstSide = document.getElementById("FirstLine").value;
var SecondSide = document.getElementById("SecondLine").value;
var evalLineOne = FirstSide;
var evalLineTwo = SecondSide;
var MathLineOne = eval(evalLineOne);
var MathLineTwo = eval(evalLineTwo);
if (MathLineOne == MathLineTwo)
document.getElementById("Reply").innerHTML = X;
else {
Command(X+1);
}
}

In angular updating one variable inexplicably updates another

I am using angular and plotly to plot either the raw data or a moving average. I have the moving average working but I am running into an issue with assigning variables. I retrieve an array of user objects which each have an x and y key with arrays associated with them.
$scope.init=function(){
$rootScope.page='companyResults';
$scope.isPlotlyDone = false;
$scope.moving = false;
var refresh = function () {
incidentService.dayWiseTripsByUser(...).then(function (plotArray){
$scope.unaffectedPlot = plotArray;
$scope.movingAveragePlot = allMoving(plotArray);
console.log($scope.unaffectedPlot[0].y);
console.log($scope.movingAveragePlot[0].y);
});
};
refresh();
}
Im that code block, I would expect that $scope.unaffectedPlot[0].y and $scope.movingAveragePlot[0].y would have different arrays since I ran the latter through the following set of functions. The curious thing is that both $scope variables are synced, so if I run the second through allMoving the unaffectedPlot variable also gets smoothed and neither get synced obviously if I don't call allMoving. What am I missing about Angular? What is a good way to have a moving average work with a toggle? My plan is to show one variable or the other depending on if a button is clicked.
var d3_numeric = function(x) {
return !isNaN(x);
}
var d3sum = function(array, f) {
var s = 0,
n = array.length,
a,
i = -1;
if (arguments.length === 1) {
// zero and null are equivalent
while (++i < n) if (d3_numeric(a = +array[i])) s += a;
} else {
while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a;
}
return s;
};
var movingWindowAvg = function (arr, step) {
return arr.map(function (_, idx) {
var wnd = arr.slice(idx - step, idx + step + 1);
var result = d3sum(wnd) / wnd.length; if (isNaN(result)) { result = _; }
return result;
});
};
var allMoving = function(pltArray) {
var movingArray = [];
pltArray.forEach(function(plot){
var oneMoving = plot;
oneMoving.y = movingWindowAvg(plot.y, 5);
movingArray.push(oneMoving);
});
return movingArray;
}
This actually isn't an angular issue. I had to test it some since I didn't see what was going on either.
When you wrote
oneMoving.y = blah
you were actually altering the contents of plot for each element and in turn altering the contents of plotArray unintentionally (since plot is an object)
So you are only creating a reference variable when you say 'var onMoving = plot' )
To outright solve your problem you can clone plot but that isn't so clean of a process
One easy yet dirty way is
JSON.parse(JSON.stringify(obj))
from this thread
I threw together a shotty example that captures what was going wrong for you
var array = [{one:1, two:2},{one:1, two:2},{one:1, two:2}],
copyArray = array,
newArr = doStuff(array)
function doStuff(a) {
var otherNewArr = []
a.forEach(function(ae) {
var aVar = ae
aVar.one = 5
otherNewArr.push(aVar)
})
return otherNewArr
}
console.log(copyArray,newArr)
And to fix it just replace
var aVar = ae
with
var aVar = JSON.parse(JSON.stringify(ae))

Categories

Resources