Cannot Read Property CSS of Undefined? - javascript

var random;
var squareArray = [$('#square1'),$('#square2'),$('#square3'),$('#square4')];
var randomOrder = [];
var i = 0;
var j = 0;
function computerPlays() {
random = Math.floor(Math.random() * 4);
randomOrder.push(random);
makeSquareBlink();
userPlays();
}
function makeSquareBlink() {
setTimeout(function() {
var randomSquare = squareArray[randomOrder[i]];
randomSquare.css('opacity', '0.5');
setTimeout(function() {
randomSquare.css('opacity', '1');
}, 300);
i++;
if (i < randomOrder.length)
makeSquareBlink();
}, 500);
}
function userPlays() {
$('#square1').on('click', function() {
if (randomOrder[j] === 0) {
$('#square1').css('opacity', '0.5');
setTimeout(function() {
$('#square1').css('opacity', '1');
}, 300);
}
else {
$('#counter').text('!!');
makeSquareBlink();
}
});
$('#square2').on('click', function() {
if (randomOrder[j] === 1) {
$('#square2').css('opacity', '0.5');
setTimeout(function() {
$('#square2').css('opacity', '1');
}, 300);
}
else {
$('#counter').text('!!');
makeSquareBlink();
}
});
$('#square3').on('click', function() {
if (randomOrder[j] === 2) {
$('#square3').css('opacity', '0.5');
setTimeout(function() {
$('#square3').css('opacity', '1');
}, 300);
}
else {
$('#counter').text('!!');
makeSquareBlink();
}
});
$('#square4').on('click', function() {
if (randomOrder[j] === 3) {
$('#square4').css('opacity', '0.5');
setTimeout(function() {
$('#square4').css('opacity', '1');
}, 300);
}
else {
$('#counter').text('!!');
makeSquareBlink();
}
});
}
function reset() {
randomOrder = [];
i = 0;
}
$('button').click(function() {
reset();
computerPlays();
});
Why it isn't possible to change the css property of randomSquare variable in makeSquareBlink function? Is there any way to do it? Edit #001: Added the full code now Still not working help. Man stackoverflow wants more details wth should I type more ? FTHISS hit FML Fk everything letme post it bro. YOu're my last hope ://

I guess the goal of the game is to click the same square like the computer before. Right?
One problem with your code is that makeSquareBlink() increases i by one when the computer plays. Then when the user plays and hits the wrong square inside makeSquareBlink() you try to access randomOrder[i] which is in fact calling randomOrder[1] which returns undefined as randomOrder only contains one element so far. Thus squareArray[randomOrder[1]] gives back undefined and undefined.css(...) is the error you get.
You may fix it by adding a param to your makeSquareBlink() method so that it reads
function makeSquareBlink(p) {
setTimeout(function() {
var randomSquare = squareArray[randomOrder[p]];
randomSquare.css('opacity', '0.5');
setTimeout(function() {
randomSquare.css('opacity', '1');
}, 300);
p++;
if (p < randomOrder.length)
makeSquareBlink(p);
}, 500);
}
And then inside computerPlays you call it with i as param and inside userPlays with j. Haven't tested it but I don't want to solve your homework completely ;)
Also rethink the event listener attachment inside userPlays() as this will attach click listeners each time the method is called. I guess that's not what you want. Maybe try jQuerys one() method here. Or better restructure your code so that the click-listeners are attached only once.
BTW here a fiddle that helped me debug your code: https://jsfiddle.net/hm69ff0a/

Related

Shopify javascript/jQuery condition for scrollTop not working

