Could some one please tell me how to refactor the JavaScript without "this" in a way that explains the use of "this" in the browser context? (please don't answer the following question with jQuery solutions)
I have passed e (event) into the callback function and implemented:
e.target.classList.toggle("active");
var panel = e.target.nextElementSibling;
What I have implemented has worked. However I want to know to what benefit/why you would use "this" in the context shown, it doesn't seem as declarative as e.target. Is this a function binding issue?
(other snippet related questions below snippet)
I have taken the below snippet from W3schools, it is used for creating an accordion menu:
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
/* Toggle between adding and removing the "active" class,
to highlight the button that controls the panel */
this.classList.toggle("active");
/* Toggle between hiding and showing the active panel */
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
/* Style the buttons that are used to open and close the accordion panel */
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
transition: 0.4s;
}
/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
.active, .accordion:hover {
background-color: #ccc;
}
/* Style the accordion panel. Note: hidden by default */
.panel {
padding: 0 18px;
background-color: white;
display: none;
overflow: hidden;
}
<button class="accordion">Section 1</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
<button class="accordion">Section 2</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
<button class="accordion">Section 3</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
Could some one please explain the relationship between the loop and the event listener?
The way I understand it, I would expect that:
every time the DOM is altered/reloads =>
the loop runs =>
adding an event listener on each html collection element=>
if HTML element clicked == true (or) the event is fired
the class is toggled to active
the following if statement is executed and styles may or may not be applied inline to the html element.
This seems like a computationally expensive method of adding event listeners.
Is the above statement that I have written correct if not exactly what is happening?
Is there a more efficient way of writing the event listener loop snippet?
I.e. using event bubbling on a containing element perhaps?
Here's a simple HTML layout:
<main>
<div class='A'></div>
<section></section>
<div class='B'></div>
<section></section>
<div class='C'></div>
</main>
Here's the JavaScript using a programming paradigm called Event Delegation:
document.querySelector('main').addEventListener('click', eventHandler);
Because the majority of the events bubble (click bubbles), the event listener should be registered to an ancestor tag (in this example that would be <main>) of the tags you want to control via events (in this example it's .A, .B, and .C). Now the event handler:
function eventHandler(event) {
const listener = event.currentTarget; // or `this` points to `<main>`
const clicked = event.target; // This is the tag user actually clicked
....
We need to control exactly what reacts to a click and what doesn't react when clicked. We can use if/if else or switch() or even a ternary to delegate events to what we want while excluding what we don't want. Continuing within eventHandler(e)...
....
// All <section>s and even <main> is excluded
if (clicked.matches('div')) {
if (clicked.matches('.A')) {
clicked.style.background = 'red';
}
if (clicked.matches('.C') {
clicked.style.background = 'blue';
}
}
// .B was never mentioned with any specific intructions so it's also excluded.
}
The example below is pretty much the same delegation scheme as the previous explination except with an additional CSS trick with adjacent sibling combinator:
.accordion.active+.panel {
display: block;
}
Whenever a button is .active, the .panel that follows it will disappear.
document.body.addEventListener("click", togglePanel);
function togglePanel(e) {
const clk = e.target;
if (clk.matches('.accordion')) {
clk.classList.toggle("active");
}
};
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
transition: 0.4s;
}
.active,
.accordion:hover {
background-color: #ccc;
}
.panel {
padding: 0 18px;
background-color: white;
display: none;
overflow: hidden;
}
.accordion.active+.panel {
display: block;
}
<button class="accordion">Section 1</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
<button class="accordion">Section 2</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
<button class="accordion">Section 3</button>
<div class="panel">
<p>Lorem ipsum...</p>
</div>
I'm trying to build an "accordion" style collapsible div into my web page as described here on w3c schools...
accordion description
I've got most of it working - my code is this:
ASP:
<div class="col-md-4">
<button class="accordion">Section 1</button>
<div class="content">
<asp:Table ID="Consumable_table" runat="server">
<asp:TableHeaderRow>
<asp:TableHeaderCell>
<h2>
<u>Consumable Stock</u>
</h2>
</asp:TableHeaderCell>
</asp:TableHeaderRow>
</asp:Table>
</div>
</div>
CSS:
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;}
.active, .accordion:hover {
background-color: #ccc;}
.content {
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;}
And I've added the following Jscript:
$(document).ready(function () {
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function () {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
return false;
});
}
});
The code seems to work fine and when I click the Accordion element it expands - But it then seems to post back and the accordion collapses again and doesn't display.
My question is how can I have it expand and stay expanded as described in the tutorial. I've seen a number of answers here and on various sites that suggests "return false" might be enough.
Does this have anything to do with the ASP table inside the div?
The dafault behaviour of the HTML button is to submit the form when clicked (its type is submit by default). All you need to do is to add type="button" attribute to the element, like this:
<button class="accordion" type="button">Section 1</button>
That should resolve the problem - it indicates that the button is just a simple clickable button, without any special action.
This answer also covers it: <button> vs. <input type="button" />. Which to use?
There are two ways,
By default the button behavior like submit button so postback will happen. If you want to prevent postback you can use below code.
<button class="accordion" onclick="return false;">Section 1</button>
You can use type attribute to prevent submit behavior.
<button type="button" class="accordion">Section 1</button>
I've come across some strange behavior in Chrome 60.0 when removing a class from an element with a very specific configuration.
I removed the fade class from an <h1> element and it makes it completely disappear. The problem can be reproduced by removing the class in the dev-tools element inspector as well. Can anyone tell me what's going on here?
The element should just go back to full opacity after clicking the button.
var button = document.querySelector('button');
var h1 = document.querySelector('h1');
button.addEventListener('click', function(){
h1.classList.remove('fade');
});
.center {
overflow: hidden;
}
h1 {
float: left;
overflow: hidden;
}
.fade {
opacity: .2;
}
<div class="center">
<div>
<h1 class="fade">Watch me disappear</h1>
</div>
</div>
<button>Click</button>
Removing the overflow: hidden property defined for h1, will solve your problem.
var button = document.querySelector('button');
var h1 = document.querySelector('h1');
button.addEventListener('click', function() {
h1.classList.remove('fade');
});
.center {
overflow: hidden;
}
h1 {
float: left;
}
.fade {
opacity: .2;
}
<div class="center">
<div>
<h1 class="fade">Watch me disappear</h1>
</div>
</div>
<button>Click</button>
I've got a div learn-more that expands to the size of the whole page by adding a CSS class as follows:
.learn-more{
padding:10px;
font-size: 20px;
text-align: center;
margin-top:20px;
font-family: klight;
-webkit-transition:2s;
-moz-transition:2s;
transition:2s;
margin-left: auto;
margin-right: auto;
cursor: pointer;
}
.clicked{
width:100% !important;
visibility: visible;
height: 600px !important;
margin-top:-111px !important;
z-index: 10;
}
This addition is done using JS as follows:
$('.learn-more').on('click', function(){
$(this).addClass('clicked');
$(this).addClass('fire-inside');
});
Now the problem is that I have a button inside the expanded div to reduce the size of this same expanded window.
The JavaScript to do the same is
$('.close-overlay').on('click', function(){
$('.learn-more-btn').removeClass('clicked');
$('.learn-more-btn').removeClass('fire-inside');
});
However this doesn't work as the browser is reading the click on close-overlay as a click on learn-more as the HTML for it as
<div class="learn-more fire-btn">
<p class="fmore">
Find out more
</p>
<div class="inside-text">
<p >
...
</p>
<p class="close-overlay">Close</p>
</div>
</div>
I've added a fiddle for it:
DEMO: http://jsfiddle.net/Newtt/AqV96/
On clicking close, I need the overlay to revert to original size.
Try this on for size!
$(".fmore").on("click", function () {
$(".learn-more").addClass("clicked");
});
$(".close-overlay").on("click", function () {
$(".learn-more").removeClass("clicked");
});
$('.learn-more').on('click', function(){
if ( $(this).hasClass('clicked') )
$(this).removeClass('clicked').removeClass('fire-inside');
else
$(this).addClass('clicked').addClass('fire-inside');
});
Just use the same on click event and check if it has class 'clicked'. You could also use toggle function.
I want to display the alert box but for a certain interval. Is it possible in JavaScript?
If you want an alert to appear after a certain about time, you can use this code:
setTimeout(function() { alert("my message"); }, time);
If you want an alert to appear and disappear after a specified interval has passed, then you're out of luck. When an alert has fired, the browser stops processing the javascript code until the user clicks "ok". This happens again when a confirm or prompt is shown.
If you want the appear/disappear behavior, then I would recommend using something like jQueryUI's dialog widget. Here's a quick example on how you might use it to achieve that behavior.
var dialog = $(foo).dialog('open');
setTimeout(function() { dialog.dialog('close'); }, time);
May be it's too late but the following code works fine
document.getElementById('alrt').innerHTML='<b>Please wait, Your download will start soon!!!</b>';
setTimeout(function() {document.getElementById('alrt').innerHTML='';},5000);
<div id='alrt' style="fontWeight = 'bold'"></div>
setTimeout( function ( ) { alert( "moo" ); }, 10000 ); //displays msg in 10 seconds
In short, the answer is no. Once you show an alert, confirm, or prompt the script no longer has control until the user returns control by clicking one of the buttons.
To do what you want, you will want to use DOM elements like a div and show, then hide it after a specified time. If you need to be modal (takes over the page, allowing no further action) you will have to do additional work.
You could of course use one of the many "dialog" libraries out there. One that comes to mind right away is the jQuery UI Dialog widget
I finished my time alert with a unwanted effect.... Browsers add stuff to windows. My script is an aptated one and I will show after the following text.
I found a CSS script for popups, which doesn't have unwanted browser stuff. This was written by Prakash:- https://codepen.io/imprakash/pen/GgNMXO. This script I will show after the following text.
This CSS script above looks professional and is alot more tidy. This button could be a clickable company logo image. By suppressing this button/image from running a function, this means you can run this function from inside javascript or call it with CSS, without it being run by clicking it.
This popup alert stays inside the window that popped it up. So if you are a multi-tasker you won't have trouble knowing what alert goes with what window.
The statements above are valid ones.... (Please allow).
How these are achieved will be down to experimentation, as my knowledge of CSS is limited at the moment, but I learn fast.
CSS menus/DHTML use mouseover(valid statement).
I have a CSS menu script of my own which is adapted from 'Javascript for dummies' that pops up a menu alert. This works, but text size is limited. This hides under the top window banner. This could be set to be timed alert. This isn't great, but I will show this after the following text.
The Prakash script above I feel could be the answer if you can adapt it.
Scripts that follow:- My adapted timed window alert, Prakash's CSS popup script, my timed menu alert.
1.
<html>
<head>
<title></title>
<script language="JavaScript">
// Variables
leftposition=screen.width-350
strfiller0='<table border="1" cellspacing="0" width="98%"><tr><td><br>'+'Alert: '+'<br><hr width="98%"><br>'
strfiller1=' This alert is a timed one.'+'<br><br><br></td></tr></table>'
temp=strfiller0+strfiller1
// Javascript
// This code belongs to Stephen Mayes Date: 25/07/2016 time:8:32 am
function preview(){
preWindow= open("", "preWindow","status=no,toolbar=no,menubar=yes,width=350,height=180,left="+leftposition+",top=0");
preWindow.document.open();
preWindow.document.write(temp);
preWindow.document.close();
setTimeout(function(){preWindow.close()},4000);
}
</script>
</head>
<body>
<input type="button" value=" Open " onclick="preview()">
</body>
</html>
2.
<style>
body {
font-family: Arial, sans-serif;
background: url(http://www.shukatsu-note.com/wp-content/uploads/2014/12/computer-564136_1280.jpg) no-repeat;
background-size: cover;
height: 100vh;
}
h1 {
text-align: center;
font-family: Tahoma, Arial, sans-serif;
color: #06D85F;
margin: 80px 0;
}
.box {
width: 40%;
margin: 0 auto;
background: rgba(255,255,255,0.2);
padding: 35px;
border: 2px solid #fff;
border-radius: 20px/50px;
background-clip: padding-box;
text-align: center;
}
.button {
font-size: 1em;
padding: 10px;
color: #fff;
border: 2px solid #06D85F;
border-radius: 20px/50px;
text-decoration: none;
cursor: pointer;
transition: all 0.3s ease-out;
}
.button:hover {
background: #06D85F;
}
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
.overlay:target {
visibility: visible;
opacity: 1;
}
.popup {
margin: 70px auto;
padding: 20px;
background: #fff;
border-radius: 5px;
width: 30%;
position: relative;
transition: all 5s ease-in-out;
}
.popup h2 {
margin-top: 0;
color: #333;
font-family: Tahoma, Arial, sans-serif;
}
.popup .close {
position: absolute;
top: 20px;
right: 30px;
transition: all 200ms;
font-size: 30px;
font-weight: bold;
text-decoration: none;
color: #333;
}
.popup .close:hover {
color: #06D85F;
}
.popup .content {
max-height: 30%;
overflow: auto;
}
#media screen and (max-width: 700px){
.box{
width: 70%;
}
.popup{
width: 70%;
}
}
</style>
<script>
// written by Prakash:- https://codepen.io/imprakash/pen/GgNMXO
</script>
<body>
<h1>Popup/Modal Windows without JavaScript</h1>
<div class="box">
<a class="button" href="#popup1">Let me Pop up</a>
</div>
<div id="popup1" class="overlay">
<div class="popup">
<h2>Here i am</h2>
<a class="close" href="#">×</a>
<div class="content">
Thank to pop me out of that button, but now i'm done so you can close this window.
</div>
</div>
</div>
</body>
3.
<HTML>
<HEAD>
<TITLE>Using DHTML to Create Sliding Menus (From JavaScript For Dummies, 4th Edition)</TITLE>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">
<!-- Hide from older browsers
function displayMenu(currentPosition,nextPosition) {
// Get the menu object located at the currentPosition on the screen
var whichMenu = document.getElementById(currentPosition).style;
if (displayMenu.arguments.length == 1) {
// Only one argument was sent in, so we need to
// figure out the value for "nextPosition"
if (parseInt(whichMenu.top) == -5) {
// Only two values are possible: one for mouseover
// (-5) and one for mouseout (-90). So we want
// to toggle from the existing position to the
// other position: i.e., if the position is -5,
// set nextPosition to -90...
nextPosition = -90;
}
else {
// Otherwise, set nextPosition to -5
nextPosition = -5;
}
}
// Redisplay the menu using the value of "nextPosition"
whichMenu.top = nextPosition + "px";
}
// End hiding-->
</SCRIPT>
<STYLE TYPE="text/css">
<!--
.menu {position:absolute; font:10px arial, helvetica, sans-serif; background-color:#ffffcc; layer-background-color:#ffffcc; top:-90px}
#resMenu {right:10px; width:-130px}
A {text-decoration:none; color:#000000}
A:hover {background-color:pink; color:blue}
-->
</STYLE>
</HEAD>
<BODY BGCOLOR="white">
<div id="resMenu" class="menu" onmouseover="displayMenu('resMenu',-5)" onmouseout="displayMenu('resMenu',-90)"><br />
Alert:<br>
<br>
You pushed that button again... Didn't yeah? <br>
<br>
<br>
<br>
</div>
ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
<input type="button" value="Wake that alert up" onclick="displayMenu('resMenu',-5)">
</BODY>
</HTML>
Pure HTML + CSS 5 seconds alert box using the details element toggling.
details > p {
padding: 1rem;
margin: 0
}
details[open] {
visibility: hidden;
position: fixed;
width: 33%;
transform: translate(calc(50vw - 50%), calc(50vh - 50%));
transform-origin: center center;
outline: 10000px #000000d4 solid;
animation: alertBox 5s;
border: 15px yellow solid
}
details[open] summary::after {
content: '❌';
float: right
}
#keyframes alertBox {
0% { visibility: unset}
100% { visibility: hidden }
}
<details>
<summary>Show the box 5s</summary>
<p>HTML and CSS popup with 5s tempo.</p>
<p><b>Powered by HTML</b></p>
</details>
Nb: the visibility stay hidden at closure, haven't found a way to restore it from CSS, we might have to use js to toggle a class to show it again. If someone find a way with only CSS, please edit this post!!
If you are looking for an alert that dissapears after an interval you could try the jQuery UI Dialog widget.
tooltips can be used as alerts. These can be timed to appear and disappear.
CSS can be used to create tooltips and menus. More info on this can be found in 'Javascript for Dummies'. Sorry about the label of this book... Not infuring anything.
Reading other peoples answers here, I realized the answer to my own thoughts/questions. SetTimeOut could be applied to tooltips. Javascript could trigger them.
by using this code you can set the timer on the alert box , and it will pop up after 10 seconds.
setTimeout(function(){
alert("after 10 sec i will start");
},10000);
You can now use the HTMLDialogElement.
In this example a dialog is created when you click the button, and a timeout function is created to close it:
async function showMessage(message) {
const dialog = document.createElement("dialog");
document.body.appendChild(dialog);
dialog.innerText = message;
dialog.show();
setTimeout(function () {
dialog.close();
}, 1000);
}
<button class="btn" onclick="showMessage('This is my message')">click me!</button>
If you want you can test it on codepen.
function alertWithTimeout(title,message,timeout){
var dialog = $("<div id='dialog-confirm' title='"+title+"'>"+message+"</div>").dialog();
setTimeout(function() { dialog.dialog('close'); }, timeout);
}
alertWithTimeout("Error","This is the message" ,5000);