disable and enable click events with a counter and transition effects - javascript

I have the following lines of code in my web page - demo/example.
HTML:
<button class="wrong-answer" onclick="showResult(this)">42</button>
<button class="right-answer" onclick="showResult(this)">43</button>
<p id="answer" class="answer-display-hidden">answer</p>
<div class="incorrect">
<span>Incorrect:</span>
<p>0</p>
</div>
<div class="correct">
<span>Correct:</span>
<p>0</p>
</div>
CSS:
.answer-display-visible {
visibility: visible;
opacity: 1;
transition: opacity 1s linear;
}
.answer-display-hidden {
visibility: hidden;
opacity: 0;
transition: visibility 0s 1s, opacity 1s linear;
}
.incorrect, .correct {float: left; padding-right: 20px}
JS:
var incorrectCalls = 0;
var correctCalls = 0;
function showResult(b) {
var res = document.getElementById('answer');
if (b.classList.contains('right-answer')) {
res.innerHTML = '<span class="right">right</span>';
correctCalls++;
var cor = $('.correct > p:first');
cor[0].innerHTML = correctCalls;
}
else {
res.innerHTML = '<span class="wrong">wrong</span>';
incorrectCalls++;
var incor = $('.incorrect > p:first');
incor[0].innerHTML = incorrectCalls;
}
res.classList.remove("answer-display-hidden");
res.classList.add("answer-display-visible");
setTimeout(function() {
res.classList.add("answer-display-hidden");
}, 2000);
}
How can I de-activate the right-answer counter during the fade-in and wait effect on the text, and then re-activate afterwards? This is so that the user can't manipulate the counter (click on the button quickly before the text is displayed).

You can use setTimeout function when button clicked.
Live Demo
Code Block:
function showResult(b) {
.
.
.
$(".right-answer").prop("disabled", true);
$(".wrong-answer").prop("disabled", true);
setTimeout(function() {
$(".right-answer").prop("disabled", false);
$(".wrong-answer").prop("disabled", false);
}, 2600);
}

This is my solution
WORKING DEMO
Removed CSS code and following is the jQuery code.
$(document).ready(function(){
$(".wrong-answer").click(function(){
$(".right-answer").attr("disabled","disabled");
$("#answer").text("WRONG").fadeIn(5000,function(){
$(this).fadeOut(5000,function(){
$(".right-answer").removeAttr("disabled");
});
})
});
});

Related

keep moving an element up and down while mouse button is pressed