I am making a javascript/jQuery condition to make the header drop down once a user clicks a button ("Buy Now") only when they can't see the header (200px down). My problem is that when the user scrolls more than 200px even if they scroll back up the code still exectues. Here is my code, thanks.
$(function() {
$(document).scroll(function() {
var y = $(window).scrollTop();
console.log(y);
if (y >= 200) {
$('.product__add-to-cart-button').click(function() {
// your statements;
$(".site-header").addClass("site-header--fixedd").removeClass("site-header--transparent");
$("#crazy-pineapple, #coco-twist, #crunchy-joy, #nutty-chia").css('margin-top', 143);
setTimeout(function() {
$(".site-header__cart-bubble").removeClass("bubblenormal").addClass("bubblevisible");
}, 300);
setTimeout(function() {
$(".site-header__cart-bubble").removeClass("bubblevisible").addClass("bubblenormal");
}, 700);
setTimeout(function() {
$(".site-header").removeClass("site-header--fixedd");
$(".site-header").addClass("site-header--fixeddd");
}, 1200);
setTimeout(function() {
$("#crazy-pineapple, #coco-twist, #crunchy-joy, #nutty-chia").css('margin-top', 0);
$(".site-header").addClass("site-header--transparent");
$(".site-header").removeClass("site-header--fixedd");
$(".site-header").removeClass("site-header--fixeddd");
}, 1600);
});
}
});
});
There are a few big NO's in your code.
You should NEVER add a event handler in a scroll/resize function! Why? Because you keep stacking them once you do the resizing/scrolling.
At the moment you apply multiply click events to .product__add-to-cart-button which I assume you don't want.
In addition there is no point to your scroll event at the moment. You can just create an if statement inside the click event if the scrollTop() is bigger than 200 and you can remove the scroll event all together.
In addition you must get the habit of caching objects if you plan to use them multiply times. Any object used more than once must be cached.
And here is how should your code look if we take in consideration all of the above remarks:
$(function() {
var $win = $(window);
var $siteHeader = $(".site-header");
var $siteHeaderCartBuble = $(".site-header__cart-bubble");
var $group = $("#crazy-pineapple, #coco-twist, #crunchy-joy, #nutty-chia");
$('.product__add-to-cart-button').on('click',function() {
if ($win.scrollTop() <= 200) {
return false
};
$siteHeader
.addClass("site-header--fixedd")
.removeClass("site-header--transparent");
$group.css('margin-top', 143);
setTimeout(function() {
$siteHeaderCartBuble
.removeClass("bubblenormal")
.addClass("bubblevisible");
}, 300);
setTimeout(function() {
$siteHeaderCartBuble
.removeClass("bubblevisible")
.addClass("bubblenormal");
}, 700);
setTimeout(function() {
$siteHeader
.removeClass("site-header--fixedd")
.addClass("site-header--fixeddd");
}, 1200);
setTimeout(function() {
$group.css('margin-top', 0);
$siteHeader
.addClass("site-header--transparent")
.removeClass("site-header--fixedd")
.removeClass("site-header--fixeddd");
}, 1600);
});
})

custom when statement not firing functions

I am trying to make a when statement but it is not working as planned. Basically its a function to call another function when try. First before I explain further here is the syntax
when(function() {
//code here
});
Now basically... Think this way.. We have a progressbar.. We also have a custom event such as...
var pBarEvent = document.createEvent('Event');
pBarEvent.initEvent('pbardone', true, true);
document.addEventListener('pbardone', function() {
//code here
});
//if progress bar reaches 100 dispatchEvent
if (document.querySelector(".progress-bar").style.width === 100 + "%")
{
document.dispatchEvent(pBarEvent);
}
Now that piece of code is an example. If the document loads and its for instance at 50% it wont trigger until you add another event such as keydown or click. I dont want to do that I want to do.... "when" progress bar width equals 100% trigger it. Thats basically what needs to happen. So here is the code for the when statement so far (keep in mind its not the best looking one. As I dont normally do this but I wanted to keep this dynamic and who knows someone who later wants to do this can look at this question)
when function
function when(func)
{
var nowActive = false;
if (!typeof func === 'undefined')
{
func = new Function();
}
if (func)
{
nowActive = true;
clearInterval(whenStatementTimer);
}
else
{
nowActive = false;
var whenStatementTimer = setInterval(function() {
switch(func)
{
case true:
{
nowActive = true;
when();
break;
}
case false:
{
nowActive = false;
when();
break;
}
}
}, 1000);
}
if (nowActive === true)
{
func();
}
}
Now this does not work when I go to try something like....
when(function() {
SmartLeadJS.SmartLeadEvents.customEvents.progressBarFull(function() {
alert("100%");
SmartLeadJS.SmartLeadAds.LeadView.ChromeExtension.General.DynamicStyles.$.style("body", "background", "black");
});
});
It does not trigger. I need help possibly getting this when statement to work. What am I doing wrong? What can I do to fix it? No errors get thrown but it never fires.
edit based on answer
Function tried
function when(currentValue)
{
try
{
var o = {};
o.currentValue = currentValue;
o.do = function(func)
{
if (!typeof func === 'undefined')
{
func = new Function();
}
if (this.currentValue)
{
func();
}
else
{
setTimeout(this.do(func), 100);
}
};
return o;
}
catch(e)
{
console.log(e);
}
}
used as
when(true).do(function() {
SmartLeadJS.SmartLeadEvents.customEvents.progressBarFull(function() {
alert("This divs going through changes!!");
SmartLeadJS.SmartLeadAds.LeadView.ChromeExtension.General.DynamicStyles.$.style(".div", "background", "black");
});
});
This does not work. It never fires. But if I use a onclick listener as such it fires
document.addEventListener("click", function() {
SmartLeadJS.SmartLeadEvents.customEvents.progressBarFull(function() {
alert("This divs going through changes!!");
SmartLeadJS.SmartLeadAds.LeadView.ChromeExtension.General.DynamicStyles.$.style(".div", "background", "black");
});
}, false);
function when(statement){
o={};
o.statement=statement;
o.do=function(func){
awhen(this.statement,func);
};
return o;
}
function awhen(statement,func){
if(eval(statement)){
func();
}else{
window.setTimeout(function(){awhen(statement,func);},100);
}
}
Use:
when("true").do(function(){});
It works now :) . Its important to put the condition in ""!

