I don't believe this has been asked before. If it has I apologise as I couldn't find it.
I have an HTML table with pictures as buttons:
<td>
<button class="trigger">
<img src="D:\Elly Research\ CO2858\Presentation\Calypso_map.jpg">
</button>
</td>
<div class="modal">
<div class="modal-content">
<span class="close-button">× </span>
<img src="D:\Elly Research\CO2858\Presentation\Calypso_map.jpg">
<script src="D:\Elly Research\CO2858\Presentation\modal.js"></script>
</div>
</div>
This is controlled by a script:
var modal = document.querySelector(".modal");
var trigger = document.querySelector (".trigger");
var closeButton = document.querySelector(".close-button");
function toggleModal() {
modal.classList.toggle("show-modal");
}
function windowOnClick(event) {
if(event.target === modal){
toggleModal();
}
}
trigger.addEventListener("click", toggleModal);
closeButton.addEventListener("click", toggleModal);
window.addEventListener("click", windowOnClick);
If I copy the format of the first picture and use it for a second picture in the same table and same page, it stops working.
Does JavaScript not work like CSS where I can use multiple ID's to be controlled by one CSS value?
This is the first time I've used JavaScript with HTML and CSS.
When you do document.querySelector(".modal") you are selecting the first node that has the class "modal". Which in your case would be the div containing the first picture. And later you add the 'click' event to only the first picture.
You can use querySelectorAll, which returns a list of all the matching nodes and loop through all nodes to add the 'click' event listener like so:
const modals = document.querySelector(".modal");
modals.forEach(modal => {
modal.addEventListener('click', toggleModal)
});
I am not sure what exactly you are trying to ask. Based on my assumptions here is a small snippet. Hope it helps you.
var modal = document.getElementById("modal")
window.addEventListener("click", windowOnClick);
document.querySelector(".close-button").addEventListener("click", toggleModal)
function showImage(event){
toggleModal()
modal.getElementsByTagName("img")[0].src =event.srcElement.src
}
function windowOnClick(event){
if(event.srcElement === modal){
toggleModal()
}
}
function toggleModal(){
modal.classList.toggle("show-modal")
}
td > img{
width: 100px;
height: auto;
}
.modal{
display: none;
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.8);
z-index=10;
}
.show-modal{
display: block !important;
}
.modal-content{
width: 60%;
height: auto;
margin: 0 auto;
}
.close-button{
color: white;
cursor: pointer;
}
#viewer{
width:100%;
height: auto;
}
<!doctype>
<html>
<head>
</head>
<body>
<table>
<tr>
<td>
<img src="https://i.imgur.com/GV6086A.jpg" onclick="showImage(event)" />
</td>
<td>
<img src="https://i.imgur.com/opERcp1.jpg" onclick="showImage(event)" />
</td>
</tr>
<tr>
<td>
<img src="https://i.imgur.com/lieUEvQ.jpg" onclick="showImage(event)" />
</td>
<td>
<img src="https://i.imgur.com/B63gaEQ.jpg" onclick="showImage(event)" />
</td>
</tr>
</table>
<div class="modal" id="modal">
<div class="modal-content">
<span class="close-button">× </span>
<img id="viewer">
</div>
</div>
</body>
</html>
If it is a small application, a simple solution to this could be the creation of an object of images, containing its details, like this:
//Here you can add as many properties you want for the objects
images = [{
src: "D:\Elly Research\CO2858\Presentation\Calypso_map.jpg"
},
{
src: "D:\Elly Research\CO2858\Presentation\Calypso_map_alternative.jpg"
}]
Then you could iterate over it to generate your table, or simply create your table with some ID refs, like <button id="0" class="trigger">, therefore you can access them in the event object array index with this code:
var id = event.target.id
So, to generate the img element inside the modal, you'll have something like this:
function toggleModal(event){
var id = event.target.id;
var div = document.getElementsByClassName('modal-content')[0];
div.innerHTML += '<img class="modal-image" src="'+images[id].src+'" />';
modal.classList.toggle("show-modal");
}
But make sure you destroy the img element when it already have one:
var child = div.querySelector("img");
if(child != null){
div.removeChild(child);
}
Hope it helps you!! Good luck with your study!
You can use js multiple times. Check the src of your images.
It's discussed already here -src absolute path problem.
Related
I'm trying to toggle a second element by clicking on the first, and not having the second as interactive but it's not working. What am I doing wrong? The element.timage should change itself and the element . rimage when selected, but only the element.timage should be clickable.
function myFunction(x) {
if (x.target.matches('.timage'))
this.classList.toggle('change');
}
document.querySelector('.container4').addEventListener('click', myFunction);
.container4 {
cursor: pointer;
display: inline- block;
}
.timage {
position: relative;
left: 50px;
}
.change .timage {
left: 200px;
}
.rimage {
position: relative;
left: 200px;
}
.change .rimage {
position: relative;
left 500px;
}
<a id="mobile-nav" href="#">
<div class="container4" onclick="myFunction
(this,event)">
<div class="container4">
<div class="timage"><img class="size-medium wp-
image-13846" src="http://4309.co.uk/wp-
content/uploads/2020/05/
IMG_20200509_104613-
288x300.jpg" alt="" width="70" height="300" />.
</div>
<div class="rimage">
<img class="size-medium wp-
image-13669" src="http://4309.co.uk/
wp-content/uploads
/2020/05/IMG_20200508_1
30758-287x300.jpg" alt="" width="90" height="300" />.
</div>
</div>
</a>
You're probably clicking the img, not the div that the image is in, so event.target is the img.
To find the nearest ancestor (starting with the current element) that matches a selector, use closest.
You're also using myFunction both in onclick="myFunction(this,event)" and in an addEventListener call. Those will provide different arguments to the function. Remove the onclick and just use addEventListener.
Here's the updated function:
function myFunction(x) {
const timage = x.target.closest(".timage");
if (timage && this.contains(timage)) {
this.classList.toggle('change');
}
}
The reason for the contains is just completeness and in many cases you can leave it off: It's to defend against closest having gone past the container element and found the match in the container's ancestors. That won't happen with your layout because timage is only used with the container, but for more general situations, I include that check. For instance:
<div class="x">
<div id="container">
<div class="x">xxx</div>
<div class="y">yyy</div>
</div>
</div>
There, if I have click hooked on #container and the user clicks yyy and I'm doing const x = event.target.closest(".x"), I'll get the .x that's the parent of the container. So this.contains(x) weeds those out.
There are so many questions like my one,even I go through this link also.But I didnt get a proper solution yet.So Im posting my issue here.
I have to popup a message when click an icon and when I click the same div where the icon is reside,it should disappear. This is working fine.But when I click outside the div also, the popup should disappear.How can I modify this javascript function to achieve it
<div>
<h5 class="haead">Search for a product title
<div class="popup" onclick="myFunction5()"> <img class="qnicon" src="question.png">
<span class="popuptext" id="myPopup5">Search product.</span>
</div>
</h5>
</div>
<script>
function myFunction5() {
var popup = document.getElementById("myPopup5");
popup.classList.toggle("show");
}
</script>
The easiest way I've found that avoids any number of other problems you could encounter, is to put the popup on top of a 100% width/height div. That "disabler" div has the same click handler as the button that would ordinarily close the popup. So if the user clicks the "X" to close, the "Ok" button (or whatever you've got set up) or the area outside the popup, same effect, it closes.
That "disabler" div (it effectively disables the entire app except for the popup) can be completely clear, or translucent, by setting the opacity.
You put the "disabler" div at z = 9998, the popup at z = 9999 (just more CSS), and they'll always be on top. Note that this may not be necessary if all your content loads into a div that is already underneath the disabler (e.g. the router-outlet div in Angular), but I usually do it anyway.
Complete basic example. I typically make a component out of this and hook it into an event bus so I can pass data in and out of it (so I can change the position, style, messages, even what happens when you click the close button). If you get this code you should be able to use some approximation of it in any framework, etc.
<html>
<head>
<style>
.button {
text-align: center;
width: 100px;
height: 30px;
background-color: green;
border: 2px solid grey;
color: white;
margin: auto;
position: relative;
}
.disabler {
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 99998;
background-color: #000000;
opacity: 0.5;
}
.popup {
position: relative;
/* Center with whatever voodoo you like */
top: calc(50% - 150px);
left: calc(50% - 150px);
width: 300px;
height: 300px;
background-color: blue;
border: 2px solid grey;
z-index: 99999;
}
</style>
</head>
<body>
<div class="button" onclick="togglePopup ( )">
Show Popup
</div>
<div class="button" onclick="showAlert ( )">
Show Alert
</div>
<!-- This div is on top of everything except the popup div -->
<!-- It effectively disables the entire app except for the popup -->
<div id="disabler" class="disabler" onclick="togglePopup ( )"></div>
<!-- This div holds the popup -->
<!-- You can only close the popup by clicking the close button, or the disabler background -->
<!-- Clicking in the blue popup area doesn't do anything (intentionally) -->
<!-- Even though you can see other widgets through the disabler, they're all inaccessible -->
<!-- Try the show alert button to confirm -->
<div id="popup" class="popup">
<div class="button" onclick="togglePopup ( )">
Close Popup
</div>
</div>
<script type="text/javascript">
togglePopup ( ); // Hide them to start.
function togglePopup ( ) {
let disabler = document.getElementById ( 'disabler' );
disabler.style.display = disabler.style.display ? '' : 'none';
let popup = document.getElementById ( 'popup' );
popup.style.display = popup.style.display ? '' : 'none';
}
function showAlert ( ) {
alert ( 'Hey there!' );
}
</script>
</body>
</html>
Here is the way to do this:
Javascript
popup.addEventListener('click',function(e) {
// This is important to prevent the popup from inheriting the event since it
// is inside the body
e.stopPropagation();
});
var body = document.body;
body.addEventListener('click', function(e){
if(popup.classList.contains('show')) {
popup.classList.remove("show");
}
);
I wish this solves your problem
Edit
That didn't work because you have to structure your code properly like this:
HTML
<div id='popup-container'>
<!-- This all inside the popup -->
<h5 class="haead">Search for a product title</h5>
<div class="popup-data">
<img class="qnicon" src="question.png">
<span class="popuptext" id="myPopup5">Search product.</span>
</div>
Show Popup
</div>
Javascript
var popupContainer = document.getElementById('popup-container');
var body = document.body;
var showPopup = document.getElementById('show-popup');
showPopup.addEventListener('click', function(e) {
e.preventDefault();
popupContainer.classList.add('show');
});
popupContainer.addEventListener('click', function(e) {
e.stopPropagation();
});
body.addEventListener('click', function(e) {
if(popupContainer.classList.contains('show'))
popupContainer.classList.remove('show');
);
I have a list of DIVS that have buttons inside. By default, all buttons are hidden. When I click within a DIV area, the current button inside of this clicked DIV are should show (class='.db') AND all previously clicked/shown buttons should be hidden (class='.dn'). In other words, at any time there should be only one button (currently clicked) shown and all other should be hidden.
I want to use vanilla Javascript and tried this below, but it won't work. I feel there is some small error but don't know where.. Note - the DIVS and buttons don't have their own unique IDs (they only have the same CSS (.posted) classes.
PS - maybe it'd be better not to add this onClick="t();" to each DIV and use an 'addEventListener' function, but this is way too much for me ; )
CSS:
.dn {display:none}
.db {display:block}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
HTML:
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
JAVASCRIPT:
function t()
{
var x=document.getElementsByClassName("posted"),i,y=document.getElementsByTagName("button");
for(i=0;i<x.length;i++)
{
x[i].y[0].className="dn";
};
x.y[0].className='db';//make sure the currently clicked DIV shows this button (?)
}
You might want to read more about selector, how to select class, block level etc.
some link might be helpful:
CSS selector:
https://www.w3schools.com/cssref/css_selectors.asp
jQuery selector:
https://api.jquery.com/category/selectors/
Solution - Using jQuery:
$('.posted').on('click', function() {
//find all class called posted with child called dn, then hide them all
$('.posted .dn').hide();
//find this clicked div, find a child called dn and show it
$(this).find('.dn').show();
});
.dn {
display: none
}
.db {
display: block
}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="posted">
<button class="dn">Reply1</button>
</div>
<div class="posted">
<button class="dn">Reply2</button>
</div>
<div class="posted">
<button class="dn">Reply3</button>
</div>
Solution - Pure js version:
//get list of div block with class="posted"
var divlist = Array.prototype.slice.call(document.getElementsByClassName('posted'));
//for each div
divlist.forEach(function(item) {
//add click event for this div
item.addEventListener("click", function() {
//hide all button first
divlist.forEach(function(el) {
el.getElementsByTagName('button')[0].classList.add('dn');
});
//show button of the div clicked
this.getElementsByTagName('button')[0].classList.remove('dn');
}, false);
});
.dn {
display: none
}
.db {
display: block
}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="posted">
<button class="dn">Reply1</button>
</div>
<div class="posted">
<button class="dn">Reply2</button>
</div>
<div class="posted">
<button class="dn">Reply3</button>
</div>
You can do this with with plain JavaScript using Event Bubbling, querySelector and the element classList attribute like this.
Change your HTML to look like this:
<div class="posts">
<div class="posted">
<button class="dn">Reply</button>
</div>
<div class="posted" >
<button class="dn">Reply</button>
</div>
<div class="posted" >
<button class="dn">Reply</button>
</div>
</div>
Then use JavaScript like this:
var posts = document.querySelector('.posts');
var allPosted = document.querySelectorAll('.posted');
//clicks bubble up into the posts DIV
posts.addEventListener('click', function(evt){
var divClickedIn = evt.target;
//hide all the buttons
allPosted.forEach(function(posted){
var postedBtn = posted.querySelector('button');
postedBtn.classList.remove('db');
});
// show the button in the clicked DIV
divClickedIn.querySelector('button').classList.add('db')
});
You can find a working example here: http://output.jsbin.com/saroyit
Here is very simple example using jQuery .siblings method:
$(function () {
$('.posted').click(function () {
$('button', this).show();
$(this).siblings().find('button').hide();
});
});
https://jsfiddle.net/3tg6o1q7/
Here is the important part of the code that executes.
Im trying to click on one element with a particular ID that relates to bookmarking the message but the element keeps triggering another click event that hides every div with the class 'messageCase' while at the same time attaching class messageOpen2 to the bookmark images ID which is very odd
the 'hidden' classes just hide all other message instances that contain
The messageCase class.
var openMessageAnimationStrategy = function () {
var openMessage = $(document).ready(function () {
var divTarget = $("div.messageCase");
$(divTarget).click(function (e) {
var target = $(e.target);
target.toggleClass('messageOpen2');
divTarget.addClass('hidden');
target.removeClass('hidden');
});
});
};
Here is what the HTML looks like
<div class="messageCase">
<div class="messageImageBox">
<div id="messageImage">
</div>
</div>
<div id="subjectLine">
Subject Line Text
</div>
<div id="bookMarkImage">
<img id="bookmarkStatus" class="savedMessage" src="notbookMarked64.png" />
</div>
<div class="activeBookmarks">
{38} <br />
Bookmarks <br />
<br />
9:53am
</div>
<div id="bodyPreview">
Body Preview Text is light
</div>
</div>
Every Time I use the Click event on bookmarkStatus to change the src of the image it causes the first click event to execute making everything disappear & the class messageOpen2 to be added to bookmarkStatus. I can include the CSS if necessary but ill list the code for the bookmarking function below
var bookmarkedStrategy = function () {
var bookmarkedStrategy = $(document).ready(function () {
var bookmarkStatus = $("#bookmarkStatus");
var divTarget = $('messageCase');
//below trying to remove the Class that was attached by the initial function while also changing the image SRC for the class bookmark
$(divTarget).click(function (e) {
var target = $(e.target);
divTarget.removeClass('messageCase2');
bookmarkStatus.toggleClass('savedMessage');
});
});
};
I Think the main problem has to do with the initial function but I don't know what else could be wrong any ideas?
edit Here is the CSS that matters.
.savedMessage {
background-image: url("bookmarked64.png");
}
.messageOpen2 {
height: 250px;
}
.messageCase {
margin: 5px;
border-radius: 5px;
background-color: aliceblue;
height: 70px;
}
#bookMarkImage {
float:right;
height:64px;
width:64px;
z-index:9999;
}
.hidden {
display:none;
max-height: inherit;
}
.activeBookmarks {
float: right;
text-align: center;
font-size: 13px;
font-weight: 700;
text-decoration: solid;
}
Calling code
var bookmarkedthings = new MessageHandling(bookmarkedStrategy);
bookmarkedthings.greet();
var openMessage = new MessageHandling(openMessageAnimationStrategy);
openMessage.greet();
There is a missing . in your bookmarkedStrategy function code var divTarget = $('.messageCase'); Add dot and try again
I'm playing around with building a basic modal window and i want it do dissapear when i click the edges. So my problem in it's most basic form:
<div style="width:100%;height:100%;" onclick="hideAll()">
Hide all onclick.
<div style="width:100px;height:100px;">
does not hide all onclick
</div>
</div>
What is the best way to achieve this? To use unnested divs? html/css magic?
HTML:
<div style="width:100%;height:100%;" class="outerModal">
Hide all onclick.
<div style="width:100px;height:100px;">
does not hide all onclick
</div>
</div>
JavaScript:
$(document).on("click", ".outerModal", function(evt) { //listen for clicks
var target = $(evt.target ||evt.srcElement); //get the element that was clicked on
if (target.is(".outerModal")) { //make sure it was not a child that was clicked.
//hide dialog
}
});
Example:
JSFiddle
When you hide the parent tag, it automatically hides the childen tag as well, You should first contain the child div into variable and after that hide the parent div and append that stored child div into parent tag something like this.
HTML
<div id="result">
<div style="width:100%;height:100%;" id="parentDiv" onclick="hideAll()">
Hide all onclick.
<div style="width:100px;height:100px;" id="childDiv">
does not hide all onclick
</div>
</div>
</div>
javaScript
function hideAll(){
var childDiv = document.getElementById('childDiv'); //contain child div
var parDiv = document.getElementById('parentDiv');
parDiv.style.display = 'none'; //hide parent div
parDiv.parentNode.appendChild(childDiv); //append child div
}
DEMO
Assuming that "parentDiv" is to be the background and "childDiv" is to be the actual modal content, the best way I have found is to separate the divs entirely.
HTML
<div id="parentDiv" onclick="hideAll()"> </div>
<div id="childDiv" >
does not hide all onclick
</div>
Javascript using jQuery
function hideAll(){
/* The Parent Div will hide everything when clicked, but the child won't */
$('#childDiv').fadeOut(1000, function(){
$('#parentDiv').fadeOut(1000);
});
}
CSS
#parentDiv {
background: black;
display: block;
position: fixed;
top: 0;
left: 0;
z-index: 100;
height: 100%;
width: 100%;
}
#childDiv {
display: block;
position: relative;
background: white;
height: 200px;
width: 200px;
z-index: 101
}
Here is a working example.
Hope this helps at all.
See this fiddle:
http://jsfiddle.net/eZp9D/
$(document).ready(function () {
$('#parentDiv').click(function (e) {
if ($(e.target).prop('id') == "parentDiv") {
$(this).hide();
}
});
});
You can use basic jQuery and style it accordingly with CSS.
Check this example.
If you want to have it disappear by clicking outside of the dialog window, make sure that onClick you perform this action:
$( "#dialog_id" ).dialog( "close" );