Everything works here but I need to keep moving act up and down while mouse button is pressed, without repeated clicks.
Any help?
$('button').on('click', function(){
let a = $('.act');
a.insertBefore(a.prev());
});
$('button').on('contextmenu', function(e){
e.preventDefault();
let a = $('.act');
a.insertAfter(a.next());
});
.act{background:gold;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class='title act'>LOREM</div>
<div class='title'>IPSUM</div>
<div class='title'>DOLOR</div>
<div class='title'>SIT</div>
<div class='title'>AMET</div>
</div>
<br>
<button>CLICK</button>
Instead of the click and contextmenu events you'll have to use mouse events, here is an example:
let intervalId;
const a = $('.act');
$('button').on('mousedown', function(event) {
function fn () {
if (event.button == 0) {
a.insertBefore(a.prev());
} else if (event.button == 2) {
a.insertAfter(a.next());
}
return fn;
};
intervalId = setInterval(fn(), 500);
});
$(document).on('mouseup', function(event) {
clearInterval(intervalId);
});
$('button').on('contextmenu', function(event) {
event.preventDefault();
});
.act {
background: gold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class='title act'>LOREM</div>
<div class='title'>IPSUM</div>
<div class='title'>DOLOR</div>
<div class='title'>SIT</div>
<div class='title'>AMET</div>
</div>
<br>
<button>CLICK</button>
In this example, I'm using an interval to move the element every 500 milliseconds while the mouse pointer is down, I'm also preventing the contextmenu event so that the context menu will not consume the mouseup event itself.
I've made a fiddle to illustrate:
https://jsfiddle.net/10cgxohk/
html:
<p class="">x</p>
css:
.move {
animation: MoveUpDown 1s linear infinite;
position: relative;
left: 0;
bottom: 0;
}
#keyframes MoveUpDown {
0%, 100% {
bottom: 0;
}
50% {
bottom: 15px;
}
}
javascript:
$('body').on('mousedown', function() {
$('p').addClass('move');
$('body').on('mouseup', function() {
$('p').removeClass('move');
$('body').off('mouseup');
console.log('here');
})
});
This is really rough and creates an issue if you have other 'mouseup' callbacks on the body, but if that's not a worry for you then it should work. The javascript is adding a class to the element, and the class is animated in css

Show and hide based on time interval

I want to show and hide a series of divs based on time interval.
Show div 1 after 4 seconds, show div 2 after a further 4 seconds and so on.
The previous div being hidden, so it appears as if new information is replacing the previous and at time intervals.
I have it working to a point, it's just when I add more divs.
setInterval(function() {
$("#a").hide();
setTimeout(function() {
$("#b").fadeIn('normal');
});
}, 4000);
#b, #c {
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a">1</div>
<div id="b">2</div>
<div id="c">3</div>
https://jsfiddle.net/Layt8cuy/1/
The first div needs to be there by default, and they stop with the last div with no loop back to the beginning.
Here is basic function Jsfiddle
var currentDiv = $("#a");
var nextDiv, count = 1;
var myInterval = setInterval(function() {
if (count == 5) {
clearInterval(myInterval);
} else {
count++;
currentDiv.hide();
currentDiv = currentDiv.next();
currentDiv.show();
}
}, 2000);
#b,
#c,
#d,
#e {
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a">1</div>
<div id="b">2</div>
<div id="c">3</div>
<div id="d">4</div>
<div id="e">5</div>
You need a variable to track the current visible div. Also it's recommended to use a class to select all divs, otherwise you'll have to select them by tag name, which is an issue if you have other divs that shouldn't be included.
You only need setInterval() and inside it first hide all divs, then show the div with the current index, and finally increment the current index variable if it is still less that the number of divs, otherwise reset it to 0.
var current = 0;
setInterval(function() {
var divs = $(".roll").hide();
divs.eq(current).fadeIn("normal");
if (current < divs.length - 1)
current++;
else
current = 0;
}, 1000);
.roll {
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a" class="roll">1</div>
<div id="b" class="roll">2</div>
<div id="c" class="roll">3</div>
To do only one loop, you need to store the ID of the setInterval() and use it in clearInterval() to stop. Here is a solution for the points in your comments:
var current = 0;
var divs = $(".roll");
var timer = setInterval(function() {
if (current < divs.length - 1) {
divs.eq(current).hide();
current++;
divs.eq(current).fadeIn("normal");
} else
clearInterval(timer);
}, 1000);
.roll {
display: none
}
#a {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a" class="roll">1</div>
<div id="b" class="roll">2</div>
<div id="c" class="roll">3</div>
a working example, with returning to first div after finish
recursive + timeout
you can use the same method for your situation:
let duration = 1000, // these are miliseconds
activeIndex = 0; // first item to activate
function activateNext() {
let boxes = $('.boxes > div');
// activate current item
boxes.addClass('hide').eq(activeIndex).removeClass('hide');
// increase activeIndex and make reset at end of collection
if (++activeIndex >= boxes.length) activeIndex = 0;
// run the function again after duration
setTimeout(function() {
activateNext(activeIndex);
}, duration)
}
// start the loop
$(window).on('load', activateNext);
.hide {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="boxes">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
Without looping back to first:
let duration = 1000, // these are miliseconds
activeIndex = 0; // first item to activate
function activateNext() {
let boxes = $('.boxes > div');
// activate current item
boxes.addClass('hide').eq(activeIndex).removeClass('hide');
// increase activeIndex and make reset at end of collection
if (++activeIndex < boxes.length) {
// run the function again after duration
setTimeout(function() {
activateNext(activeIndex);
}, duration)
}
}
// start the loop
$(window).on('load', activateNext);
.hide {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="boxes">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
You might also consider pure CSS solution:
#a, #b, #c {
position: absolute;
animation: hide 4s linear forwards;
}
#b, #c {opacity: 0}
#b {
animation-delay: 4s;
}
#c {
animation-name: last;
animation-delay: 8s;
}
#keyframes hide {
0%, 99.99% {opacity: 1}
100% {opacity: 0}
}
#keyframes last {
0%, 100% {opacity: 1}
}
<div id="a">1</div>
<div id="b">2</div>
<div id="c">3</div>

CSS - Transition does not work properly in JavaScript for loop