during scroll call a function only once

I have a counter on a page. When I scroll to it I need start it only once. but now it starts twice during next scroll. Thank's.
var quit = false;
$(window).scroll(function() {
// ...
something();
function something() {
if (quit == true) {
return;
}
quit = true;
setTimeout(function() {
$(begin).html(2002);
}, 500); // this function must be call only once
}
}
}
$(document).on('scroll', function() {
something();
$(document).off('scroll');
});
this solution helped me https://github.com/HubSpot/odometer/issues/35
my second mistake was creating "new odometer" object

Hide DIVs after function has completed his task

I wrote a piece of code that auto replies to user text input.
An automated "live chat" so to say.
Though when the script runs out of responses I want it to disable the subit form and button, I don't really have any clue on how to do such a thing.
My code:
<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
$(document).ready(function() {
$("#typing").hide();
var n = "You:<br>";
var o = $('#outputWindow');
var i = $('#inputWindow');
var s = $('#sendButton');
var t = $('#typing');
var r = -1;
//arrays
var msg = ['msg1', 'msg2', 'msg3'];
//fire send events
$(s).click(function() {
runAI();
});
$(i).keydown(function(e) {
if (e.keyCode == 13) {
runAI();
}
});
function runAI() {
if (i.val().length > 0) {
r = r + 1;
o.html(o.html()+n+$("#inputWindow").val()+"<br><hr>" );
setTimeout(function(){ $("#typing").show(); }, 3000);
setTimeout(function(){ o.html(o.html()+"Username:<br>"+msg[r]+"<br><hr>") }, 7000);
setTimeout(function(){ $("#typing").hide(); }, 8000);
i.val('');
i.focus();
}
}
i.focus();
});
});//]]>
</script>
The idea is to hide the submit form and button after (in the case) the script has responded with: msg1, msg2 and msg3.
If anyone can help, that'd be great !
This will do that. Place at the bottom of the runAI() function.
this will check r+1 each time runAi() is invoked. When it detects that it's greater than or equal to the message array length it will hide the user input possibilities after the last message is sent.
function runAI() {
if (i.val().length > 0) {
r = r + 1;
o.html(o.html()+n+$("#inputWindow").val()+"<br><hr>" );
setTimeout(function(){ $("#typing").show(); }, 3000);
setTimeout(function(){ o.html(o.html()+"Username:<br>"+msg[r]+"<br><hr>") }, 7000);
setTimeout(function(){ $("#typing").hide(); }, 8000);
if (r+1 >= msg.length)
{
$('#inputWindow').hide();
$('#sendButton').hide();
return true; // end the function here;
}
else
{
i.val('');
i.focus();
}
}
}
When r reaches a length greater than or equal to the length of the array the input and button is hidden.
Well, simply use CSS to hide it:
$(<your object>).css('display', 'none');
use this for every object you want to hide. Go to www.w3schools.com and check out the posible values for the display property.

