Create repeated fade-out effect by using className Method and setInterval - javascript

Dears,
I have an assignment that is to create a repeated fade-out effect by using setInterval and using the DOM className method, below is my code:
<!DOCTYPE html>
<html>
<style>
.mystyle {
background-color: coral;
padding: 16px;
opacity: 0;
transition: opacity 1s linear;
}
</style>
<body>
<div id="myDIV"></div>
<p>Click the button to set a class for myDIV:</p>
<button onclick="setInterval()">Try it</button>
<script>
setInterval(change, 2000)
function change() {
function subchange1(){
document.getElementById("myDIV").className = "mystyle";
};
function subchange2(){
document.getElementById("myDIV").className = "";
};
}
</script>
</body>
</html>
However, it shows no change at all, could you tell me where i get wrong and how to correct it? Thanks very much!

You've used setInterval() as a user defined function. It needs two arguments one is callback function and other is time interval. You should've used and remove the setInterval in JS.
<button onclick="setInterval(change, 2000)">Try it</button>
In change() function you just declared the functions. You didn't call them back. It will not give you expected output even if you call them.
For your code to work you need to check if myDiv has class .mystyle. For that you'll need to use if-else statements.
Here's a Working code :-
let myDiv = document.getElementById("myDIV");
function change() {
if (myDiv.className === "mystyle") {
myDiv.className = "";
} else {
myDiv.className = "mystyle";
}
}
function startAnimation() {
setInterval(change, 2000);
};
#myDIV {
background-color: #1a8cff;
padding: 16px;
transition: opacity 1s linear;
}
.mystyle {
background-color: coral;
opacity: 0;
}
<div id="myDIV"></div>
<p>Click the button to set a class for myDIV:</p>
<button onclick="startAnimation()">Try it</button>

Since this is an assignment that you have to complete, I will only list the issue I notice and let you fix them as an exercise.
You have a <style> tag directly inside the <html>. You should have that style inside of a <head> element.
Code functions called inside of the <script> tag are executed directly and immediately. You are calling setInterval(change, 2000) directly so there is no need to to add it to the <button> tag. If you want the repeated action to only start when you press the button, you need to call setInterval, this line setInterval(change, 2000), inside of another function, like start for example. Then you add start to onclick like this: onclick="start()".
The change function has 2 function declarations in it but no function calls. This means that the two functions inside of it, subchange1 and subchange2 are never called. To use a function you need to call it. You should move those two functions outside, after the change function, and then you can call them by using subchange1() and subchange2().
That will fix your code issues but don't have correct logic to implement the function requirements. You can search for class toggle function and find different ways of doing it. I suggest in going with the one that better matches what you have already learned.
This looks like a medium to advanced assignment. The best way to solve these will be to start simple and test your code as you progess. It will be very dificult to write everything and test. I highly suggest you write a simple function call, like alert(7), and then add it to the button, test the button, then add it to a function, test the function with the button, then use it with setInterval. This will make sure you have things working before you add more complexity.
Good luck with you assignment :)

After few research, i found that it is highly the cause of the async nature of the codes of Javascript, i found using setTimeout can overcome this issue and my code is below:
<!DOCTYPE html>
<html>
<head>
<style>
.mystyle {
background-color: coral;
padding: 16px;
opacity: 0;
transition: opacity 1s linear;
}
</style>
</head>
<body>
<div id="myDIV" >
<p>I am myDIV.</p>
</div>
<p>Click the button to set a class for myDIV:</p>
<button onclick="change()">Try it</button>
<script>
function change(){
let abc = document.getElementById("myDIV");
abc.className = "mystyle";
setTimeout(function() {abc.className = "";}, 1000);
setTimeout(change, 2000);
};
</script>
</body>
</html>

Related

on button click, show message for x seconds without alert() function - is it possible?