I have used a JavaScript for loop to change the className property of a group of DIV's that have same class.
I'm trying to change of appearance of each div by the changing the className property so that the CSS transition activates and effects the each DIV.
The problem is that the transition ONLY affects the first DIV.
Here is my HTML code:
<body onload="init()">
<div id="menu">
<div class="accor hide" id="chosen">
od
</div>
<ul>
<li>To</li>
<li>Pr</li>
<li>La</li>
</ul>
<div class="accor hide">
En
</div>
<ul>
<li>fa</li>
<li>Co</li>
<li>Co</li>
</ul>
<div class="accor hide">
Sp
</div>
</div>
</body>
Here is my CSS:
.accor + ul {
max-height: 500px;
overflow: hidden;
transition: max-height 0.5s ease
}
.hide + ul {
max-height: 0px;
overflow: hidden;
transition: max-height 0.5s ease
}
Here is my JavaScript:
function init() {
var chosen = document.getElementById("chosen");
chosen.onclick = toggleDivs;
}
function toggleDivs() {
hideDivs = document.getElementsByClassName("accor hide");
for(var i = 0; i <= hideDivs.length; i++) {
hideDivs[i].className = 'accor';
}
}
When I click the DIV with the id of "chosen" I want to make all the DIV's with the class "accor" slide down like like jQuery's $.fn.slideDown(...);.
If I change the JavaScript a little bit the transition will effect the first two DIV's.
Here is my changed JavaScript:
hideDivs = document.getElementsByClassName('accor hide');
hideDivs[0].className = 'accor';
hideDivs = document.getElementsByClassName('accor hide');
hideDivs[0].className = 'accor';
I think this is because when I used the for loop (above) i was initially set to 0 and i did not increment so the transition only effected the first DIV.
pugazh have other fix so i want to post hear for diversity.
function toggleDivs() {
var menu = document.getElementsByClassName('accor')
for (var i = 0; i <= menu.length; i++)
menu[i].classList.toggle('hide');
};
I replaced hideDivs[i].className = 'accor'; with hideDivs[0].className = 'accor';
I did this because each time you execute toggleDivs(); the class hide is removed from the element, you want to toggle the DIV's not always hide them.
window.addEventListener("load", init, false);
function init() {
var chosen = document.getElementById("chosen");
chosen.onclick = toggleDivs;
}
function toggleDivs() {
hideDivs = document.getElementsByClassName("accor hide");
for(var i = 0; i <= hideDivs.length; i++) {
hideDivs[0].className = 'accor';
}
}
.accor + ul {
max-height: 500px;
overflow: hidden;
transition: max-height 0.5s ease
}
.hide + ul {
max-height: 0px;
overflow: hidden;
transition: max-height 0.5s ease
}
<body onload="init()">
<div id="menu">
<div class="accor hide" id="chosen">
od
</div>
<ul>
<li>To</li>
<li>Pr</li>
<li>La</li>
</ul>
<div class="accor hide">
En
</div>
<ul>
<li>fa</li>
<li>Co</li>
<li>Co</li>
</ul>
<div class="accor hide">
Sp
</div>
</div>
</body>

Slide show css transition in Angular

