Unexpectedly passing integer by reference? - javascript

I'm having some issues with this. For some reason, updateCurrentItem is always called with the same parameter regardless.
function updatePromoList(query) {
query = query.toUpperCase();
clearCurrentList();
var numItems = 0;
currentItem = 0;
result_set = cached[query.charAt(0)][query.charAt(1)][query.charAt(2)];
for(i in result_set){
if(numItems >= NUMBER_MATCHES){
$("<li/>").html("<span style='color: #aaa'>Please try to limit your search results</span>").appendTo("#possibilities").mouseover(function(event){ updateCurrentItem(numItems+1); });
break;
}
promo = result_set[i];
found_number = false;
if (!promo.client)
found_number = (promo.prj_number.toString().substr(0,query.length) == query) ? true : false;
if (query.length >= MATCH_NAME) {
if(promo.prj_name && typeof promo.prj_name == 'string'){
found_name = promo.prj_name.toUpperCase().indexOf(query);
} else {
found_name = -1;
}
if (promo.client)
found_client = promo.client_name.toString().indexOf(query);
else
found_client = -1;
} else {
found_name = -1;
found_client = -1;
}
if(found_client >= 0) {
var thisIndex = numItems+1;
console.log("setting", thisIndex);
$("<li/>").text(promo.client_name).bind('click',function(e){ updatePromoChoice(e,promo); }).appendTo("#possibilities").mouseover(function(event){ updateCurrentItem(thisIndex); }); } else if(found_name >= 0 || found_number) { var thisIndex = numItems+1;
console.log("setting", thisIndex);
$("<li/>").text(promo.prj_number+": "+promo.prj_name).bind('click',function(e){ updatePromoChoice(e,promo); }).appendTo("#possibilities").mouseover(function(event){ updateCurrentItem(thisIndex); });
}
if(found_number || found_client >= 0 || found_name >= 0){
numItems++;
}
}
}
function updateCurrentItem(i){
currentItem = i;
console.log("updating to", i);
}
The results of running this are:
setting 0
setting 1
setting 2
setting 3
setting 4
setting 5
setting 6
setting 7
setting 8
setting 9
setting 10
setting 11
setting 12
setting 13
then when I move my mouse over the content area containing these <li>s with the mouseOver events, all I ever see is:
updating to 4
Always 4. Any ideas?

You're creating a closure but it's still bound to the numItems variable:
function(event){ updateCurrentItem(numItems+1); }
What you should do is something like this:
(function(numItems){return function(event){ updateCurrentItem(numItems+1); }})(numItems)
Edit: I think I might have the wrong function but the same principle applies:
function(event){ updateCurrentItem(thisIndex); }
should be
(function(thisIndex)
{
return function(event){ updateCurrentItem(thisIndex); }
})(thisIndex)

Related

useState in while cause infinite loop