In my NEXT.JS project, I want a simple <p> element to show below my button for x amount of time, and then I want it to disappear. I don't want to use alert() function. How can I manage that?
You can achieve that with a simple js event trigger. All you need to do is create a click event listener for the button, and then attach your 'p' element to the desired view.
Btw this has nothing to do with next.js this is core js DOM manipulation. You should learn about DOM and how to work with it, and then explore frameworks like next. Only with good knowledge of core js, and DOM manipulation, You will be able to really learn frameworks.
In case anyone needs it, here is the solution using useState and simple handler...
const [myAlert, setMyAlert] = useState(false)
const handleMyAlert = () => {
setMyAlert(true);
setTimeout(() => {
setMyAlert(false)
}, 5000);
}
You can use it like this: <button onClick={handleMyAlert}>Click me</button>
and for <p> set style={myAlert ? {display: "block"} : {display: "none}}
I'm too late but I post it anyway to try the snippet method.
function setMsg(e){
let inter = alertMsg(e);
}
function alertMsg(e){
document.getElementById("alertP").innerHTML="Click-me!";
document.getElementById("alertP").style.display="inline";
inter= setInterval("hideOutput()",3000);
}
function hideOutput(){
document.getElementById("alertP").style.display="none";
clearInterval(inter);
}
html, body{
font-family:"sans-serif";
font-size:1em;
}
button{
font-size:1.2em;
}
#buttonContainer{
width:200px;
margin:auto;
}
#alertP{
display:none;
text-align: center;
border:1px solid #000000;
background-color:red;
color:#FFFFFF;
}
<div id="buttonContainer">
<button id="clickableArea" onMouseOver="setMsg()">Alert Button</button>
<p id="alertP"></p>
</div>

How can i make anchor unclickable after 10 seconds?

<html>
<head>
<style>
.inactiveLink {
pointer-events: none;
cursor: default;
}
</style>
</head>
<body>
<p> You have won a prize. Click here within <div id='clock'></div> seconds ...</p>
<script>
var time = 10;
var f = function counttime(){document.getElementById('clock').innerHTML--;}
function stoptime(){cleatInterval(f);}
if(time){
document.getElementById('clock').innerHTML = time;
var h = setInterval(f,1000);
setTimeout(function(){clearInterval(h);
document.getElementById('clock').innetHTML = "Time's up!";
}, time*1000);
}
</script>
</body>
</html>
I'm trying to create a basic webpage, that says "You have won a prize. Click here within 10 seconds ..." when it opens. You have 10 seconds to click "here" to get your prize. After 10 seconds, "here" should be unclickable. I added a CSS part about being unclickable, which is called "inactiveLink". I don't know how i should implement the change of anchor tag after 10 seconds, to JS. (I'm thinking about after 10 sec, a in HTML should be changed to a with id inactiveLink)
You were almost there :)
I would use a class that uses the CSS-rule pointer-events: none and then use JS to add that class to the link after 10 seconds:
const a = document.getElementById('a');
setTimeout(() => a.className = 'unclickable', 10000);
.unclickable { pointer-events: none; }
<a id="a" href="">Hurry up</a>
Use setAttribute to make it unclickable. Maybe make a class called "unclickable" with all of the CSS you want.
You can see this thread for more information on how to set your link so that it won't fire an event upon click. Check the second answer (not the one that the user marked as correct).
The best way to do it is by removing the attribute href removeAttribute("href");.
Note: that pointer-events:none only prevents mouse clicks but if you used the tab key and pressed ENTER over the link it will still be followed.
function myFunction() {
document.getElementById("anc").removeAttribute("href");
}
<a id="anc" href="google.com">Click Me.</a>
<button onclick="myFunction()">Disabler</button>
anchor tags dont have a disabled attribute, but one approach you can take is to style a button like a link. Something link this for example:
const buttonEl = document.querySelector('#target');
const handler = e => {
console.log('Button is still active!');
};
buttonEl.addEventListener('click', handler);
setTimeout(() => {
buttonEl.disabled = true;
}, 2000);
button {
all: unset;
color: blue;
cursor: pointer;
text-decoration: underline;
}
button:disabled {
color: gray;
cursor: not-allowed;
}
<button id="target" type="button">Click the button</button>

If statement to check css property not working

