I want a to have an animation only when seven elements have been click. Here is the code but it doesn't work:
var animp5 = function () {
var i = 0;
$("#ans1_p5").on('click', function () {
i = i + 1;
$("#ans1_p5").fadeOut(800);
$("#correct1_p5").fadeIn(1000);
});
$("#ans2_p5").on('click', function () {
i = i + 1;
$("#ans2_p5").fadeOut(800);
$("#correct2_p5").fadeIn(1000);
});
$("#ans3_p5").on('click', function () {
i = i + 1;
$("#ans3_p5").fadeOut(800);
$("#correct3_p5").fadeIn(1000);
});
$("#ans5_p5").on('click', function () {
i = i + 1;
$("#ans5_p5").fadeOut(800);
$("#correct4_p5").fadeIn(1000);
});
$("#ans7_p5").on('click', function () {
i = i + 1;
$("#ans7_p5").fadeOut(800);
$("#correct5_p5").fadeIn(1000);
});
$("#ans9_p5").on('click', function () {
i = i + 1;
$("#ans9_p5").fadeOut(800);
$("#correct6_p5").fadeIn(1000);
});
$("#ans10_p5").on('click', function () {
i = i + 1;
$("#ans10_p5").fadeOut(800);
$("#correct7_p5").fadeIn(1000);
});
if (i === 7) {
$("#ans4").fadeOut(800);
$("#ans6").fadeOut(800);
$("#ans8").fadeOut(800);
$("#wrong1_p5").fadeIn(1000);
$("#wrong2_p5").fadeIn(1000);
$("#wrong3_p5").fadeIn(1000);
$("#cor_p5").fadeIn(1000);
}
};
I have tried other solutions (like .data('clicked') or .attr('clicked') but they didn't work either.
You can use observer design pattern in javascript to achieve this the right way.
First create handlers, subscribe and execute functions and then you can subscribe waht ever you like in your case its comparison i===7. execute fade.execute after every click to validate.
Also it's advisable to use class selectors than id selectors in your case. As id selectors will be unmanageable and you will end up with a lot of duplicate code.
But for the sake of your question observer is your way to go.
jsFiddle
function Fade() { // Create Fade handlers
this.handlers = []; // observers
}
Fade.prototype = { // define subscribe and execute
subscribe: function(fn) {
this.handlers.push(fn);
},
execute: function(o, thisObj) {
var scope = thisObj || window;
this.handlers.forEach(function(item) {
item.call(scope, o);
});
}
};
var fade = new Fade();
fade.subscribe(function(){ // pass function you want to subscribe
console.log(i);
if(i===7){
$("#ans4").fadeOut(800);
$("#ans6").fadeOut(800);
$("#ans8").fadeOut(800);
$("#wrong1_p5").fadeIn(1000);
$("#wrong2_p5").fadeIn(1000);
$("#wrong3_p5").fadeIn(1000);
$("#cor_p5").fadeIn(1000);
}
});
var animp5 = (function(){
var i = 0;
$("#ans1_p5").on('click',function(){
i=i+1;
$("#ans1_p5").fadeOut(800);
$("#correct1_p5").fadeIn(1000);
fade.execute(); // execute to check if condition met
});
$("#ans2_p5").on('click',function(){
i=i+1;
$("#ans2_p5").fadeOut(800);
$("#correct2_p5").fadeIn(1000);
fade.execute();
});
$("#ans3_p5").on('click', function(){
i=i+1;
$("#ans3_p5").fadeOut(800);
$("#correct3_p5").fadeIn(1000);
fade.execute();
});
$("#ans5_p5").on('click', function(){
i=i+1;
$("#ans5_p5").fadeOut(800);
$("#correct4_p5").fadeIn(1000);
fade.execute();
});
$("#ans7_p5").on('click', function(){
i=i+1;
$("#ans7_p5").fadeOut(800);
$("#correct5_p5").fadeIn(1000);
fade.execute();
});
$("#ans9_p5").on('click', function(){
i=i+1;
$("#ans9_p5").fadeOut(800);
$("#correct6_p5").fadeIn(1000);
fade.execute();
});
$("#ans10_p5").on('click', function(){
i=i+1;
$("#ans10_p5").fadeOut(800);
$("#correct7_p5").fadeIn(1000);
fade.execute();
});
})();
Thanks for your answers.
As I have not much experience working with jquery I was unable to code your solution but I found a new one that works perfect. I put the "if" inside every click function so each time I click, code checks if the condition has been fulfilled and once this happens run the appropriate code.
Thanks again
Related
var start = $('#start_img');
start.on('click', function(){
var piano = $('.piano');
piano.each(function(index){
$(this).hide().delay(700 * index).fadeIn(700*index);
start.off('click');
})
});
You can see that I have used the start.off('click') method, to stop the Event Listener from running again once it has been called. But the thing is, I only want the Event listener to be off during the time that the event is running. So that it cannot be called again while the event is still running. But once the event has finished, I want it to be 'callable' again. Does anyone know how t do this?
other way of doing this (doesn't work neither). Can anyone help me here. The other one is now clear.
var start = $('#start_img');
start.on('click', function() {
var q = 0;
var piano = $('.piano');
if (q === 1) {
return; // don't do animations
}
else{
piano.each(function(index) {
q = 1;
$(this).hide()
.delay(700 * index)
.fadeIn(700 * index, function() {
// remove from each instance when animation completes
q = 0
});
});}
});
You could toggle a class on active elements as well and then you can check for that class and not do anything if it exists
start.on('click', function() {
var piano = $('.piano');
if (piano.hasClass('active')) {
return; // don't do animations
}
piano.each(function(index) {
$(this).addClass('active')
.hide()
.delay(700 * index)
.fadeIn(700 * index, function() {
// remove from each instance when animation completes
$(this).removeClass('active')
});
});
});
For only one object, you could use a global variable for this, in my case, I'll be using isRunning:
var start = $('#start_img');
var isRunning = false;
start.on('click', function(){
if (!isRunning){
isRunning = true;
var piano = $('.piano');
piano.each(function(index){
$(this).hide().delay(700 * index).fadeIn(700*index, function(){
isRunning = false;
});
start.off('click');
});
}
});
This way your app shouldn't run the code until isRunning == false, which should happen after fadeIn is completed.
Syntaxes:
.fadeIn([duration] [,complete]);
.fadeIn(options);
.fadeIn([duration] [,easing] [,complete]);
For two or more objects, Charlietfl's answer should work perfectly.
I am currently setting up two buttons, start and stop for a jquery loop on html5. The start button works perfectly but whatever I try the 'stop' button remains inactive. I have seen many examples about stopping the loop but none seems to resolve the issue in the button being unresponsive. Sorry if this is such a simple question, but as a student I am quite frustrated and thus asking. cheers
"use strict";
var current_banner_num = 1;
$(document).ready(function(){
$("#banner-base").css("visibility","hidden");
$("#banner-"+current_banner_num).show();
var next_button = $("#start").button();
var stop_button = $("#stop").button();
next_button.click(function(){
var timer = setInterval(myCode, 2000);
function myCode() {
//$("#banner-"+current_banner_num).hide();
$("#banner-"+current_banner_num).fadeTo(800, 0);
if (current_banner_num == 4) {
current_banner_num = 1;
}
else {
current_banner_num++;
}
$("#banner-"+current_banner_num).fadeTo(800, 1);
}
});
stop_button.click(function(){
function abortTimer(){
clearInterval(timer);
}
});
});
You are just defining a function again and again here. Just get rid of the function in the event handler:
stop_button.click(function(){
clearInterval(timer);
});
This would execute the clearInterval(), while the code in your original question just defines a function, but doesn't call or do anything as you said. Hope it gets solved.
I think you have 2 problems in your code. timer variable is not visible outside of next_button.click(function(){ ... }); because it is local for this function, so you need to make it a little bit global; second problem is that in stop_button.click(function(){ ... }); you just declare function abortTimer but do not call it (in general, it is not necessary to declare that function). I think your code should be like:
"use strict";
var current_banner_num = 1;
$(document).ready(function(){
$("#banner-base").css("visibility","hidden");
$("#banner-"+current_banner_num).show();
var next_button = $("#start").button();
var stop_button = $("#stop").button();
var timer = null;
next_button.click(function(){
timer = setInterval(function(){
//$("#banner-"+current_banner_num).hide();
$("#banner-"+current_banner_num).fadeTo(800, 0);
if (current_banner_num == 4) {
current_banner_num = 1;
}
else {
current_banner_num++;
}
$("#banner-"+current_banner_num).fadeTo(800, 1);
}, 2000);
});
stop_button.click(function(){
clearInterval(timer);
});
});
Also it wasn't necessary to declare function myCode in nextButton function, so i clear it too for you
Use a global variable instead of a local one ,unwrap the clearInterval function
"use strict";
var current_banner_num = 1;
$(document).ready(function(){
$("#banner-base").css("visibility","hidden");
$("#banner-"+current_banner_num).show();
var next_button = $("#start").button();
var stop_button = $("#stop").button();
var timer = null;
next_button.click(function(){
timer = setInterval(myCode, 2000);
function myCode() {
//$("#banner-"+current_banner_num).hide();
$("#banner-"+current_banner_num).fadeTo(800, 0);
if (current_banner_num == 4) {
current_banner_num = 1;
}
else {
current_banner_num++;
}
$("#banner-"+current_banner_num).fadeTo(800, 1);
}
});
stop_button.click(function(){
clearInterval(timer);
});
});
Am getting key Combination from the server. Based on that am assigning key Combination to function dynamically. The below code is working for last iteration in loop. how below code is work for all iterations.
In my page i have two buttons save and cancel the below code is working for last iteration in for loop, It means btnCanel button triggers if i press key for save function.Any suggestions. hope understand my question.
$(document).ready(function fn() {
var keyCombination = new Object();
keyCombination['btnAdd'] = "Alt+S";
keyCombination['btnCancel'] = "Alt+C";
for (var k in keyCombination) {
if (keyCombination.hasOwnProperty(k)) {
shortcut.add(String(keyCombination[k]), function () {
var btnAdd = document.getElementById(String(k));
btnAdd.focus();
btnAdd.click();
});
}
}
});
if i give like this means it is working
shortcut.add("Alt+S", function () {
var btnAdd = document.getElementById('btnAdd ');
btnAdd .focus();
btnAdd .click();
});
shortcut.add("Alt+C", function () {
var btnCancel = document.getElementById('btnCancel');
btnCancel.focus();
btnCancel.click();
});
but if i try to add dynamically its overriding help me this issue.
Thanks in Advance.
I created a separate function outside the document.ready function like this now its working fine.
$(document).ready(function fn() {
var keyCombination = new Object();
keyCombination['btnAdd'] = "Alt+S";
keyCombination['btnCancel'] = "Alt+C";
for (var k in keyCombination) {
if (keyCombination.hasOwnProperty(k)) {
Set_KeyCombinations(k, keyCombination);
}
}
});
function Set_KeyCombinations(k, keyCombination) {
shortcut.add(String(keyCombination[k]), function () {
var eleId = document.getElementById(String(k));
if (eleId) {
if ($('#' + String(k).trim()).css('display') !== 'none' && eleId.getAttribute("disabled") !== "disabled") {
eleId.click();
eleId.focus();
}
}
});
}
Try this:
var keyCombinations = [ "Ctrl+Shift+X" , "Ctrl+Shift+Y" ];
for(var i=0; i<keyCombinations.length; i++){
(function(shorcutCombination){
shortcut.add(shorcutCombination,function() {
alert("i am " + shorcutCombination);
});
})(keyCombinations[i]);
}
The idea is that you need to preserve the value of keyCombinations[i]
as i increases in the loop. Tested this here: Openjs
I'm having trouble getting the element in a jQuery Callback function. I have tried various suggestions of $(this) and $(this.element) with no success.
$.fn.onTypeFinished = function (func) {
$(this).bind("keypress", onKeyPress)
function onKeyPress() {
setTimeout(onTimeOut, 500);
}
function onTimeOut() {
func.apply();
}
return this;
};
$(".user-input").onTypeFinished(function () {
var ntabindex = parseFloat($(this.element).attr('tabindex'));
ntabindex++;
$('input[tabindex=' + ntabindex + ']').focus();
});
I have been thinking I need some way to pass a reference to this to the callback function but no other similar posts seem to suggest that route.
Here is a JSFiddle of what I am trying to do. The gist of the functionality is I'm trying to auto advance to the next input according to tabindex.
http://jsfiddle.net/helfon/fdu8xw0h/2/
Thanks
From your code it looks like you want to pass the element on which the keypress has occurred as this to the callback.
For that to happen you need to pass the correct context to the timeout handler, for which we can use .bind() as shown below.
Also to make the timer work correctly some other corrections are also made.
$.fn.onTypeFinished = function(func) {
$(this).bind("keypress", onKeyPress)
function onKeyPress() {
var onTypeFinished = $(this).data('onTypeFinished');
if (!onTypeFinished) {
onTypeFinished = {};
$(this).data('onTypeFinished', onTypeFinished);
}
clearTimeout(onTypeFinished.keytimer);
onTypeFinished.keytimer = setTimeout(onTimeOut.bind(this), 500);
}
function onTimeOut() {
func.apply(this);
}
return this;
};
$(".user-input").onTypeFinished(function() {
//$('input[tabindex=3]').focus();
var ntabindex = parseFloat(this.getAttribute('tabindex'));
ntabindex++;
$('input[tabindex=' + ntabindex + ']').focus();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="1" tabindex=1 class="user-input">
<input id="2" tabindex=2 class="user-input">
<input id="3" tabindex=3 class="user-input">
<input id="4" tabindex=4 class="user-input">
As per the logs, it seems that your this keyword inside the jQuery fn is pointing to the window object instead, I've bound the functions as follows and passed this in your apply, and got it working so that this points to the input elements instead:
$.fn.onTypeFinished = function (func) {
var time;
$(this).each(function () {
$(this).on('keypress', onKeyPress);
});
function onKeyPress() {
clearTimeout(time);
time = setTimeout(onTimeOut.bind(this), 500);
}
function onTimeOut() {
func.apply(this);
}
return this;
};
$(".user-input").onTypeFinished(function () {
//$('input[tabindex=3]').focus();
var ntabindex = parseFloat($(this).attr('tabindex'));
++ntabindex;
$('input[tabindex=' + ntabindex + ']').focus();
});
http://jsfiddle.net/fdu8xw0h/9/
You have to also iterate over the array of elements as your selector is returning an array of inputs, so you have to handle them separately, otherwise your event will occur only once, i've tested it and it goes from the first input to the second and then it stops working. With the approach i've pasted here it will go from input to input.
You should understand that this changes whenever you change scope. Always var $this = $(this) to lock it down.
$.fn.onTypeFinished = function (func) {
var $this = $(this);
$this.bind("keypress", onKeyPress);
function onKeyPress() {
setTimeout(onTimeOut, 500);
}
function onTimeOut() {
func($this); //I would personally send this, like how you do $.each(function(count, element){})
}
return this;
};
$(".user-input").onTypeFinished(function (t) {
var ntabindex = parseInt($(t).attr('tabindex')) + 1; //You should parse int here
$('input[tabindex=' + ntabindex + ']').focus();
});
Of course, you can simplify the above more into:
$.fn.onTypeFinished = function (func) {
var $this = $(this);
$this.bind("keypress", onKeyPress);
function onKeyPress() {
setTimeout(function(){
func($this);
}, 500);
}
return this;
};
$(".user-input").onTypeFinished(function (t) {
$('input[tabindex=' + String(parseInt($(t).attr('tabindex')) + 1) + ']').focus();
});
The jsfiddle: http://jsfiddle.net/vimxts/fdu8xw0h/6/
I am trying to write a javascript function that when called performs function DoSomething() once,
but can be triggered to perform the function repeatedly until triggered to stop.
I am using setTimeout() function. I am not sure if this is best method from performance and memory point of view.
Also I would like to avoid global variable if possible
<!DOCTYPE html>
<html>
<script src="jquery.js"></script>
<script>
var globalCheckInventory = false;
$(document).ready(function(){
// start checking inventory
globalCheckInventory = true;
myTimerFunction();
});
// check inventory at regular intervals, until condition is met in DoSomething
function myTimerFunction(){
DoSomething();
if (globalCheckInventory == true)
{
setTimeout(myTimerFunction, 5000);
}
}
// when condition is met stop checking inventory
function DoSomething() {
alert("got here 1 ");
var condition = 1;
var state = 2 ;
if (condition == state)
{
globalCheckInventory = false;
}
}
</script>
This is probably the easier way to do what you're describing:
$(function () {
var myChecker = setInterval(function () {
if (breakCondition) {
clearInterval(myChecker);
} else {
doSomething();
}
}, 500);
});
Another way to do it would be the store the timer ID and use setInterval and clearInterval
var timer = setInterval(DoSomething);
function DoSomething() {
if (condition)
clearInterval(timer);
}
I see nothing wrong with your implementation other than the pollution of the global namespace. You can use a closure (self-executing function) to limit the scope of your variables like this:
(function(){
var checkInventory = false, inventoryTimer;
function myTimerFunction() { /* ... */ }
function doSomething() { /* ... */ }
$(document).ready(function(){
checkInventory = true;
/* save handle to timer so you can cancel or reset the timer if necessary */
inventoryTimer = setTimeout(myTimerFunction, 5000);
});
})();
Encapsulate it:
function caller(delegate, persist){
delegate();
if(persist){
var timer = setInterval(delegate, 300);
return {
kill: function(){
clearInterval(timer);
}
}
}
}
var foo = function(){
console.log('foo');
}
var _caller = caller(foo, true);
//to stop: _caller.kill()