I've been playing around with the animation aspect in AngularJS, and I just can't seem to get the kind of functionality I need:
.box.ng-hide-add {-webkit-animation: fadeOutLeftBig 0.4s;}
.box.ng-hide-remove {-webkit-animation: fadeInRightBig 0.4s;}
.box.ng-show-add{-webkit-animation: fadeInRightBig 0.4s;}
Ideally, when the user hits the 'Next' button, the current box should exit to the left, while the box next in line eases in from the right, creating that slideshow/carousel effect.
But right now it's all from the same side.
Is this even possible? I feel like I'm getting close, but I could just be thinking about it the wrong way. What am I overlooking or forgetting?
Code snippet:
(function(){
var app = angular.module("theapp", ['ngAnimate']);
var controller = function($scope){
$scope.currentPage = 1;
};
app.controller("controller", controller);
}());
.box.ng-hide-add {
-webkit-animation: fadeOutLeftBig 0.4s;
}
.box.ng-hide-remove {
-webkit-animation: fadeInRightBig 0.4s;
}
.box.ng-show-add {
-webkit-animation: fadeInRightBig 0.4s;
}
.box {
height:100px;
width:100px;
}
.red {background-color:red;}
.blue {background-color:blue;}
.purple {background-color:purple;}
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.0/animate.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular-animate.min.js"></script>
<body ng-app="theapp">
<div ng-controller="controller">
<div style="height:100px; margin-left:300px;">
<div ng-show="currentPage==1" class="box red">
content
</div>
<div ng-show="currentPage==2" class="box blue">
content
</div>
<div ng-show="currentPage==3" class="box purple">
content
</div>
</div>
<button ng-click="currentPage=currentPage-1">Previous</button>
<button ng-click="currentPage=currentPage+1">Next</button>
</div>
</body>
(fiddle: http://jsfiddle.net/poppypoop/Ldyvy062/3/)
Any help is appreciated!
The code below does what you want, see comments in code for explanation, hope this is helpful.
I changed to ng-if, instead of ng-show, to be able to use ng-enter, ng-leave in CSS
(function () {
var app = angular.module("theapp", ['ngAnimate']);
var controller = function ($scope, $timeout) {
$scope.currentPage = 1;
$scope.numberOfPages = 3;
$scope.changePage = function (action) {
if (action === '+') {
$scope.direction = 'toRight';
$timeout(function () { // timeout to allow direction class to update before changing currentPage
$scope.currentPage = $scope.currentPage < $scope.numberOfPages ? $scope.currentPage + 1 : 1;
}, 0)
} else if (action === '-') {
$scope.direction = 'toLeft';
$timeout(function () { // timeout to allow direction class to update before changing currentPage
$scope.currentPage = $scope.currentPage > 1 ? $scope.currentPage - 1 : $scope.numberOfPages;
}, 0)
}
}
};
app.controller("controller", controller);
}());
.toRight .box.ng-enter {
-webkit-animation: fadeInRightBig 0.7s;
}
.toLeft .box.ng-enter {
-webkit-animation: fadeInLeftBig 0.7s;
}
.toRight .box.ng-leave {
-webkit-animation: fadeOutLeftBig 0.7s;
}
.toLeft .box.ng-leave {
-webkit-animation: fadeOutRightBig 0.7s;
}
.box {
height: 100px;
width: 100px;
position:absolute; /*This is to avoid animations to overlap, causing a weird behavior*/
}
.red {background-color:red;}
.blue {background-color:blue;}
.purple {background-color:purple;}
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.0/animate.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular-animate.min.js"></script>
<body ng-app="theapp">
<div ng-controller="controller">
<div style="height:100px; margin-left:300px;" class="{{direction}}"><!--Added angular variable in class to determite direction-->
<div ng-if="currentPage==1" class="box red">
content
</div>
<div ng-if="currentPage==2" class="box blue">
content
</div>
<div ng-if="currentPage==3" class="box purple">
content
</div>
</div>
<button ng-click="changePage('-')">Previous</button>
<button ng-click="changePage('+')">Next</button>
</div>
</body>

I need to change the opacity value of an image using JavaScript when i mouse over it but my code isn't working

I need the images opacity to increase when I mouse over and decrease when I mouse out and I need
this to be gradual and not instant as it would be with CSS.
<html>
<head>
</head>
<body>
<img id="test" src="space1.png" onmouseover="updateOpacity()"/>
<script type="text/javascript">
var element = document.getElementById('test');
var opacity = element.style.opacity;
function updateOpacity()
{
opacity = opacity += 0.2;
if(opacity >= 1)
{
// done
opacity = 1;
}
else
{
element.style.opacity = opacity; // this updates the opacity
setTimeout(function(){updateOpacity();}, 50); // 50 is the delay, 50milliseconds
}
}
</stript>
</body>
</html>
Is jQuery an option?
<img id="test" src="space1.png" style="opacity: 0.1;">
<script>
var delay = 500; //500ms
$("#test").mouseover(function(){
$(this).stop().animate({
opacity: 1.0
}, delay);
}).mouseout(function(){
$(this).stop().animate({
opacity: 0.1
}, delay);
});
</script>
EDIT: http://jsfiddle.net/m3PAy/
If you don't need to support current IE, you can do this cleanly using CSS transitions:
HTML
<img id="test" src="space1.png"/>
CSS
#test {
transition: opacity 600ms;
opacity: 0.35;
}
#test:hover {
opacity: 1.0;
}
Obligatory jsFiddle: http://jsfiddle.net/millimoose/uNeMg/
(For the sake of clarity and sanity I'm omitting the vendor prefixes and using -prefix-free.)

Categories

Resources