I trying to make Blackjack game in React. A bot has got 2 cards at start. If user stands, and bots card value is less than 17, it should draw addictional card, but then program cause infinite loop. This is my code:
const [playerCards, setPlayerCards] = useState<Card[]>([]);
const shuffledDeck = shuffleDeck(deck);
const [dealerCards, setDealerCards] = useState<Card[]>([]);
const shuffleDeck = (deck: Card[]): Card[] => {
for (let i = deck.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[deck[i], deck[j]] = [deck[j], deck[i]];
}
return deck;
};
const handleStand = () => {
if (gameState === 'playing') {
console.log(shuffledDeck[playerCards.length + dealerCards.length]);
while(getHandValue(dealerCards) < 17) {
setDealerCards([
...dealerCards,
shuffledDeck[playerCards.length + dealerCards.length],
]);
}
}
let dealerHandValue = getHandValue(dealerCards);
const playerHandValue = getHandValue(playerCards);
if (dealerHandValue > 21 || dealerHandValue < playerHandValue) {
setGameState('won');
setPlayerBalance(playerBalance + currentBet);
} else if (dealerHandValue > playerHandValue) {
setGameState('lost');
setPlayerBalance(playerBalance - currentBet);
} else {
setGameState('tied');
}
};
const getHandValue = (cards: Card[]): number => {
let value = 0;
let numAces = 0;
for (const card of cards) {
if (card.rank === Rank.Ace) {
numAces++;
} else if (card.rank === 'J' || card.rank === 'K' || card.rank === 'Q') {
value += 10;
} else {
value += Number(card.rank);
}
}
while (numAces > 0) {
if (value + 11 > 21) {
value += 1;
} else {
value += 11;
}
numAces--;
}
return value;
};
The goal is to make bot draw a cards until value of his cards will be at least 17.
As discussed in the comments, using setDealerCards inside the while loop can be problematic. Setting the state causes a re-render to the component and may trigger the function again depending on it's use.
Another problem may be that since React schedules it's updates you may not get the most updated state every time you set the state again in the while loop.
So this might help
const handleStand = () => {
let newDealerCards = [...dealerCards];
if (gameState === 'playing') {
while(getHandValue(newDealerCards) < 17) {
newDealerCards =
[...newDealerCards, shuffledDeck[playerCards.length + newDealerCards.length]];
}
setDealerCards(newDealerCards);
}
let dealerHandValue = getHandValue(newDealerCards);
const playerHandValue = getHandValue(playerCards);
if (dealerHandValue > 21 || dealerHandValue < playerHandValue) {
setGameState('won');
setPlayerBalance(playerBalance + currentBet);
} else if (dealerHandValue > playerHandValue) {
setGameState('lost');
setPlayerBalance(playerBalance - currentBet);
} else {
setGameState('tied');
}
};
We make the new newDealerCards variable to spread dealerCards state, we then do the while loop with your condition and update newDealerCards accordingly. When we're done, only then we set the state again with the updated variable we made and thus we avoid calling setDealerCards multiple times inside the while loop.

Placing the element at last of sorted list

I am sorting on the basis of doc_status the items using sort function.
Everything is fine just one case when doc_requirment =0 I want it to be last element of items irrespective of its doc_status.
var lockStatus = 2;
var items = [
{ doc_requirement :4, doc_status :0 },
{ doc_requirement: 3,doc_status:1 },
{ doc_requirement:0,doc_status :2},
{doc_requirement: 3 ,doc_status :3},
{ doc_requirement: 1,doc_status : 0},
];
if(lockStatus == 2){
var finalSortedDocuments = items.sort(function(firstDoc,secondDoc){
var order = [2,0,1,3];
if(firstDoc.doc_status == secondDoc.doc_status && firstDoc.doc_status ==0){
var orderNew = [ 1,4];
return orderNew.indexOf(firstDoc.doc_requirement) - orderNew.indexOf(secondDoc.doc_requirement);
}
return order.indexOf(firstDoc.doc_status) - order.indexOf(secondDoc.doc_status);
});
}
You just have to add one more criteria to the sorting function:
items.sort(function(firstDoc, secondDoc) {
if(firstDoc.doc_requirement == 0 && secondDoc.doc_requirement != 0) return 1;
else if(firstDoc.doc_requirement != 0 && secondDoc.doc_requirement == 0) return -1;
// Then sort by doc_status
var order = [2,0,1,3];
return (order.indexOf(firstDoc.doc_status) - order.indexOf(secondDoc.doc_status));
});
Try something like this-
items.sort(function(doc1,doc2){
if(doc1.doc_requirement=== 0){
return 1;
}
if(doc2.doc_requirement=== 0){
return -1;
}
return doc1.doc_status > doc2.doc_status;
})
You can try like this
var finalSortedDocuments = items.sort(function(firstDoc,secondDoc){
if(firstDoc.doc_status== 0){
return(1);
}
if(secondDoc.doc_status== 0){
return(-1);
}
return firstDoc.doc_status-secondDoc.doc_status;
});

Matching variables not updating

