I've put this in the simplest terms for this question.
if element is clicked, 'active' class is added to element, 'active' class is removed from other elements.
However, if the element is 'active' and it's clicked for a second time the 'active' class should not be "re-applied" (or called for a second time).
$(".class").click(function(){
$('.class').not(this).removeClass('active');
$(this).addClass('active');
}
For example when button 1 is clicked and has the 'active' class -> doFunction;
if ( $(".active").is("#1") ) {
doFunction();
}
when it's clicked again, a second time, the function is fired again even though the element is already 'active'. If the element is active and is clicked a second time I don't want to call the functions again. How can I achieve this?
Codepen Example: https://codepen.io/anon/pen/yvZXOB?editors=1111
Thanks!
Since you didn't specify exactly how you want to limit the functions from being called, let's look at two possibilities.
First possibility: each button you can click to activate and call some function at most one time. After that, toggling buttons will toggle the classes but not calling the other function again.
In this scenario, you can use jQuery's .one().
$(".class").one('click', function(){
$('.class').not(this).removeClass('active');
$(this).addClass('active');
if ( $(".active").is("#1") ) {
doFunction();
}
if ( $(".active").is("#2") ) {
doFunction();
}
function doFunction() {
console.log("function fired!");
}
});
.class {
padding: 10px;
border-radius: 5px;
background: #392;
width: 100px;
color: white;
text-align: center;
margin: 25px;
display: inline-block;
cursor: pointer;
}
.active {
background: #932;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="class" id="1">
button
</div>
<div class="class" id="2">
another
</div>
Second possibility: when you click between buttons, the active state is toggled, but clicking a button that's already active won't keep running the other function. However, toggling away from a button and back to it will allow that button's function to run again.
In this case, you can set some kind of flag via a variable and then check the flag to see if you're allowed to run the other function again. Function runs, flag goes up. Different button gets clicked, flag goes back down.
var preventFunction;
$(".class").on('click', function(){
if($(this).hasClass('active')) {
preventFunction = true;
} else {
preventFunction = false;
}
$('.class').not(this).removeClass('active');
$(this).addClass('active');
if ( $(".active").is("#1") ) {
if(preventFunction !== true) {
doFunctionOne();
}
}
if ( $(".active").is("#2") ) {
if(preventFunction !== true) {
doFunctionTwo();
}
}
});
function doFunctionOne() {
console.log("function one fired!");
preventFunctiong = true;
}
function doFunctionTwo() {
console.log("function two fired!");
preventFunction = true;
}
.class {
padding: 10px;
border-radius: 5px;
background: #392;
width: 100px;
color: white;
text-align: center;
margin: 25px;
display: inline-block;
cursor: pointer;
}
.active {
background: #932;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="class" id="1">
button
</div>
<div class="class" id="2">
another
</div>
Since you are dynamically adding/removing classes, the correct apporach is to use event delegation like this:
$(document).on('click', ".class:not(.active)", function(){
$('.class').removeClass('active');
$(this).addClass('active');
console.log("click triggered!");
})
https://codepen.io/connexo/pen/PQVKNY?editors=1111
This trick will work(just use one global variable and hold the last active item's id),
var last_act_id = 0;
$(".class").click(function(){
if($(this).attr('id') != last_act_id) {
last_act_id = $(this).attr('id');
$('.class').removeClass('active');
$(this).addClass('active');
doFunction();
}
function doFunction() {
console.log("function fired!");
}
});
Demo: https://codepen.io/anon/pen/Nyovjr?editors=0001
Just check to see if that event target has the class already. Since you're using jQuery you could do something like
if($('.selector').hasClass('active')) {
$('.selector').removeClass('active')
} else {
$('.selector').addClass('active')
}
Try this
$("#1").click(function(){
$('#2').removeClass('active');
if (!$("#1").hasClass('active')) {
$("#1").addClass('active');
doFunction();
}else{
console.log("already clicked");
}
});
$("#2").click(function(){
$('#1').removeClass('active');
if (!$("#2").hasClass('active')) {
$("#2").addClass('active');
doFunction();
}else{
console.log("already clicked");
}
});
function doFunction() {
console.log("function fired!");
}
I hope it helps
Related
I have a div with the attribute contenteditable = true. I can activate the div content editing by double clicking the div, this is because my div is draggable, so I use the dooble click event to activate the div edition. The fact is that I want to eliminate the complete div by clicking on it and then pressing the Delete key on the keyboard. How can I do that? How can I make it so that when I write something on the div and press the delete key, the entire div will not be deleted? I only want to delete the div when the div edition is not activated, just click on the div and then hit the delete key and voila, it is deleted.
This is my HTML Code:
$(document).ready(function() {
$('.draggable').draggable({
containment: "parent"
});
$(".draggable").resizable();
$('#MyFirstDiv').click(function() {
//HERE I WANT TO PUT THE CODE TO DELETE THE DIV.
});
$("#myContainer").on("dblclick", "#MyFirstDiv", function(e) {
e.preventDefault();
$(".draggable").draggable('disable');
this.querySelector(":scope > :first-child").focus();
});
$("#myContainer").on("blur", "#MyFirstDiv", function(e) {
e.preventDefault();
$(".draggable").draggable('enable');
});
});
#myContainer {
border: 1px solid black;
height: 400px;
width: 100%;
}
#DraggableDiv {
border: 1px solid blue;
}
<!DOCTYPE html>
<html>
<head>
<title>My Delete Div</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
</head>
<body>
<div id="myContainer">
<div id="MyFirstDiv">
<div class="draggable" contenteditable="true" id="DraggableDiv">
THIS IS MY TEXT INSIDE THE DIV
</div>
</div>
</div>
</body>
</html>
Easiest way to to capture the keydown on the delete key.
$('#MyFirstDiv').click(function(e){
e.preventDefault();
});
$('#MyFirstDiv').keydown(function(e){
e.preventDefault();
if(e.keyCode == 46) {
this.remove();
}
});
You could first just make a variable: divClicked, I store the clicked state of the div
var divClicked = false;
Then in your event listener, update divClicked (it'll be a toggled button):
$("#MyFirstDiv").click(function(e) {
e.preventDefault();
divClicked = !divClicked;
}
Finally, add a delete key event listener like so:
$("#MyFirstDiv").keydown(function(e) {
e.preventDefault();
if (e.keyCode == 46) {
if (divClicked) {
$(this).remove();
} else {
alert("Click the div first then press Delete to remove it");
}
}
})
Full code:
var divClicked = false;
$("#MyFirstDiv").click(function(e) {
e.preventDefault();
divClicked = !divClicked;
}
$("#MyFirstDiv").keydown(function(e) {
e.preventDefault();
if (e.keyCode == 46) {
if (divClicked) {
$(this).remove();
} else {
alert("Click the div first then press Delete to remove it");
}
}
})
It is not advisable to use Delete while the content is being edited. You will want to ensure that the user can click the <div> element itself without editing the content.
Since the <div> is draggable, I would advise using a handle since the click event and keypress events may get capture for content editing and not for your script.
$(function() {
function disDrag(part) {
var drag = part.closest(".draggable");
drag.draggable("disable");
$(".drag-content", drag).removeAttr("contenteditable").blur();
part.toggleClass("ui-icon-locked ui-icon-unlocked");
}
function enDrag(part) {
var drag = part.closest(".draggable");
drag.draggable("enable");
$(".drag-content", drag).attr("contenteditable", true).focus();
part.toggleClass("ui-icon-locked ui-icon-unlocked");
}
function delDrag(part) {
var drag = part.closest(".draggable");
var res = confirm("Are you sure you wish to delete this item?");
if (res) {
drag.remove();
}
}
$('.draggable')
.draggable({
containment: "parent",
handle: ".ui-drag-handle",
start: function() {
$(".ui-drag-handle", this).data("selectable", false);
},
stop: function() {
$(".ui-drag-handle", this).data("selectable", true);
}
})
.resizable();
$(".ui-drag-handle")
.data("selectable", true)
.click(function(e) {
var drag = $(this).closest(".draggable");
if ($(this).data("selectable")) {
drag.toggleClass("drag-selected");
}
});
$(".btn").click(function(e) {
switch (true) {
case $(this).hasClass("ui-icon-unlocked"):
disDrag($(this));
break;
case $(this).hasClass("ui-icon-locked"):
enDrag($(this));
break;
case $(this).hasClass("ui-icon-close"):
delDrag($(this));
break;
}
});
$(document).keyup(function(e) {
if (e.which == 46 && $(".drag-selected").length) {
delDrag($(".drag-selected"));
}
});
});
#myContainer {
border: 1px solid black;
height: 400px;
width: 100%;
}
.draggable {
border: 1px solid blue;
}
.draggable.drag-selected {
border: 1px solid #0f0;
}
.center {
margin-left: 50%;
}
.right {
float: right;
}
.ui-icon.btn {
border: 1px solid #ccc;
border-radius: 3px;
margin-top: 0px;
margin-left: 1px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<div id="myContainer">
<div class="draggable ui-widget" id="DraggableDiv">
<div class="ui-widget-header">
<span class="right ui-icon ui-icon-close btn" title="Delete the item."></span>
<span class="right ui-icon ui-icon-unlocked btn" title="Lock and disable Drag"></span>
<div class="ui-drag-handle" style="width: calc(100% - 42px);">
<span class="center ui-icon ui-icon-grip-dotted-horizontal"></span>
</div>
</div>
<div class="drag-content" contenteditable="true">
THIS IS MY TEXT INSIDE THE DIV
</div>
</div>
</div>
You can see that this is draggable, resizable, and editable. The user can disable drag by clicking the lock icon. If the select the div and click Delete (or key code 46), or they click the close icon, they will be prompted to confirm that they want to delete the item. Once they confirm that Yes they want to, the item is removed.
Since the delete could be triggered by two different ways, I created a delete function.
In regards to structure, you may not be able to get away with such simple HTML structures when dealing with more complex UI interactions. This one <div> element had all sorts of interactions tied to the click event. The user clicks to edit, select, drag... It is better to make more specific targets for some of these events so that you can better script your events.
You could save yourself a lot of time by using Dialog Widget: https://jqueryui.com/dialog/
Hope that helps.
Test
Click on the text to select.
Press D to delete. [sadly delete key didn't work on stack overflow. Simply change the key code in the if statement to change the key from D to DELETE]
Explanation
There are two functions that help solve this problem.Select: Selected the div clicked.EventListener:Listens for the keypress and deletes the selected div.
Select function
Global variable selected stores the information on the div selected.
In select function we are fetching the id name of the div clicked by using currentTarget.id from the event object 'e'.
If statements inside the select function select and deselect the div.
EventListener
Uses event object from the keypress listener to fetch the key pressed.
e.keyCode gives the key. e.which is a fallback. [for ie users]
If they keyCode is 100 (D key), then use the selected variable to get the selected div and change its css display to 'none'.
Additionally there is a else statement, where u can add js to when nothing is selected and the key is pressed.Also the css for class selected is for feedback of when the div is selected.
Here is the code snippet:
let selected;
const select = e => {
//If already selected, this will deselect the div
if(selected == e.currentTarget.id) {
document.getElementById(selected).classList.remove('selected'); //some CSS
selected = null;
} else {
//select this div
selected = e.currentTarget.id;
document.getElementById(selected).classList.add('selected'); //some CSS
}
}
window.addEventListener('keypress', e => {
//Get key pressed
let key = e.keyCode || e.which;
if(selected != undefined) {
if(key == 100) {//If D is pressed
let target = document.getElementById(selected); //get the div
target.style.display = 'none'; //hide div
console.log('deleted: ' + selected);
}
} else {
//Runs if nothing is selected. Do as you please here.
}
})
.selected {
background: black;
color: white;
}
#DraggableDiv {
user-select: none;
cursor: pointer;
font-family: sans-serif;
width: 400px;
text-align: center;
padding: 10px 5px;
}
<!DOCTYPE html>
<html>
<head>
<title>My Delete Div</title>
</head>
<body>
<div id="myContainer">
<div id="MyFirstDiv">
<div id="DraggableDiv" onclick="select(event)">
Click me and press D
</div>
</div>
</div>
</body>
</html>
I want to detect if a class exist and I'm trying to use this simple function to detect if an element has a class but it doesn't work.
var parent = document.querySelector('.menu'),
child = document.querySelector('.liked');
if (parent.contains(child)) {
$('.empty').addClass("none")
}
Any help would be greatly appreciated.
Thanks in advance.
$(document).on("click", ".click", function() {
$(".submenu").addClass("liked")
})
var parent = document.querySelector('.menu'),
child = document.querySelector('.liked');
if (parent.contains(child)) {
$('.empty').addClass("none")
}
body {
font: 10vw/1.2em -apple-system, BlinkMacSystemFont, sans-serif
}
.none {
display: none
}
.liked {
color: red
}
button {
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class=click>
ADD CLASS LIKED
</button>
<div class=menu><br>
<span class=submenu>ONE</span>
<span class=submenu>TWO</span>
<span class=submenu>THREE</span>
</div>
<div class=empty><br>IF CLASS 'VISITED' EXIST, THIS TEXT MUST GO</div>
First, I'm not a fan of mixing jQuery with plain JS. Bouncing back and forth feels slightly sloppy, so as a bit of cleanup, my answer below will be solely jQuery.
Second, if you want to check again on the click of the button, then your code has to be in the click handler. Currently, you're only evaluating on the page load.
$(function() {
checkIfParentContainsChild(); //Run on page load
$(document).on("click", ".click", function() {
$(".submenu").addClass("liked");
checkIfParentContainsChild(); //Run on button click
});
});
function checkIfParentContainsChild() {
var $child = $(".menu .liked"); //Select all .liked with parent .menu
var childExists = ($child.length > 0); //Result will be true or false
//EDITED PER COMMENT
if (childExists) {
$('.empty').addClass("none");
} else {
// ...DOESN'T EXIST
}
}
Your logic is only running once on page load. If you add it into a function like so, you can also run it in the click event.
function childCheck() {
var parent = document.querySelector('.menu'),
child = document.querySelector('.liked');
if (parent.contains(child)) {
$('.empty').addClass("none")
}
}
childCheck(); // run on page load (optional)
$(document).on("click", ".click", function() {
$(".submenu").addClass("liked")
childCheck(); // run here on click event
})
body {
font: 10vw/1.2em -apple-system, BlinkMacSystemFont, sans-serif
}
.none {
display: none
}
.liked {
color: red
}
button {
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class=click>
ADD CLASS LIKED
</button>
<div class=menu><br>
<span class=submenu>ONE</span>
<span class=submenu>TWO</span>
<span class=submenu>THREE</span>
</div>
<div class=empty><br>IF CLASS 'VISITED' EXIST, THIS TEXT MUST GO</div>
Could someone help me with this, I am a bit stuck with JavaScript. Every time when someone is clicking on the question, the active class name should be added to the next sibling, but how to get that fixed. Only in plain JavaScript please. Any other frameworks do not count.
document.querySelector(".question").addEventListener("click", function() {
if(this.classList.contains("active")) {
this.classList.remove("active");
} else {
this.classList.add("active");
}
});
.faq-block .question,
.faq-block .answer {
border: 1px solid red;
padding: 10px;
}
.answer {
display: none;
}
.active {
display: block;
}
<div class="faq-block">
<div class="question">How do I cancel my order</div>
<div class="answer">Answer</div>
</div>
<div class="faq-block">
<div class="question">I am not getting an internet connection from my second SIM card</div>
<div class="answer">Answer</div>
</div>
<div class="faq-block">
<div class="question">My charger does not work and my device would not charge properly</div>
<div class="answer">Answer</div>
</div>
<div class="faq-block">
<div class="question">My fingerprint scanner is not working and does not respond when touched</div>
<div class="answer">Answer</div>
</div>
Use querySelectorAll ,document.querySelector will only select first matched element.
// get all matched element
var ques = document.querySelectorAll(".question")
// loop over the array to add event to each of the element
ques.forEach(function(item, index) {
// creating closure
(function(i) {
// adding event listerner to each element
ques[i].addEventListener("click", function() {
// this refers to the current selected element
if (this.classList.contains("active")) {
this.classList.remove("active");
} else {
this.classList.add("active");
}
});
}(index)) // passing the index to target element in the array
})
DEMO
Try this
document.querySelector(".question").addEventListener("click", function() {
if(this.classList.contains("active")) {
this.classList.remove("active");
this.nextSibling.classList.add("active")
} else {
this.nextSibling.classList.add("active");
}
});
I don't know why u need to do conditional checking. but to answer your question, you can use nextSibling
A simple adjustment to your CSS will do the trick:
.question.active+.answer {
display: block;
}
This will allow you to set the "active" class on the question, and let it reveal the answer.
Alternatively, use this.parentNode for the class, and then the CSS becomes:
.faq-block.active>.answer {
display: block;
}
This, I would argue, conveys more meaning too.
First of all document.querySelector(".question") returns the first element matching selector(documentation).
If i understood right you wanted to get .active class applied to Answers so here you are:
document.querySelectorAll(".question")
.forEach(element => element.addEventListener("click", function () {
nextNode = this.nextElementSibling;
if(!nextNode.classList.contains("active")){
nextNode.classList.add("active");
}
else{
nextNode.classList.remove('active');
}
})
);
JSFiddle
I have the following code that detects if a user is hovering over a box:
var toolTipHover = false;
$('#chartTooltip').on('mouseover', function () {
toolTipHover = true;
}).on('mouseout', function () {
toolTipHover = false;
});
$('.box').on('mouseover', function () {
$('#chartTooltip').show();
}).on('mouseout', function () {
console.log(toolTipHover);
if (!toolTipHover) {
$('#chartTooltip').hide();
}
toolTipHover = false;
});
And if they are then it shows the #chartTooltip element. (The tooltip is positioned and populated via some other means.)
However if the user hovers the tooltip itself it causes the tooltip to disappear (because they are no longer hovering the box). So I'm trying to check if the tooltip is being hovered (i.e. the next element hovered). and if so then ignore the mouseout event.
But toolTipHover is always false. I presume due to a race exception where mouseout has completed before the mouseover for the #chartTooltip can return the variable value of true.
How can I get around this?
I'm going to assume #chartToolTip is outside of .box for this. Instead of a flag variable (toolTipHover), just check the mouseleave event toElement property. So for example:
$('.box').on('mouseleave', function(e){
if (!$(e.toElement).is('.tooltip')){
$('.tooltip').hide();
}
})
Here is an example: https://jsfiddle.net/qvqafyf2/
$('.tooltip').hide();
$('.box').on('mouseover', function(e){
$('.tooltip').show();
})
$('.box').on('mouseleave', function(e){
if (!$(e.toElement).is('.tooltip')){
$('.tooltip').hide();
}
})
$('.tooltip').on('mouseleave', function(e){
if (!$(e.toElement).is('.box')){
$(this).hide();
}
})
.box{
width: 200px;
height: 200px;
background: red;
}
.tooltip{
height: 50px;
width: 50px;
background: green;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
</div>
<div class="tooltip">
hi
</div>
You could add #chartTooltip with .box in your function like this:
$('.box , #chartTooltip').on('mouseover', function()
here is fiddle
I have 3 separate scripts for 3 pop ups, Im sure there is a better way to structure these into one script? I also want to be able to only open one pop up at a time, so if .popup-new is active and i click to open .popup-new-b then .popup-new will automatically close. Any help would be much appreciated.
<script>
$(document).ready(function () {
$(".popup-trigger").click(function () {
$(".popup-new").fadeIn(300);
});
$(".popup-new > span, .popup-new").click(function () {
$(".popup-new").fadeOut(300);
});
});
</script>
<script>
$(document).ready(function () {
$(".popup-trigger-b").click(function () {
$(".popup-new-b").fadeIn(300);
});
$(".popup-new-b > span, .popup-new-b").click(function () {
$(".popup-new-b").fadeOut(300);
});
});
</script>
<script>
$(document).ready(function () {
$(".popup-trigger-c").click(function () {
$(".popup-new-c").fadeIn(300);
});
$(".popup-new-c > span, .popup-new-c").click(function () {
$(".popup-new-c").fadeOut(300);
});
});
</script>
Since I cannot see your HTML. I have added some with CSS. I hope this is what you are looking for. Ofcourse I could've asked clarify but I do not have enough reputation to add comment :(
$('button').click(function(){
$('.popup').removeClass('popped');
$('#popup-new'+$(this).attr('class')).addClass('popped');
});
.popup{
position:fixed;
width:70%;
height:70%;
top:50%;
left:50%;
margin-top:-5%;
margin-left:-35%;
background-color:#ccc;
z-index:100;
display:none;
}
.popped{
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="popup-new" class="popup">HI I am POPUP NEW</div>
<div id="popup-new-b" class="popup">HI I am POPUP-NEW-B</div>
<div id="popup-new-c" class="popup">HI I am POPUP-NEW-C</div>
<button class="">Pop up New</button>
<button class="-b">Pop up New B</button>
<button class="-c">Pop up New C</button>
You could do something like this:
popups = ['.popup-new','.popup-new-b','.popup-new,-c']
// Pass an additional parameter to popup_click, which is the index of the popup in the array
$('.popup-trigger').click({popup: 0}, popup_click);
$('.popup-trigger-b').click({popup: 1}, popup_click);
$('.popup-trigger-c').click({popup: 2}, popup_click);
function popup_click(event) {
// Here write the code to open the popup
// You can access the popup through $(popups[event.data.popup])
for (var i in popups) {
if (i != event.data.popup) { // event.data.popup contains the index that we passed
// Here write the code to close each of the other popups
// Access them through $(popups [i])
}
}
}
$('html').click(function() {
for (var i in popups) {
$(popups[i]).hide();
}
});
$('.popup-btn-close').click(function(e) {
for (var i in popups) {
$(popups[i]).hide();
}
});
$('.popup-new').click(stop_propagation);
$('.popup-new-b').click(stop_propagation);
$('.popup-new-c').click(stop_propagation);
function stop_propagation(e) {
e.stopPropagation();
}
It is generally a good idea to use arrays or objects whenever you have repetitive code you want to factor.
Note that passing parameters to an event handler this way only works with jQuery; in raw JavaScript you will have to use closures.
You can even simplify both blocks of three lines by using another array and loop (see below).
Also note that as #404UserNotFound wrote, if all of your popups share a common class, you can simplify these lines:
for (var i in popups) {
$(popups[i]).hide();
}
And turn them into:
$('.yourClassNameHere').hide(); // Will select all the elements of the right class
Which leaves you with this compact code:
popups = ['.popup-new', '.popup-new-b', '.popup-new,-c']
popup_triggers = ['.popup-trigger', '.popup-trigger-b', '.popup-trigger-c']
// Pass an additional parameter to popup_click, which is the index of the popup in the array
for (i in popup_triggers) {
$(popup_triggers[i]).click({popup: i}, popup_click);
}
function popup_click(event) {
// Here write the code to open the popup
// You can access the popup through $(popups[event.data.popup])
for (var i in suffixes) {
if (i != event.data.popup) { // event.data.popup contains the index that we passed
// Here write the code to close each of the other popups
// Access them through $(popups [i])
}
}
}
$('html').click(function() {
$('.yourClassNameHere').hide();
});
$('.popup-btn-close').click(function(e) {
$('.yourClassNameHere').hide();
});
for (i in popups) {
$(popups[i]).click(stop_propagation);
}
function stop_propagation(e) {
e.stopPropagation();
}
And finally, if all of your popups and triggers are always named the same way, with a suffix, you could condense it even further (with a few more tricks to save some space):
suffixes = ['', '-b', '-c']
for (let i in suffixes) {
$('.popup-trigger' + suffixes[i]).click(function(i) {
return function(e) {
hideAllPopups();
$('.popup-new' + suffixes[i]).toggle();
//e.stopPropagation(); // HERE
}
}(i));
}
$('.popup-btn-close').click(hideAllPopups);
//$('html').click(hideAllPopups); // HERE
function hideAllPopups() {
$('.popup').hide();
}
// Uncomment the two lines marked "HERE" to make the popups disappear whenever you click somewhere in the page (except on the buttons)
.popup {
margin: 20px auto;
padding: 20px;
background: #ccc;
width: 30%;
position: relative;
}
.popup-btn-close {
position: absolute;
top: 20px;
right: 30px;
font-weight: bold;
}
.box {
background: rgba(0,0,0,0.2);
padding: 5px;
background-clip: padding-box;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="box popup-trigger">Trigger popup #1</span>
<span class="box popup-trigger-b">Trigger popup #2</span>
<span class="box popup-trigger-c">Trigger popup #3</span>
<hr/>
<div class="popup-new popup" style="display:none">Popup #1 <span class="popup-btn-close">X</span></div>
<div class="popup-new-b popup" style="display:none">Popup #2 <span class="popup-btn-close">X</span></div>
<div class="popup-new-c popup" style="display:none">Popup #3 <span class="popup-btn-close">X</span></div>