I have a div that displays a little popup menu when clicked. I want users to be able to click anywhere in the body of the site to close the popup, but when I add code for that, the popup cant be opened at all anymore.
So I tried adding an if-statement so that the closemenu() function will only try close the popup if its already open, but it seems like the statement is evaluating to false even if the popup is open.
Here is the HTML for showing the popup:
<div class="popcolor" onclick="showmenu()"> Click!
<span class="popupcolor" id="myPopup">Pop!</span>
</div>
Here is the css:
.popcolor .show {
visibility: visible;
-webkit-animation: fadeIn 0.5s;
animation: fadeIn 0.5s;
}
Here is the Javascript:
function showmenu() {
var popup = document.getElementById("myPopup");
popup.classList.toggle("show");
}
function closemenu() {
var popup = document.getElementById("myPopup");
if (popup.style.visibility == "visible") {
popup.classList.toggle("close");
};
}
Here is the HTML for closing the popup:
<body onclick="closemenu()">
I've been through every post I can find on this for solutions, and I'm still stuck. Any help is appreciated.
You can use the getComputedStyle() method on the window object, to calculate the style rules that result from the classes applied to your popup element.
This gives you a reliable way of determining the values of different styling rules that result from, say, the 'close' class being applied to popup
Something along the lines of this should work for you:
function closemenu() {
var popup = document.getElementById("myPopup");
// Get the computed style, that is the combination of styles
// resulting from your CSS classlist, etc
var computedStyle = window.getComputedStyle(popup, null);
// Get visibility value from computed styles
var visiblityValue = computedStyle.getPropertyValue("visibility")
if (visiblityValue == "visible") {
popup.classList.toggle("show"); // Correct this from "close" to "show"
};
}
There are also some other functional issues with your implementation which are causing problems. Consider updating your showmenu() method to:
function showmenu(event) {
// Prevent event propagation, which would cause closemenu to call
// after this method is called
event.stopPropagation()
var popup = document.getElementById("myPopup");
popup.classList.toggle("show");
}
For more information on getComputedStyle(), see the MDN documentation
Problem here is that click event triggered from div bubbles up to body which eventually closes the popup.
function showmenu(e) {
e.stopPropagation();
console.log('toggle');
document.getElementById("myPopup").classList.toggle("close");
}
function closemenu(e) {
e.stopPropagation();
console.log('hide');
document.getElementById("myPopup").classList.add("close");
}
#myPopup.close {
visibility: hidden;
}
body {
border: 1px solid #ccc;
padding: 2rem;
}
<body onclick="closemenu(event)">
<div class="popcolor" onclick="showmenu(event)"> Click!
<span class="popupcolor close" id="myPopup">Pop!</span>
</div>
</body>
P.S. Use event.stopPropagation() to cancel/consume event
Because the visibility property is being set at the class level, the style information isn't available in the style property of your element. Maybe instead of checking for a specific style, you can check to see if the 'show' class is currently assigned to your element like so:
function closemenu() {
var popup = document.getElementById("myPopup");
if (popup.classList.contains("show")) {
popup.classList.toggle("close");
};
}
Problem in your code is with the use of JavaScript functions.
Try this simple example I took from W3Schools and enhanced it for your case.
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_add_class
There seems to be some issue with W3CSchool TryIt Editor page. Here is the link to JSBin for the same code: https://jsbin.com/xefolinape/edit?html,output
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.mystyle {
width: 100%;
padding: 25px;
background-color: coral;
color: white;
font-size: 25px;
box-sizing: border-box;
}
</style>
</head>
<body>
<p>Click the "Try it" button to add the "mystyle" class to the DIV element:</p>
<button onclick="myFunction()">Try it</button>
<button onclick="myFunctionClose()">Close it</button>
<script>
function myFunction() {
var element = document.getElementById("myDIV");
element.classList.add("mystyle");
}
function myFunctionClose() {
var element = document.getElementById("myDIV");
element.classList.remove("mystyle");
}
</script>
</body>
</html>
Hope this helps!

Handle nestled ng-click's with "peek through" in Angularjs

I'm having a bit of trouble handling multiple, nestled, angularjs mousebutton directives.
I have a template that looks like this:
<div class="project-wrap">
<div class="workspace-wrap">
<div id="workspace" class="workspace"
oncontextmenu="return false;"
ng-mousedown="project.checkBtnDown($event)"
ng-mouseup="project.checkBtnUp($event)"
ng-mousemove="project.mouseMoved($event)">
</div>
</div>
<button class="logoutBtn" ng-click="project.logout()">
Logout
</button>
</div>
What checkBtnDown() does, is simply check which of the mousebuttons was pressed and then processes it.
The problem I'm having is, when the left mousebutton is pushed down on the "workspace" (within my ProjectCtrl's template), it places a SVG element inside the "workspace" div. This SVG element is bound with an custom angular directive, which has a ng-click on it's template.
So what's happening is, I create the SVG element as planned but, when I click on the portion of the SVG element that I want to call a function on scope. It's still calling checkBtnDown(), because the new SVG element is inside the project template.
How can I get the SVG element ng-click to "peek through" and not fire checkBtnDown() simultaneously?
Hi, i don't know if you meaning this or not..hope this helps you.
in fact you just need to detect if your mouse clicked or not, for that we need to something to detect this for second time.
var app = angular.module("app", []);
app.controller("ctrl", function ($scope) {
$scope.alreadyClicked = false;
$scope.action = function() {
console.log("action");
}
$scope.mousedown = function (event) {
if ($scope.alreadyClicked) {
$scope.action();
} else {
console.log("mousedown");
$scope.alreadyClicked = true;
}
}
});
.box {
position: relative;
background: #eee;
border: solid 1px #ccc;
float: left;
width: 100px;
height: 100px;
cursor:pointer
}
<!DOCTYPE html>
<html ng-app="app" ng-controller="ctrl">
<head>
<title></title>
</head>
<body>
<div class="box" ng-mousedown="mousedown($event)">
{{alreadyClicked ? "click to call action":"click to call mousedown"}}
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>
</html>
What I decided to do using your suggestion Mayer,
"In fact you just need to detect if your mouse clicked or not, for that we need to [do] something to detect this for second time."
was to measure the maximum time between the first and second mouse-events, then use a setTimeout().
Here's some pseudo-code to illustrate my idea.
// First mouse-down event
if (firstEvent) {
var timerID = setTimeout(function() {
// handle first mouse-event
}, dTimeBetween);
}
// Second mouse-down event
if (secondEvent) {
clearTimeout(timerID);
function() {
// handle second mouse-event
}
}

