I am trying to create overlays for each row in a rails iteration.
<% #inquiries.each do |inquiry| %>
<div class= "col-xs-12 col-sm-12 col-lg-12 col-md-12">
</div>
<% end %>
For each inquiry, I want to have a button which when clicked, shows an overlay with details of comments on that inquiry.
Each Inquiry has many comments.
A simple overlay can be made by:
<div id="overlay">
<div id="text">Overlay Text</div>
<button onclick="off()">Turn off overlay</button>
</div>
<div style="padding:20px">
<h2>Overlay with Text</h2>
<button onclick="on()">Turn on overlay effect</button>
</div>
<script>
function on() {
document.getElementById("overlay").style.display = "block";
}
function off() {
document.getElementById("overlay").style.display = "none";
}
</script>
#overlay {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.8);
z-index: 2;
cursor: pointer;
}
#text{
position: absolute;
top: 50%;
left: 50%;
font-size: 50px;
color: white;
transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
}
But this uses ids for identifying corresponding overlapys. If I use classes, there can't be any identifications and overlays will interfere.
My question is how can I have separate overlays with different contents for each inquiry That means each inquiry has a button which opens an overlay with different items(the inquiry comments) in it.
pass "this" as a parameter in your click function, this will give you access to the current element that was clicked. Then traverse the parameter in your function to access its parent element. Example:
<button onclick="on(this)">Turn on overlay effect</button>
function on(clickedElement) {
clickedElement.parentElement.parentElement.style.display = "block";
}
Hope this helps!
Thanks to #grey.dim I got the direction. Solved it by using:
<div class = "overlayparent">
<div class="overlay">
<div id="text">Overlay Text</div>
<button onclick="off(this)" type="button" class = "btn btn-danger">Turn off overlay</button>
</div>
<div>
<button onclick="on(this)" type="button" class = "btn btn-danger">View/Add Comments</button>
</div>
</div>
For javascript I used:
<script>
function on(clickedElement) {
clickedElement.parentElement.parentElement.getElementsByClassName("overlay")[0].style.display = "block";
}
function off(clickedElement) {
clickedElement.parentElement.parentElement.getElementsByClassName("overlay")[0].style.display = "none";
}
</script>
Related
So what I'm trying to make is a map of Germany with markers.
and when clicked on a marker a div (content) will show with some things in it
is there a way to let JavaScript know which marker I clicked and it will open the corresponding content div, in total it will be about 200 markers so it must be a decently efficient code and my knowledge about JavaScript is not that great
this is the code I have for now
<div class="map">
<img src="/images/map.jpg">
</div>
<div class="markers" style="top: 60%; left: 35%;">
<div class="content" style="display: none;">
<h1>Test</h1>
<p>test</p>
</div>
</div>
<div class="markers" style="top: 20%; left: 60%;">
<div class="content" style="display: none;">
<h1>Test2</h1>
<p>test2</p>
</div>
</div>
Basic idea is using event delegation and listen to the click on the parent. You can than determine what was clicked and you can toggle a class to show the hidden element. Basic idea:
document.querySelector(".map-wrapper").addEventListener("click", function (e) {
// find if a marker was clicked
var marker = e.target.closest('.marker');
console.log(marker)
// was one clicked?
if (marker) {
// Hide any others that may be showing
var active = document.querySelector('.marker.active');
if(active && active!==marker) {
active.classList.remove('active');
}
// toggle the info so it shows/hides
marker.classList.toggle('active');
}
});
.map-wrapper {
position: relative;
background-color: #CCCCCC;
width: 400px;
height: 400px;
}
.marker {
position: relative;
}
.marker::after {
content: '🚻';
}
.marker .content {
display: none;
opacity: 0;
}
.marker.active .content {
position: absolute;
display: block;
opacity: 1;
transition: opacity 0.3s;
background-color: #CCFF00;
border: 2px solid red;
margin: 20px;
}
<div class="map-wrapper">
<div class="marker" style="left:100px; top: 100px;">
<div class="content">
<h1>Test1</h1>
<p>test1</p>
</div>
</div>
<div class="marker" style="left:150px; top: 270px;">
<div class="content">
<h1>Test2</h1>
<p>test2</p>
</div>
</div>
<div class="marker" style="left: 46px; top: 143px;">
<div class="content">
<h1>Test3</h1>
<p>test3</p>
</div>
</div>
</div>
There is no need to add any IDs or other means to identify the correct .content to show.
Add a click event listener to each marker and toggle a class on the element. The rest can be done with CSS.
// Find all of the .markers elements
const markers = document.querySelectorAll('.markers');
// Loop through the .markers
markers.forEach((marker) => {
// Add event listener to each .marker
marker.addEventListener('click', (e) => {
if (e.currentTarget.classList.contains('active')) {
// If the clicked element is active, deactivate it...
e.currentTarget.classList.remove('active');
} else {
// ...otherwise, deactivate any other active .markers...
removeClass(markers, 'active');
// ...and activate the clicked .marker
e.currentTarget.classList.add('active');
}
})
});
// Helper function to remove a class from a collection of elements
function removeClass(els, className) {
els.forEach((el) => {
el.classList.remove(className);
});
}
.markers {
border: 1px solid #e6e6e6;
}
.markers .content {
display: none;
}
.markers.active .content {
display: block;
}
<div class="markers" style="top: 60%; left: 35%;">
<p>
Marker 1
</p>
<div class="content">
<h1>Test</h1>
<p>test</p>
</div>
</div>
<div class="markers" style="top: 20%; left: 60%;">
<p>
Marker 2
</p>
<div class="content">
<h1>Test2</h1>
<p>test2</p>
</div>
</div>
I am trying to display a message at the bottom when someone click on checkbox.
<style>
.stick {
background-color: red;
height: 60px;
position: fixed;
width: 100%;
left: 0;
}
</style>
<div class="col-md-12" id="compare" style="stick; display:none;">
<div class="separator"></div>
<div class="alert alert-info text-md-center">
<span class="text-md-center">
<button class="btn">
My message
</span>
</div>
</div>
<script>
function showProductsCompare() {
document.getElementById('compare').style.display = "block";
}
</script>
until now, all it's correct, the message appear on the page when the code is inserted
but I tried to make a sticky message like this page https://www.homedepot.com/s/french%2520door%2520refrigerators?NCNI-5 (click on the checkbox.
I don't find example or to make that.
Thank you.
This will do the work:
.stick {
background-color: red;
height: 60px;
position: fixed;
width: 100%;
left: 0;
buttom: 0;
}
You will need to give the div a class of "stick":
<div class="col-md-12 stick" id="compare" style="stick; display:none;">
I am working on a site where I employ the Overlay effect. I found how to do it on W3 Schools and it's quite easy.
However, I am trying to have two separate overlays on the same page: click on one button to see one set of text, click on a second to see another.
The problem I am having is that I don't know how to differentiate the separate overlays. In my example below, if a user clicks on the first overlay button, then get the text meant for the second overlay. And if they click on the second overlay button they get the text meant for the second overlay. I can't seem to get the first overlay text to appear, in other words.
I imagine it is something fairly simple but I haven't figured it out on my own.
Below is some code. This is not my actual site, but a slightly edited version of what's offered on W3. If I could learn how to differentiate the two buttons here I can do it on my own site.
Thank you for your help.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSS -->
<style>
#overlay1 {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.5);
z-index: 2;
cursor: pointer;
}
#overlay2 {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.5);
z-index: 2;
cursor: pointer;
}
#text{
position: absolute;
top: 50%;
left: 50%;
font-size: 50px;
color: white;
transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
}
</style>
</head>
<body>
<!-- Overlay 1: -->
<div id="overlay1" onclick="off()">
<div id="text">Overlay 1 Text</div>
</div>
<div style="padding:20px">
<h2>Overlay with Text Examples</h2>
<button onclick="on()">Overlay 1</button>
</div>
<script>
function on() {
document.getElementById("overlay1").style.display = "block";
}
function off() {
document.getElementById("overlay1").style.display = "none";
}
</script>
<!-- Overlay2: -->
<div id="overlay2" onclick="off()">
<div id="text">Overlay 2 Text</div>
</div>
<div style="padding:20px">
<button onclick="on()">Overlay 2</button>
</div>
<script>
function on() {
document.getElementById("overlay2").style.display = "block";
}
function off() {
document.getElementById("overlay2").style.display = "none";
}
</script>
</body>
</html>
You are calling the same on and off functions for both overlays... In other words, you are redefining the functions.
Change your body to the following:
<!-- Overlay 1: -->
<div id="overlay1" onclick="off('overlay1')">
<div id="text">Overlay 1 Text</div>
</div>
<div style="padding:20px">
<h2>Overlay with Text Examples</h2>
<button onclick="on('overlay1')">Overlay 1</button>
</div>
<!-- Overlay2: -->
<div id="overlay2" onclick="off('overlay2')">
<div id="text">Overlay 2 Text</div>
</div>
<div style="padding:20px">
<button onclick="on('overlay2')">Overlay 2</button>
</div>
<script>
function on(id) {
document.getElementById(id).style.display = "block";
}
function off(id) {
document.getElementById(id).style.display = "none";
}
</script>
I am trying to create a page with multiple modals on but for each modal i am creating a button with a function attached with onclick() to open them.
Is there a way which I could write one function which could then open any of the modals on page depending on the container the button is in?
Here is my example code.
<div>
<button type="button" onclick="showModal1()">Open Modal</button>
<div id="overlay"></div>
<div class="modal" id="modal1">
<span class="close" onclick="hideModal1()"></span>
<p>modal content</p>
</div>
</div>
<div>
<button type="button" onclick="showModal2()">Open Modal</button>
<div id="overlay"></div>
<div class="modal" id="modal2">
<span class="close" onclick="hideModal2()"></span>
<p>modal content</p>
</div>
</div>
js
function showModal1() {
document.getElementById("modal1").style.display = "block",
document.getElementById("overlay").style.display = "block"
}
function hideModal1() {
document.getElementById("modal1").style.display = "none",
document.getElementById("overlay").style.display = "none"
}
function showModal2() {
document.getElementById("modal2").style.display = "block",
document.getElementById("overlay").style.display = "block"
}
function hideModal2() {
document.getElementById("modal2").style.display = "none",
document.getElementById("overlay").style.display = "none"
}
Here is a way.
<button type="button" onclick="showModal(1)">Open Modal</button>
<div id="overlay"></div>
<div class="modal" id="modal1">
<span class="close" onclick="hideModal(1)"></span>
<p>modal content</p>
</div>
<button type="button" onclick="showModal(2)">Open Modal</button>
<div id="overlay"></div>
<div class="modal" id="modal2">
<span class="close" onclick="hideModal(2)"></span>
<p>modal content</p>
</div>
js
function showModal(modal_no) {
document.getElementById("modal"+modal_no).style.display = "block",
document.getElementById("overlay").style.display = "block"
}
function hideModal(modal_no) {
document.getElementById("modal"+modal_no).style.display = "none",
document.getElementById("overlay").style.display = "none"
}
If you're able to use jQuery, you can bind an event handler to the "click" JavaScript element using the .click() method, and you can find nearby elements using .siblings() and .parent() (among others). This way, you just need to define one binding for each of the modal opening class and the modal closing class, and use their context to determine which modal to open and close. Note that $(this) captures the specific element that was clicked on.
$(function() {
$('.modal-open').click(function() {
$(this).siblings('.modal').add('#overlay').show();
});
$('.modal-close').click(function() {
$(this).parent('.modal').add('#overlay').hide();
});
});
.modal {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: none;
z-index: 100;
background: #fff;
min-width: 300px;
padding: 10px;
}
.modal-close {
cursor: pointer;
float: right;
}
#overlay {
opacity: 0.4;
background-color: #000;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 99;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="display:none" id="overlay"></div>
<div>
<button class="modal-open">Open Modal #1</button>
<div style="display:none" class="modal">
<span class="modal-close">x</span>
<p>Modal #1 content</p>
</div>
</div>
<div>
<button class="modal-open">Open Modal #2</button>
<div style="display:none" class="modal">
<span class="modal-close">x</span>
<p>Modal #2 content</p>
</div>
</div>
Note: In order for .siblings('.modal') to work correctly here, the button and modal should be placed within their own <div> element, or you run the risk that the button could be siblings with two elements with the modal class.
You could also do this with vanilla JavaScript using .addEventListener. You'll have to get sibling and parent elements in a different way, of course.
Here's a simple example thet does what you asked for, using only one function. Of course, one could (and should) try to make it even more generic like thesublimeobject did in his answer, getting rid of "onclick" to separate HTML and script.
function showModal(modalId) {
document.getElementById("modal" + modalId).style.display = "block",
document.getElementById("overlay").style.display = "block"
}
function hideModal(modalId) {
document.getElementById("modal" + modalId).style.display = "none",
document.getElementById("overlay").style.display = "none"
}
.modal {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: none;
z-index: 100;
background: #fff;
min-width: 300px;
padding: 10px;
}
.modal .close {
cursor: pointer;
float: right;
}
#overlay {
display: none;
opacity: 0.4;
background-color: #000;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 99;
}
<div id="overlay"></div>
<button type="button" onclick="showModal(1)">Open Modal</button>
<div class="modal" id="modal1">
<span class="close" onclick="hideModal(1)">X</span>
<p>modal content</p>
</div>
<button type="button" onclick="showModal(2)">Open Modal</button>
<div class="modal" id="modal2">
<span class="close" onclick="hideModal(2)">X</span>
<p>modal content</p>
</div>
First, put a class of some sort on all of your buttons; let's say modal__trigger. Then assign each of them some sort of dynamic data-attribute; let's say, for example,
<button class="modal__trigger" data-modal="modal--id">Button</button>
Now, for each modal, assign a matching ID:
<div class="modal" id="modal--id">Content</div>
Now, all you need to do is add listeners with whatever events you want, like open, close, etc.
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', open.bind(buttons[i]))
}
function open() {
let id = this.getAttribute('data-modal')
let modal = document.getElementById(id)
modal.classList.add('modal--visible')
}
function close() {
(however you want to close the modal, using the same sort of logic)
}
This is an extremely simplified version that will work in a base case. I have a much more complex library written for our internal team if you would like me to link you to it, but I don't know if it's necessary at all in this case.
My code looks something like :-
<div id="boxgallery" class="boxgallery" data-effect="effect-3">
<div class="panel"><img src="img/2.jpg" alt="Image 2" />
<button class="button overlay-launcher" id="pop2">
link
</button>
<div id="pop2" class="overlay-background"></div>
<div id="pop2" class="overlay-content">
<button id="pop2" class="overlay-close">Close overlay Window</button>
</div>
</div>
<div class="panel"><img src="img/3.jpg" alt="Image 3" />
<button class="button overlay-launcher" id="pop3">
link
</button>>
<div id="pop3" class="overlay-background"></div>
<div id="pop3" class="overlay-content">
<button id="pop3" class="overlay-close">Close overlay Window</button>
</div>
</div>
<div class="panel"><img src="img/1.jpg" alt="Image 1" />
<button class="button overlay-launcher" id="pop1">
link
</button>>
<div id="pop1" class="overlay-background"></div>
<div id="pop1" class="overlay-content">
<button id="pop1" class="overlay-close">Close overlay Window</button>
</div>
</div>
<div class="panel"><img src="img/4.jpg" alt="Image 4" />
<button class="button overlay-launcher" id="pop4">
link
</button>>
<div id="pop4" class="overlay-background"></div>
<div id="pop4" class="overlay-content">
<button id="pop4" class="overlay-close">Close overlay Window</button>
</div>
</div>
</div>
I was trying :-
$(function() {
$(".overlay-launcher").click(function() {
$(".overlay-content,.overlay-background").toggleClass("active");
});
});
but it would work only if i have only one of those
or if i write the jquery for each one separately
what i want to achieve is if i click on the launcher for the pop1 then the content and background of the 1st overlay should appear
same for the rest
the nearest I found was this Single function to toggle multiple divs inside other divs individually
but it doesn't really solve the problem in my specific case I,
I ahve to toggle the active class based on the class of the element
EDIT:
CSS goes like this:-
.overlay-background {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: white;
opacity: .50;
z-index: 1000;
}
.overlay-content {
background-color: white;
border-radius: 10px;
box-shadow: 0 0 20px 0 #222;
display: none;
height: 240px;
left: 50%;
margin: -120px 0 0 -160px;
padding: 10px;
position: absolute;
top: 50%;
width: 320px;
z-index: 1000;
}
.overlay-background .active,
.overlay-content .active {
display: block;
}
Below are the 2 things that needs to be done to make it work
In css,
.overlay-background.active, .overlay-content.active {
display: block;
}
In Javascript,
$(".overlay-launcher").click(function () {
$('.overlay-content,.overlay-background').removeClass("active");
$(this).siblings('.overlay-content,.overlay-background').addClass("active");
});
$('.overlay-close').on('click', function(){
$('.overlay-content,.overlay-background').removeClass("active");
});
Working fiddle https://jsfiddle.net/sachin_puthran/ssmstjvu/7/
You should not have multiple elements in your page with the same id like that. id values should be unique within a particular page.
Also note other syntax errors:
</button>>
</button>>
$(".overlay-launcher,")