JavaScript/jQuery - Add Delay between Add and Remove Class and next function [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
jquery add a fade to an .addClass
Here is my jsFiddle example: http://jsfiddle.net/sLzGc/
I am trying to create an effect where it appears options 1 through 3 are being rotated. Every 1.2 seconds the green class is removed from the option that has it and the green class is added to the next option. The idea is that the rotation through the three options happens five times (i<5) before the final function alert('Finished') is executed.
I'm trying to use setTimeout(), but I'm open to using .delay(), another jQuery function, or some other option.
Here is my JavaScript/jQuery:
alert('Start');
sampleFunction();
function sampleFunction() {
for (i=0; i<5; i++) {
setTimeout(function() {
$('#option2').addClass('green');
$('#option1').removeClass('green');
},1200);
setTimeout(function() {
$('#option3').addClass('green');
$('#option2').removeClass('green');
},1200);
setTimeout(function() {
$('#option1').addClass('green');
$('#option2').removeClass('green');
},1200);
}//end for loop
}
alert('Finished');​
My whole example is on jsFiddle: http://jsfiddle.net/sLzGc/
Thanks for any help or insight you can offer!
Here's how I would approach the problem:
​(​function() {
var options = [$("#option1"), $("#option2"), $("#option3")],
cycles = 5,
i = 0,
$last = $(null);
(function next() {
if(i < cycles * options.length) {
$last.removeClass("green");
$last = options[i % options.length].addClass("green");
i++;
setTimeout(next, 1200);
} else {
$last.removeClass("green");
alert("finished!"); //do any other "we're done" stuff here.
}
}());
}());​
It's pretty straightforward and the cool part is that you can add elements to the list of elements to cycle through pretty easily (just add them to options). You can also set the number of cycles if you want. I didn't make the class or delay length a variable, but that would be very simple in case you wanted to do that.
You can see a demo here:
http://jsfiddle.net/D7SR8/
You might also consider having a callback function at the end and putting the alert() in there. That would be more reusable.
If you are wanting to use setTimeouts then your code could look something like this:
var iteration = 0;
alert('start');
rotateColors();
function rotateColors() {
setTimeout(function() {
$('#option2').addClass('green');
$('#option1').removeClass('green');
setTimeout(function() {
$('#option3').addClass('green');
$('#option2').removeClass('green');
setTimeout(function() {
$('#option1').addClass('green');
$('#option3').removeClass('green');
iteration += 1;
if(iteration < 5)
rotateColors();
else
alert('finished');
},1200);
},1200);
},1200);
}
Live DEMO
alert('Start');
var varobj=0;
sampleFunction();
function sampleFunction() {
setTimeout(function() {
$('#option2').addClass('green');
$('#option1').removeClass('green');
},1200, setTimeout(function() {
$('#option3').addClass('green');
$('#option2').removeClass('green');
},1200,setTimeout(function() {
$('#option1').addClass('green');
$('#option3').removeClass('green'); if(varobj<5){varobj=varobj+1;sampleFunction();}else{ alert('finished');}
},1200);););}
this is a approch how call function after execution of other in settimeout
I use both setTimeout() and setInterval() to do this and then clear the interval after 5 executions. If you want them to all end on a certain color or any other modifications let me know! I just modified it to loop through how you asked.
http://jsfiddle.net/sLzGc/9/
sampleFunction();
function sampleFunction() {
alert('Start');
$('#option1').addClass('disabled');
var i = 0;
var shift = function() {
setTimeout(function() {
$('#option1').toggleClass('disabled');
$('#option2').toggleClass('disabled');
}, 0);
setTimeout(function() {
$('#option2').toggleClass('disabled');
$('#option3').toggleClass('disabled');
}, 400);
setTimeout(function() {
$('#option3').toggleClass('disabled');
$('#option1').toggleClass('disabled');
}, 800);
};
var interval = setInterval(function() {
++i;
if (i == 5) {
clearTimeout(interval);
alert('Finished');
} else {
shift();
}
}, 1200);
shift();
}​

Categories