The concept is simliar to a slider. Here is the JsFiddle
Each section is set to:
visibility: hidden;
until assigned the "anim-in" class. The issue is with var $currSection and $nextSection that need the var $rightCounter to correctly evaluate.
var $currSection = $rightCounter;
var $nextSection = $rightCounter + 1;
$rightCounter is updated in the counter function:
function counter (event){
var $counterSelect = $(this).attr('id');
if ( $counterSelect == "right") {
if ( $rightCounter >= 0 && $rightCounter <= 4){
$rightCounter += 1;
console.log($rightCounter);
if ($leftCounter <= 0) {
$leftCounter = 0;
console.log($leftCounter);
}
else {
$leftCounter -= 1;
console.log($leftCounter);
}
}
}
else {
if ($leftCounter >= 0 && $leftCounter <= 4){
$leftCounter += 1;
console.log($leftCounter);
if ($rightCounter <= 0) {
$rightCounter = 0;
console.log($rightCounter);
}
else {
$rightCounter -= 1;
console.log($rightCounter);
}
}
}
animOut();
return $rightCounter;
};
The animOut function uses $currSection and $nextSection to redistribute classes, but they are not updating with the $rightCounter?
Note: the console logs are there to show what the vars are evaluating to

How do you increment the value of a variable based on a substring in Javascript?

I'm trying to create a script where I validate a phone number without too much regex in my scripts. So far I have:
var phone = document.PizzaForm.phone.value;
var num = [1,2,3,4,5,6,7,8,9,0];
var delim = ["(" , ")" , "-" , "."];
var incr = 0;
var status = 0;
if (document.PizzaForm.phone.value.substring() = num) {
incr++;
return;
}
if (incr < 10) {
var statustext=1;
alert("Phone data is missing.");
}
if (document.PizzaForm.phone.value.substring[0,4,8] != num || document.PizzaForm.phone.value.substring[0,4,8] != delim) {
(status var statustext=1;
alert("Phone data is incorrect.");)
}
if (statustext == 0) {
return true;
}
else {
return false;
}
}
but it's not working. I'm trying to increment my incr everytime there is a number so if incr < 10, i get a message that there aren't enough numbers. Anyone see where I might be going wrong?
In your below if condition :
if (document.PizzaForm.phone.value.substring[0,4,8] != num || document.PizzaForm.phone.value.substring[0,4,8] != delim) {
(status var statustext=1;
alert("Phone data is incorrect.");)
}
Declare your statustext set globally. Not inside the if condition.
status set to 1 directly.
change your logic as below
var statustext = 0;
if (document.PizzaForm.phone.value.substring[0,4,8] != num || document.PizzaForm.phone.value.substring[0,4,8] != delim) {
status = 1;
statustext = 1;
alert("Phone data is incorrect.");)
}

after a variable change to 1, call something.. javascript

So Basicly if i click the burtton, it should change the variables to 1.
However, it dosen't print out "It's happening now" as it should.
Could someone please explain what's wrong with this??
Best regards daniel.
var reg_uname_done = 0;
var reg_pword1_done = 0;
var reg_pword2_done = 0;
var reg_email_done = 0;
$("#first_nav_bar li:first").click(function(event) {
reg_uname_done = 1;
reg_pword1_done = 1;
reg_pword2_done = 1;
reg_email_done = 1;
});
if(reg_pword1_done === 1 && reg_pword2_done === 1 && reg_email_done === 1 && reg_uname_done === 1) {
console.log('its happening now');
}
The reason why this is not happening is b/c the js file is going down, and you haven't "clicked" the <li> element yet, therefore your variables are still equal to 0. You have to set a function inside of that event.
See fiddle
var reg_uname_done = 0;
var reg_pword1_done = 0;
var reg_pword2_done = 0;
var reg_email_done = 0;
$("#first_nav_bar li:first").click(function (event) {
reg_uname_done = 1;
reg_pword1_done = 1;
reg_pword2_done = 1;
reg_email_done = 1;
check();
})
function check() {
if (reg_pword1_done === 1 && reg_pword2_done === 1 && reg_email_done && reg_uname_done) {
console.log('its happening now');
}
}

Categories