Identify different buttons that have the same "onmouseover" function - javascript

I am trying to identify different buttons that have the same ID with different positions. I am trying to display a window next to the correct button, but so far it is only working with the first button, and when I try to add another button with the same ID as it should use the same function logic, it displays the div element next to the first button.
I was thinking maybe each button should have its own identifier and the function uses the code from identify different buttons that have the same "onclick" function name to search through the list of existing buttons and run the function at that button, however, I do not know how to do this. Here is my code as to what I have tried.
function displayInfo(){
var coords = friend_button.getBoundingClientRect();
var coordsOfInfo = $('.backgroundInfo').width();
var subtractWidth = coords.left-coordsOfInfo;
friend_info.style.left = subtractWidth+"px";
friend_info.style.top = coords.top + "px";
friend_info.style.display = "block";
friend_button.addEventListener("mouseout", function(){
friend_info.style.display = "none";
});
};
<button type="button" class="friend-button" id="friend-button" onmouseover=displayInfo()>
<div class="media">
<img src="default-pic.png" class="mr-3" alt="Default Picture" width="50" height="50">
</div>
<div class="media-body">
<h5 class="mt-0">Friend1</h5>
<p>status: active</p>
</div>
</button>
<div class="friend_info" id="friend_info">
<video autoplay muted loop class="backgroundInfo" id="backgroundInfo">
<source src="Background.mp4" type="video/mp4">
</video>
<div class="d-flex">
<img src="default-pic.png" class="profile-picture" alt="Default Picture" width="200" height="200">
<div class="d-flex flex-column">
<div class="p-2">
<h1 class="Friend_Name">Friend1</h1>
</div>
<div class="p-1">
<h5>status: active</h5>
</div>
<div class="p-9">
<p class="info">Name: Joesdadsadsadsadsa</p>
<p class="info">Surname: Smithdsadsadsadsadsa</p>
<p class="info">Phone Number: 07914836605</p>
<p class="info">Gender: Male</p>
<p class="info">Date of birth: 14/02/2003</p>
</div>
</div>
</div>
</div>

