I'm trying to create a quiz in the style of Buzzfeed. Is there a way to deactivate a part of the page when the user clicks on an answer, so that users can no longer click on alternative options of the same question and thus distort the final score of the test.
I've found some similar topics here and here but I don't want to add overlays and I'm not using inputs in my code so I was wondering if there is an alternative route.
I created a codepen here http://codepen.io/kkoutoup/pen/ByGEoQ
$(document).ready(function(){
//create an array to store correct answers
var totalCorrect = [];
$('li').click(function(){
//caching variables
var $parent = $(this).parent();
var $span = $(this).find('.fa');
//check for .correct class
//if yes
if($(this).hasClass('correct')){
//add .correctAnswer class
$(this).addClass('correctAnswer');
//find next span and change icon
$span.removeClass('fa fa-square-o').addClass('fa fa-check-square-o');
//reduce opacity of siblings
$(this).siblings().addClass('fade');
//show answerText
var $answerReveal= $parent.next('.answerReveal').show();
var $toShowCorrect = $answerReveal.find('.quizzAnswerC');
var $toShowFalse = $answerReveal.find('.quizzAnswerF');
$toShowCorrect.show();
$toShowFalse.remove();
//add 1 to total correct array
totalCorrect+=1;
//get array's length
var $finalScore = totalCorrect.length;
console.log($finalScore);
}else{
//add .wrongAnswer class
$(this).addClass('wrongAnswer').addClass('fade');
//change icon
$span.removeClass('fa fa-square-o').addClass('fa fa-check-square-o');
//reduce opacity of its siblings
$(this).siblings().addClass('fade');
//show wrong Message
var $answerReveal= $parent.next('.answerReveal').show();
var $toShowCorrect = $answerReveal.find('.quizzAnswerC');
var $toShowFalse = $answerReveal.find('.quizzAnswerF');
$toShowCorrect.remove();
$toShowFalse.show();
//locate correct and add respective class
$parent.find('.correct').addClass('correctAnswer');
};
});
});//end dom ready
Any ideas?
Thanks
What we're doing is removing the click function from the click event of the selected set of options - in this case, all the children of the elements parent. Thus when the user tries to click again, the click function would not be called on the click event.
Add the following line in click function because we want to trigger the disable as soon as any option is clicked on
$(this).parent().find('li').off("click");
Here is the updated codepen
Be aware of one thing - .off('click') removes all event listeners of type click from the element. If you want remove just this function, assign the function to a variable and then use the variable in the on and off calls. Like below:
event_fce = function(event) {
//do stuff here
$(this).off('click', event_fce);
}
$('li').on('click', event_fce);
You could turn off click as soon as one option is selected (right/wrong), like below:
Codepen updated
$(this).siblings().off("click"); //add this to where appropriate, such as either in `if` or `else` or both.
Related
I am working with caph framework and i trying to click in every id focused
$(event.currentTarget).on('selected',function() {
var value = $(this).prop('id');
$('#' + $(this).prop('id')).trigger('click');
});
You can access the event target with $(this) in jQuery. To automatically click on the selected element you could do
$(event.currentTarget).on('select', function() {
$(this).click()
// or $(this).trigger('click')
};
If I understand your question right though you're asking how to click every element with a given ID - please note that you should be using classes for this, as IDs are supposed to be unique. You could achieve that with the following:
$(event.currentTarget).on('select', function() {
$('.yourClassName').click()
};
This will click on every element with the given class.
I've got a table with different columns identified with different classes.
I've also a checkbox binded to every column.
I created a function which is called on the click of any checkbox. In this function I hide/show the column which is linked to this.
It doesn't have any javascript error, and the code is the following:
$(document).ready(function(){
$('ul input').click(function(){
//alert('yooo');
if ($(this).is(':checked')) {
//alert('checked');
$("td."+replaceAll(" ","_",$(this).val())).show();
$("th."+replaceAll(" ","_",$(this).val())).show();
//alert($("td").length);
}
else{
//alert('unselected');
$("td."+replaceAll(" ","_",$(this).val())).hide();
$("th."+replaceAll(" ","_",$(this).val())).hide();
}
});
});
However, after every click, the action has a lag (after many clicks it becomes tooooooo slow, many seconds).
I tried also with .css instead of hide-show, but it doesn't make any change.
I understood that the problem was linked only to checkbox, not on callback or on jquery function. I solved the problem simply by working with radio input, adding a "true" and a "false" radio input for every checkbox that was in the page.
Instead of running the jQuery selector on every click like below:
$("td."+replaceAll(" ","_",$(this).val()))
You could set up some sort of caching like:
var cache = {} //<-- declare this outside your click handler
//add the code below inside your click handler
className = replaceAll(" ","_",$(this).val())
if(!cache[className])
cache[className ] = $("td."+className + ", th."+className); //select all the elements once and store in the cache object
$el = cache[className];
if ($(this).is(':checked'))
$el.show();
else
$el.hide();
i am in touch with jquery for the first time and ran into this: I am trying to create a dynamic input-form. A click function creates a new list-item with another click function nested into it (to provide a remove function for the clicked item).
When i execute the nested click function it appears to be called the number of instances that have been created of it.
Here is the code (i tried to remove as much as possible, but i am not quite sure where the error is - so i guess i left to much stuff in - sorry).
$("#addIngredient").click(function(e){
e.preventDefault();
var prefix = "form-"
var last = $("#IngredientForm ul li").last().html();
$("#IngredientForm ul").append("<li>"+last+"</li>");
var name = $("#IngredientForm ul li:last input").attr("name");
name = name.replace(prefix,'');
var count = parseInt(name[0]);
count += 1;
$("#IngredientForm ul li:last input").attr("name",prefix+count+"-weight")
$("#IngredientForm ul li:last select").attr("name",prefix+count+"-ingredient")
$("#IngredientForm ul li:last input").attr("id","id_"+prefix+count+"-weight")
$("#IngredientForm ul li:last select").attr("id","id_"+prefix+count+"-ingredient")
$("#id_form-TOTAL_FORMS").val(count+1);
$(".deleteIngredient").click(function(e){
e.preventDefault();
var aktuell = $(this).closest('li');
var formCount;
name = aktuell.children('input').attr("name");
name = name.replace(prefix,'');
counter = name.replace("-weight",'');
formCount = parseInt($("#id_form-TOTAL_FORMS").val());
aktuell.remove();
--formCount;
$("#id_form-TOTAL_FORMS").val(formCount);
for (var i = parseInt(counter); i<formCount; i++){
var newName = "form-"+(i);
$("#id_form-"+(i+1)+"-weight").attr("name",newName+"-weight");
$("#id_form-"+(i+1)+"-ingredient").attr("name",newName+"-ingredient");
}
});
});
This block
$(".deleteIngredient").click(function(e){...
attaches a clickevent to all .deleteIngredient elements, also those created before.
You have to put this block outsite the click event of #addIngredient. You can make the delete event to be attached also to every element added in the future.
$("#addIngredient").click(function(e){
// ...
});
$(document).on("click", ".deleteIngredient", function(e){
// ...
});
As the other answers have noted, the click handler is adding a click handler to every .deleteIngredient element every time you run it, which adds multiple handlers to all the previous elements.
When you add a new item to the list, you don't have to add a click handler to it. You can use delegation to create a handler one time that will apply to dynamically-added elements:
$("#IngredientForm").on("click", ".deleteIngredient", function(e) {
...
});
See Event binding on dynamically created elements? for more information.
Every time that outer "click" event happens, you're adding another "click" handler for the ".deleteIngredient" element(s). The .click function does not remove previously-assigned event handlers.
You can get rid of old handlers with .unbind or, preferably with new versions of jQuery, .off:
$('.deleteIngredient').unbind('click').click(function(event) {
// ...
});
No, the thing is, here I think you probably want to bind to the .deleteIngredient button that you're adding for the new ingredient. The code you've got — based on the reference to $('.deleteIngredient') — will affect all of the elements on the page with that class. My guess here is that you're adding a button or something for each <li>. Thus, what you should probably be doing is finding the button inside the newly-added structure:
$('#IngredientForm ul li:last .deleteIngredient').click(function(event) {
// ...
});
Use this format instead
$("#addIngredient").on('click', function() {
$(this).off();
});
With jQuery (or javascript), how can I have one button reveal different hidden (display: none) divs with each click? For example, on the first click of the button, div1 should appear. On the second click of the same button, div2 will appear also (so both div1 and div2 are visible). Same for div3, etc.
With the code I have now, the first button click reveals all the hidden divs at once. Here's an example:
$(document).ready(function () {
$('button').click(function () {
$('.div1').show('slow');
});
$('button').click(function () {
$('.div2').show('slow');
});
$('button').click(function () {
$('.div3').show('slow');
});
});
The reason they are all appearing at once is because what you have done now is appended three separate click handlers to the same object that each show in a separate div. Now every time you click on "button", all three of those functions are going to run.
What you could do is collect all the divs you want to show in one object, and keep a count of the amount of divs you have already shown in.
var count = 0,
$allDivs = $('.div1, .div2, .div3');
$('.button').click( function() {
if( count < $allDivs.length - 1 ) {
$allDivs.eq( count ).show( 'slow' );
count++;
}
});
If you select all the divs at once, then you can use jQuery's eq() method to pick them out one at a time.
Here is a working example on JS fiddle: http://jsfiddle.net/grammar/76arV/
Hope this helps!
var blocks = $('.div1, .div2, .div3');
$('button').click(function () {
if (block = blocks.next())
block.show('slow');
});
What about this?
var iShow = 0;
$('button').click(function () {
$('.show:eq(' + iShow + ')').show('slow');
iShow = iShow + 1;
});
So in this example i gave every element that you want to interact with the button the class .show. This way you can just select any of these element by the index value, you do this with .eq().
First .show element has the index value of 0, so that is where we start(our default value).
Each time we click we increasing the variable by one so next there is clicked, the next element will be showed.
Based on what you want to do next, you can do the same with hiding all the elements again one by one.
Hope this helped you.
jsFiddle
I am new to jQuery, i want to get the list of last div ID's minimum last three iD's.
my need is when user clicks on cancel button then i want to move user to last 2nd clicked div.
Try this:
var clicks = [];
$("div[id^=test]").on('click',function() {
clicks.push(this.id);
});
$("button").on('click',function() {
console.log(clicks.pop())
});
This uses a array to store all the clicks and the show & removes the last one on button click.
To read about .push() and .pop().
Demo here
Make an "history" array that push the id everytime the div is clicked :
var history = [];
$('div').click(function(){
history.unshift(this.id);
})
And on cancel click:
$('button.cancel').click(function(){
history.shift();
})
To save previous clicks you'll want to store clicks in an array as follows:
clicks = [];
$(function () {
$("div").on("click", function (e) {
// The following is what you wanted, but the uncommented code is better (as it saves future DOM lookups)
// clicks.shift($(this).attr("id"));
clicks.shift(this);
// If you want to use jQuery on the objects, you'll need to call jQuery on them ex: $(this)
// If you do want to remove previous elements, uncomment the following code
// if(clicks.length > 3){
// clicks.pop();
// }
});
});
Each time a click occurs, the object that was clicked on will be stored in the array (clicks.push(this)). Later you can reference the array. clicks[0] will have the most recent click, clicks[1] the next most recent, and so on.
So, to do what you described, you would make a function along the lines of:
$(function () {
$("#cancel").on("click", function (e) {
$(clicks[1]).yourMethods();
});
});