Giving user 2nd attempt - javascript

In my spelling game there is a grid with words in to spell. The user is given a highlighted area in the grid and some clues like a picture and a sound of a word like "cat" for example.
The user then is supposed to click the corresponding letters on the side of the grid to achieve the correct answer.
If the user correctly spells the word, the word fades out to show a section of the image behind. The aim of the game is to spell all the words correctly and reveal the the whole image
If the user gets the spelling of a word wrong, there is a style applied to the word that makes it glow red, this should then fade after 2 seconds and he/she should be given another attempt to try to spell the word.
Currently when a word is spelt incorrectly the style appears to make the word glow red, but it does not go after 2 seconds and the user is not given another shot at the word.
I have used this line of code to get rid of the style's after 2 seconds...
$('.drop-box.spellword').removeClass('wordglow wordglow3 wordglow4', "2000");
For some reason it doesn't work
The script that adds the styles is here...
if (!$('.drop-box.spellword:not(.occupied)').length) {
var wordIsCorrect = 0;
$('.drop-box.spellword').each(function() {
if ($(this).attr("data-letter") == $(this).find("div").attr("data-letter")) {
wordIsCorrect++;
}
});
console.log(wordIsCorrect);
console.log($('.drop-box.spellword').length);
if ($('.drop-box.spellword').length == wordIsCorrect) {
$('.drop-box.spellword').addClass('wordglow2');
$(right).val('Well Done!');
$(right).show();
audioS.play();
$('.counter').html(completeWords + '/6').show();
$(wrong).hide();
$('.minibutton').prop('disabled', false);
} else {
$('.drop-box.spellword').addClass("wordglow4").css('color', 'transparent');
$(wrong).val('Try Again');
$('.minibutton').prop('disabled');
$(wrong).show();
audioF.play();
$('.counter').html(completeWords + '/6').show();
$(right).hide();
$('.minibutton').prop('disabled', true);
}
To give the user another attempt I thought you may use something like this..
$('.drop-box.spellword').splice(0, $('.drop-box.spellword').length);

You have to use javascript's setTimeout function, for jQuery's removeClass doesn't accept an argument for timeouts.
Also, removeClass only removes one class at the time, so you have to chain them.
try replacing this:
$('.drop-box.spellword').removeClass('wordglow wordglow3 wordglow4', "2000");
for this:
setInterval(
function(){
$('.drop-box.spellword').removeClass('wordglow').removeClass('wordglow3').removeClass('wordglow4');
}, 2000
);

To remove the class after 2 seconds, use this:
setTimeout(function(){
$('.drop-box.spellword').removeClass('wordglow wordglow3 wordglow4')
},2000)
removeClass doesn't accept any argument for a delay before removing a class.
I'm not sure what you're trying to do with the splice, but one error I can see is that you forgot a $ before ('.drop-box.spellword') inside the splice() call.

jQuery's removeClass doesn't support passing a second parameter to be considered as a timer, but you can do this manually using setTimeout():
setTimeout(function() {
$('.drop-box.spellword').removeClass('wordglow wordglow3 wordglow4');
}, 2000);
As for giving the user another attempt, why are you using splice()? Isn't each element with class drop-box.spellword a text input with individual strings? In that case you can use $('.drop-box.spellword').val('') to clear all inputs of that class.
Edit:
To remove the classes from the other children modify it to something like this:
$('.drop-box.spellword').removeClass('wordglow4');
$('.drop-box.spellword').children('.ui-widget-content').removeClass('wordglow')
The jsFiddle is really large so I'm not sure where wordglow3 gets applied, but the principle is the same, find the element and removeClass() from it, all in your timed function.

Related

I have managed to find a way to get text of my slides by using each but how do I get it to display my can products not text?

I have found a way to display text on each of my empty slides. so far, so good. But at you can see in my codepen project, there's a can displaying on the first slide. Instead of the text 'Hello' on each of my slides, how do I display a loop of cans on each slide?
https://codepen.io/Rosstopherrr/pen/GVRvxJ
I had it like this thinking it will show all cans in each slide but it doesn't show any cans...
$('#products article').each(function() {
$(this).append(initApp())
});
what am I doing wrong?
$('#products article').each(function() {
$(this).append('hello')
});
EDIT - progress so far
so in the each.function(index) - I can add the index, and then in initApp(index) - I can add index. and then in the initApp function I can adjust so that bottle[index] gets selected and then added.
But nothing seems to work?? What am I doing wrong?
I know there is a bunch of ways I can do this.
Like could I skip the initApp() function and add all the code in the .each(function() { my code to append bottle})??
in initApp() you define const $container = getElement('.container'); getElement function calls document.querySelector(selector); that returns just the first element that matches the selector, in this case the first div with class .container in the first article tag. That's the first error.
In order to add a bottle to each container you need a list of .containers, that you can obtain with $containers = [...document.querySelectorAll('.container')]
once you have all .container you can integrate the forEach function call, maybe in this way
[$bottle1, $bottle2, $bottle3].forEach(($bottle, i) => {
$bottle.classList.add('bottle' + i);
$containers[i].append($bottle)
});
it's possible that you will still not find the bottles like in the first item; that's because the single .bottle1, .bottle2, .bottle3 etc have wrong letf and top css properties; in addition, the .side divs miss the background-image property.

Reverting to original element ID

I have li blocks which onclick will change class ID as follows:
onclick = "document.getElementById('procblock1').id = 'procblock1Clicked';"
"document.getElementById('procblock2Clicked').id = 'procblock2';"
"document.getElementById('procblock3Clicked').id = 'procblock3';"
"document.getElementById('procblock4Clicked').id = 'procblock4';"
The line document.getElementById('procblock2Clicked').id = 'procblock2'; should revert any clicked elements (blocks) back to their original ID names.
The code works for changing the original id to the clicked id but doesn't have any effect in reverting previously clicked to the original as per lines 2,3 & 4.
I have searched hard for similar questions but can find nothing that covers this specific issue.
#Matthias - I acted upon your advice and came up with a very simplified jquery solution :
`$(function() {
$(".showinfo").click(function() { //using class instead of ID
$(".showinfo").removeClass("clicked"); //Remove all existing clicks
$(this).addClass("clicked"); //add the class to the clicked element });
});`
Posted solution in case anyone else has same query. Your help was appreciated.
If this really is part of the code you're using lines 2-4 won't work; onclick will only handle the first line. You should wrap it as a function to be called onclick, like onclick = "doStuff()" and add a function doStuff () {/* your code here */}. But that's just guessing as you only provide some part of the code in question.
In addition would be good to know what you want to achieve - in case you want to mark clicked elements, it would be a cleaner approach to add a class, e.g. "clicked" or "active", that you simply remove later on instead of changing ids.

how to traverse a loop in javascript

I've three boxes ,each one fades in, shakes then fades out.
The ID of each one reserved in an array and a loop traverses them,the loop works correctly but just shows the first item!.
I've checked the javascript with different ways using for loop,delay instead of setTimeout
.I've also tried to add the boxes in html not in js file
(if it casued any problems!!!!!!!!)
Here is my code:
http://jsfiddle.net/#&togetherjs=QLRAbwHOR7
could any one help me please???!!
$(document).ready(function(){
var imgID= ['red','green','blue'];
$.each(imgID, function(i) {
$(".image").append('<div class="box"fid="'+i+'">'+imgID[i]+'</div>');
$('#'+i).fadeIn(500);
setTimeout(function(){
$('#'+i).effect( "shake",{times:5}, 1000 ).fadeOut(500);
}, 1000);
alert("ID: "+i);
});
});
Based on the code in the question (not the jsfiddle link) I think the problem is on this line
$(".image").append('<div class="box"fid="'+i+'">'+imgID[i]+'</div>');
^
should be
$(".image").append('<div class="box" id="'+i+'">'+imgID[i]+'</div>');
^ remove the 'f'
here is my fiddle results
http://jsfiddle.net/jasrus/ZqayT/
Update Also make sure that you include jQueryUI because effect is not part of the jquery library

jQuery hide - how to know if element has started to hide but still visible?

I have form where are inputs. Answers and visibility of the inputs may affect visibility of other inputs which are located below it.
I have javascript function which is called when value of some of the inputs have changed. The function is going through every input and checking it’s visibility and answer. Based on that information it may hide or show some other inputs. One loop is enough, because visibility of the element can’t affect visibility of previous elements.
$(".test_this").each(function() {
var id_number = $(this).attr("id").split("_")[1];
var tested_id = parseInt(id_number) + 1;
if ($(this).find("input:checked").val() != 1 || $(this).is(":hidden")) {
if ($("#element_"+tested_id).is(":visible")) {
$("#element_"+tested_id).hide();
}
}
else {
if ($("#element_"+tested_id).is(":hidden")) {
$("#element_"+tested_id).show(500);
}
}
});
My code is working well, but I would like to add duration to hide-function, but then my visibility check fails. Is it possible to know if some element has started to hide but is still visible?
I don’t want to use callback function, because it is executed after the delay. Second, I don’t want to change values of hidden inputs. One solution is to add some extra class which existence would be possible to check, but is there some better way to do this?
My code in Fiddle: http://jsfiddle.net/nmUPj/3/
For the further information, my actual code is lot more complicated and getting information about form from MySQL and generating form and javascript code with PHP.
You can check if the element is still animating by:
$("#element_"+tested_id).is(":animated")
Alternatively, you can give a callback function to your show(),
$("#element_"+tested_id).show(5000, function(){
alert('animation completed');
});

jQuery smooth change of innerHTML

I have the code below working like a charm:
var div = $('#div');
div.html('<div>one line</div><div>another line</div>');
div.slideDown('slow');
But the problem comes when I need to change the content (the number of lines):
div.html('<div>one line replacement</div><div>another line replacement</div><div>third line</div>')
This transition is too fast. How to animate this?
You can add an invisible span to the html:
<span class="foo" style="display: none">some other lines</span>
And then fade them in:
$("span.foo").fadeIn('slow');
Going by your edit, you may also want to consider:
div.slideUp('slow'); // you may want this to be 'fast'
div.html('some other lines');
div.slideDown('slow');
A wrinkle on Daniel Sloof's answer:
div.fadeOut('fast', function() {
div.html(html);
div.fadeIn('fast');
}
This will ensure your first animation is complete before proceeding. In my current case at least, fading makes a nicer experience than sliding.
Maybe if you put the extra lines into a div with display:none style, then you can fade in that div, something like this (concept - code not tested):
div.html("<div id='next_line' style='display:none'>some other lines</div>");
$("#next_line").fadeIn('slow');
If you want to make it take a certain time, then:
div.slideDown(numberOfMilliseconds);
Thomas mentioned "slideDown(numberOfMilliseconds)". I have tried it and jquery's doc defined the speed in milliseconds is the time taken to execute the amimation.
In that case, 1 line or 10 lines will take the same amount of time to slide. If you know the number of line, perhaps you can add in a multiplier, e.g. slideDown(lineCount * speedInMS)

Categories