You should never have the same id for more than an element. Its meaning is Unique Identifier. By the way solution is to pass a parameter (the friend Id, or the name, an unique Id btw) from the hovering button.
onmouseover=displayInfo(frendId)
_
function displayInfo(frendId){ // do stuff

If I understand you correctly (there is a chance I don't)
you need to pass event into a callback. This way you click the button and the correct info related to the specific (clicked) button will be passed.
<button type="button" class="friend-button"
id="friend-button"
onmouseover= "() => displayInfo(e)">
function displayInfo(event){
let btn = event.target;
var coords = btn.getBoundingClientRect();
As previously it was mentioned ID is unique, you should not use the same ID for different elements. Also. try not to use var, use either let to const.

Related

How do I get the value of the first child element in Javascript?

I'm trying to get the value of the first child element from my HTML to show whenever I click on an image aka my 'services-cell" container, but it keeps saying the value is undefined.
<div class="services-cell">
<img class="services-cell_img" src="gallery/img-1.jpg" alt="">
<div class="services-cell_text">Digital Marketing</div>
</div>
Here is my Javascript
let galleryImages = document.querySelectorAll('.services-cell')
if(galleryImages) {
galleryImages.forEach(function(image){
image.onclick = function() {
console.log(galleryImages.firstElementChild.value)
}
})
}
I tried to add the img class as a variable as well, but it also says undefined. I want the console.log to print
<img class="services-cell_img" src="gallery/img-1.jpg" alt="">
I have multiple images with the same html except it just say img-2, img-3 etc. So ideally whenever I click on the other images it would print the same HTML value but just will say the image number that I clicked on
You created the array as galleryImages, but then rather than accessing the firstElementChild of the div, you're trying to access that property on the array. You need to do image.firstElementChild instead. Also, as far as I know, accessing .value of an image has no meaning, I think you meant to just do firstElementChild instead:
let galleryImages = document.querySelectorAll('.services-cell');
if (galleryImages) {
galleryImages.forEach(function (image) {
image.onclick = function() {
console.log(image.firstElementChild);
};
});
}
<div class="services-cell">
<img class="services-cell_img" src="https://s3.amazonaws.com/pix.iemoji.com/images/emoji/apple/ios-12/256/deciduous-tree.png" alt="">
<div class="services-cell_text">Digital Marketing</div>
</div>
<div class="services-cell">
<img class="services-cell_img" src="https://cdn-cloudfront.cfauthx.com/binaries/content/gallery/gg-en-us/icons/gg-tree-icon.png" alt="">
<div class="services-cell_text">Digital Marketing</div>
</div>
What you could do to achieve this is passing the event attribute as a parameter of the onclick function.
The event attribute has a target; which is the item that triggered the event. So for example:
if(galleryImages) {
galleryImages.forEach(function(image){
image.onclick = function(e) {
console.log(e.target.firstElementChild.value)
}
})
}
However instead of adding an eventListener to every element, it might be better to add one event handler on the parent - and check which item is clicked.
E.g.
<div class="parent">
<div class="services-cell">
<img class="services-cell_img" src="gallery/img-1.jpg" alt="" />
<div class="services-cell_text">Digital Marketing</div>
</div>
<div class="services-cell">
<img class="services-cell_img" src="gallery/img-2.jpg" alt="" />
<div class="services-cell_text">Digital Marketing</div>
</div>
</div>
And the javascript:
document.querySelector('.parent').addEventListener('click', function(e){
if(e.target.matches('.services-cell'){
// Do something with the e.target - which is the .services.cell
}
}

How to use a play/pause button for multiple html5 videos in javascript?

I'm currently working on a website that has a series of twelve HTML5 videos that starts playing automatically in a separate modal box for each video. Now I want to give the user the control to play and pause the video as well (along with other features but that's not relevant to my current problem).
I've gotten so far that the user are able to click the video itself in order to play and pause it. But the play/pause button i've added does not work right now and the code below will give me a "lastClicked.pause is not a function" error.
I know that the reason is because the lastClicked variable i'm using as a condition inside the if statement will contain a button when I click "play/pause" and a button does not have those functions. I've figured out that much so far, but I'm a bit lost of what my next step should be.
Should I make a reference to the specific video inside the toggleVideo function and replace it with the lastClicked variable or does a more simple solution exist?
EDIT: Added a bit of the HTML for reference
Javascript:
// VIDEO CONTROLS
const portfolio = document.querySelector(".portfolio");
const player = portfolio.querySelectorAll(".viewer");
const toggle = portfolio.querySelectorAll(".toggle");
let lastClicked
function toggleVideo () {
lastClicked = this;
if(lastClicked.paused) {
lastClicked.play();
}
else {
lastClicked.pause();
}
}
// Two different ways to play/pause the video - Clicking the video
// itself and clicking the play/pause button
player.forEach(video => video.addEventListener ("click", toggleVideo ));
toggle.forEach(button => button.addEventListener ("click", toggleVideo ));
HTML:
<section class="portfolio" id="portfolio">
<div class="video-wrapper">
<div class="video-thumbnail"><img src="./media/img/thumbnails/1.hammerfall.jpg"></div>
<button class="video-overlay" id="player" data-modal="videoOne"></button>
</div
><div class="modal-box">
<div class="modal-content">
<span class="close-btn">×</span>
<div class="player">
<video class="player__video viewer" src="./media/video/1.waves.mp4"></video>
<div class="video-controller">
<div class="progress-bar">
<div class="progress-filled"></div>
</div>
<button class="video-play toggle">►</button>
<input type="range" name="volume" class="player-slider" min=0 max=1 step="0,05" value="1">
<button class="video-volume mute">X</button>
</div>
</div>
</div>
</div
><div class="video-wrapper">
<div class="video-thumbnail"><img src="./media/img/thumbnails/2.lordi.jpg"></div>
<button class="video-overlay" data-modal="videoTwo"></button>
</div
><div class="modal-box">
<div class="modal-content">
<span class="close-btn">×</span>
<div class="player">
<video class="player__video viewer" src="./media/video/2.words.mp4"></video>
<div class="video-controller">
<div class="progress-bar">
<div class="progress-filled"></div>
</div>
<button class="video-play toggle">►</button>
<input type="range" name="volume" class="player-slider" min=0 max=1 step="0,05" value="1">
<button class="video-volume mute">X</button>
</div>
</div>
</div>
</div
>
</section>
Essentially you need to associate your buttons with your videos.
Currently toggleVideo() assumes that it's running in the context of a video element, whereas it could be a video or a button associated with a video.
You don't know show your HTML structure, but for this answer I'll use the following video-button relationship.
<div>
<video />
<button>Toggle</button>
</div>
...ergo in my contrived example, the button is the next sibling of the video. It doesn't matter what the precise relationship is between video and button, merely that we establish and cater for it inside toggleVideo().
So, that now becomes:
function toggleVideo () {
//establish video - might be #this, or might be prev sibling of #this
let vid = this.tagName == 'VIDEO' ? this : this.previousSibling;
lastClicked = vid;
vid.paused ? vid.play() : vid.pause();
}

Add href link to Image that has been displayed via js click

Similar to a question I asked recently but the previous was using mouse over so was rubbish for touch screen.
This is 3 divs with images. on click they individually change to a second image and reset the other 2 to a standard image. this all works ok.
But when the second image in any of the divs is active i would like to be able to click this image and navigate to a different page.
Clearly adding href to the html just navigates and ignores the JS effect.
Thanks for reading.
$(document).ready(function(){
$('#s1').click(function(){
$('#s1').attr('src', 'images/object/click-1.png');
$('#s2').attr('src', 'images/object/standard-2.jpg');
$('#s3').attr('src', 'images/object/standard-3.jpg');
});
$('#s2').click(function(){
$('#s1').attr('src', 'images/object/standard-1.jpg');
$('#s2').attr('src', 'images/object/click-2.png');
$('#s3').attr('src', 'images/object/standard-3.jpg');
});
$('#s3').click(function(){
$('#s1').attr('src', 'images/object/standard-1.jpg');
$('#s2').attr('src', 'images/object/standard-2.jpg');
$('#s3').attr('src', 'images/object/click-3.png');
});
});
<div id="section3" class="container-fluid" align="center">
<div class="row row-centered ">
<div id="top-box-1" class="col-sm-4">
<img src="images/object/standard-1.jpg" class="std" id="s1" width="300" height="300"/>
</div>
<div id="top-box-2" class="col-sm-4">
<img src="images/object/standard-2.jpg" class="std "id="s2" width="300" height="300"/>
</div>
<div id="top-box-3" class="col-sm-4">
<img src="images/object/standard-3.jpg" class="std" id="s3" width="300" height="300"/>
</div>
</div>
</div>
You can see if the src now contains 'click'. if not then swap the src and return false to stop the href:-
$('#s1').click(function(e) {
if (!$(this).is('[src*="click"]')) {
$('#s1').attr('src', 'images/object/click-1.png');
$('#s2').attr('src', 'images/object/standard-2.jpg');
$('#s3').attr('src', 'images/object/standard-3.jpg');
return false;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="section3" class="container-fluid" align="center">
<div class="row row-centered ">
<div id="top-box-1" class="col-sm-4">
<a href="http://stackoverflow.com/">
<img src="images/object/standard-1.jpg" class="std" id="s1" width="300" height="300" />
</a>
</div>
<div id="top-box-2" class="col-sm-4">
<a href="http://stackoverflow.com/">
<img src="images/object/standard-2.jpg" class="std " id="s2" width="300" height="300" />
</a>
</div>
<div id="top-box-3" class="col-sm-4">
<a href="http://stackoverflow.com/">
<img src="images/object/standard-3.jpg" class="std" id="s3" width="300" height="300" />
</a>
</div>
</div>
</div>
To break this down: if (!$(this).is('[src*="click"]')) {
$(this).is allows you to check this against a selector, returning a boolean (true) if it does.
'[src*="click"]' is the selector to determine if the src attribute contains 'click'. Where the * means contains anywhere. There are other combinations like ^= for starts with.
Therefore $(this).is('[src*="click"]') means true if the src has 'click'. But you need to invert this to not contains. That's what the ! is for, meaning if this (the clicked element) has not got 'click' in the src.
Since you're already handling the click event, you'll likely want to perform this logic in that same event. Something structurally like this:
if (/* some condition */) {
window.location.href = someUrl;
}
I guess you'd need to define what that condition is. Would it be based on the current src of the image? Something like this?:
if ($(this).attr('src') === 'images/object/click-1.png') {
window.location.href = someUrl;
}
(You'd also have to define what someUrl is, of course.)

Toggle between multiple divs

I have an issue. I want to toggle between many divs, while one shows the rest hide.
This is what I have so far.
Thanks in advance!
<a href="#n" onclick="toggle_visibility('box1');">
<div class="square img_1-1"></div>
</a>
<a href="#n" onclick="toggle_visibility('box2');">
<div class="square img_1-2"></div>
</a>
<a href="#n" onclick="toggle_visibility('box3');">
<div class="square img_1-3"></div>
</a>
<div id="box1" style='display:none;'>
<div class="trabajo">
<p>box1</p>
</div>
</div>
<div id="box2" style='display:none;'>
<div class="trabajo">
<p>box2</p>
</div>
</div>
<div id="box3" style='display:none;'>
<div class="trabajo">
<p>box3</p>
</div>
</div>
<a href="#n" onclick="toggle_visibility('box4');">
<div class="square img_2-1"></div>
</a>
<a href="#n" onclick="toggle_visibility('box5');">
<div class="square img_2-2"></div>
</a>
<a href="#n" onclick="toggle_visibility('box6');">
<div class="square img_2-3"></div>
</a>
<div id="box4" style='display:none;'>
<div class="trabajo">
<p>box4</p>
</div>
</div>
<div id="box5" style='display:none;'>
<div class="trabajo">
<p>box5</p>
</div>
</div>
<div id="box6" style='display:none;'>
<div class="trabajo">
<p>box6</p>
</div>
</div>
Also, here is the Javascript. I'm using toggle_visibility(id) The problem is that it start to get weird when I hide one box and open another it opens both then it just gets weird. It leaves both open then closes one.
var prevId;
function toggle_visibility(id) {
if(prevId && id !== prevId){
$("#"+prevId).toggle();
}
var e = document.getElementById(id);
$(e).toggle();
prevId = id;
}
There's also another javascript code I tried before, this one works sorta fine, the only thing it doesn't do is toggle it just shows the work and doesn't hide it, although it does toggle between different work.
top.visible_div_id = 'box1';
function toggle_visibility(id) {
var old_e = document.getElementById(top.visible_div_id);
var new_e = document.getElementById(id);
if(old_e) {
console.log('old', old_e, 'none');
old_e.style.display = 'none';
}
console.log('new', new_e, 'block');
new_e.style.display = 'block';
top.visible_div_id = id;
}
Instead of the onclick, I used the eventhandler on() (you should not inline-javascript). I coombine this with the data-attribute:
<a data-toggles="#box2">box 2</a>
And some changes to your javascript:
$('a.triggeringAnchor').on('click', function(e){
e.preventDefault() // stop the anchor
$('a.triggeringAnchor').hide(); // hide them all
$( $(this).data('toggles') ).show(); // bring the one back in the one back
})
You could use the :not() selectors, but this is a bit more obvious :)
The trick here is the 'bring back' line. I use the value of the data-attribute as selector for the actual element we want back.
This code has a big advantage over yours. If you add 1 more element, your counter would be to know about this (could be done via .length()), my code doesn't care. Everything gets hidden, and just that 1 will come back.
I think this jQuery Widget is exactly what you are looking for. Easy to implement and very usable. Plus, the jQuery API instructions make it a breeze to get onto your page.

Getting the Id attribute from an Image in a div

I have a div that contains 1 to many images with next and previous image buttons. When a user clicks the next/previous button the current image style is changed from display:block to display:none using jquery. I need to get the ID attribute from the current image that is showing ie. has the display:block style applied.
<div id="propPhotos" name="propPhotos">
<div id="propPhotsDivList">
<div id="imageNameId0" style="display:block">
<img src="/PropertyImages/1/171fc210b4584f41936a078c4176c7e0.jpg" height="200" width="200" id="3"/>
</div>
<div id="imageNameId1" style="display:none">
<img src="/PropertyImages/1/114810f0067749eda8049d2f8269dd00.jpg" height="200" width="200" id="4"/>
</div>
<div id="imageNameId2" style="display:none">
<img src="/PropertyImages/1/8.jpg" height="200" width="200" id="15"/>
</div>
<div id="imageNameId3" style="display:none">
<img src="/PropertyImages/1/e8f182ab645549b399cebc67ed996d151.jpg" height="200" width="200" id="25"/>
</div>
</div>
<div>
<div class="row">
<input type="button" id="NextImage" value="Next Image" onclick="ImageNext()" /><input type="button" id="PrevImage" value="Previous Image" onclick=" ImagePrev()" />
</div>
<div class="row">
<button type="button" class="AddImage">Add Image</button><button type="button" class="RemoveImage">Remove This Image</button>
</div>
</div>
This is the path I am currently on which is in the next and previous image click handlers.
CurrentImageId = document.getElementById("imageNameId" + id).children('img').attr('id');
So when the user clicks either button its supposed to assign the id value to the CurrentImageId. This does not work for one and does not help on the initial load when neither next or previous image buttons have been clicked.
Well, there are a few different ways as far as the initial load is concerned. Here are a couple of examples:
Using the :visible selector:
var currentImageId = $('#propPhotsDivList > div:visible > img').prop('id');
Or perhaps combined with filter():
var currentImageId = $('#propPhotsDivList img').filter(function(){
return $(this).parent('div').is(':visible');
}).prop('id');
If the divs are hidden and shown correclty using your click handlers, you can use the same functionality inside them as well.
$('#propPhotsDivList').children('div:not(:hidden)').attr('id');

Categories