jQuery click event seems to be kind of late

I'm working on a Facebook reaction bar so it is pretty hard to copy the code here because it has a lot of events binded but all of you got facebook so if you want to check it by yourself - please do it.
The thing is that I managed to move the reaction bar under the react root and now I wanted to make the clicked reaction counter change the background color of itself to green.
And everything is working almost good excluding one thing: it is one click behind. To make you understand better I recorded little example how it looks. The red pulse ring appears when I click: https://vid.me/HqYp
Here is the changing code:
$(this).find('div._iu-[role="toolbar"]').bind('click',function(){
$(this).find('p.counter').each(function(){$(this).css('background-color','#48649F');});
$(this).find('span[aria-pressed="true"]').find('p.counter').css('background-color','green');
});
$(this) is div[id*="post"] so in $(this) I'm getting div with the whole post.
I thought that maybe I should use a callback function after changing-every-counter-to-default-color function but I don't know am I right and if it's right solution.
Thanks from above. (:
You can probably simplify this a bit. Although without the html structure I can't know for sure how the layout of the function works with respect to the event origin. Also I am not sure when the aria-pressed is set to true so I made the function a bit more generic. You simply add a data attribute to target the span you want to be targeted by the click.
<div class="_lu-" role="toolbar" data-target=".facebook-counter">
Later in your javascript you do the following
var $t = $(this);
var $t.target = $(this).data('target');
$t.on('click','div._lu-[role="toolbar"]', function() {
$t.find($t.target).css({
'background-color':'green'
}).siblings().css({'background-color','#48649F'});
});
This code is assuming first that your spans are in the same container, and second that the first $(this) refers to the parent container of this whole toolbar, and last that you have put data-target="" attributes with selectors for the appropriate target you want to affect.
This is a sample:
$(document).ready(function(){
$('.toolbar').on('click','.toolbar-item .icon', function(event) {
event.preventDefault();
event.stopPropagation();
if(!this.$) this.$ = $(this);
if(!this.parent) this.parent = this.$.parent();
if(!this.counter) this.counter = this.$.siblings('.counter');
this.parent.addClass('selected').siblings('.selected').removeClass('selected');
var count = this.counter.data('value');
count++;
this.counter.data('value',count);
this.counter.html(count);
});
});
.toolbar {
font-size:0;
text-align:center;
}
.toolbar-item .icon {
background:#FFF;
padding:30px;
border:1px solid #AAA;
border-radius:100%;
margin:0 20%;
transition:0.8s ease all;
}
.selected .icon {
background:#369;
}
.toolbar-item .counter {
background:#E0E0E0;
margin:0 10px;
transition:0.4s ease background;
}
.selected .counter {
background:#509050;
}
.toolbar-item {
font-size:10pt;
width:25%;
display:inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="toolbar">
<div class="toolbar-item">
<div class="icon">Like</div>
<div class="counter" data-value="0">0</div>
</div>
<div class="toolbar-item">
<div class="icon">Wow</div>
<div class="counter" data-value="0">0</div>
</div>
<div class="toolbar-item">
<div class="icon">Sad</div>
<div class="counter" data-value="0">0</div>
</div>
<div class="toolbar-item">
<div class="icon">Angry</div>
<div class="counter" data-value="0">0</div>
</div>
</div>
As of jQuery 1.7 they introduced the .on('click', function().... method. Try that instead and see if you get the same results.
Quick answer without having tested or the time to test your code. I recently had a performance issue with a nested function, so maybe look at that second line with the .each() method.

Categories