Change background-image on hover, but also on click with jQuery - javascript

The background image is an image of an office. The background image will have a few <a> tags where the person can click. For example: there is an <a> tag on a computer that's on the desk. Taking this example, I want to do the following:
Hovering on the <a> tag that is over the computer, will load in a picture of the same office, however, the computer has been outlined with a white line in photoshop (Lets say: img/bureau2). Indicating that it is interactable. Hovering away from this will return it to the original picture which you see when you enter site (img/bureau1)
You can also click on the <a> tag. This will open up another image (img/bureau3).
So far I managed to get the change on hover and click to work. Issue is, hovering away from the <a> tag will cancle the click.
This is what I have so far, how can I tackle this issue?
$(".computerHover").hover(function() {
$("#backgroundImage").attr('src', 'img/bureau2.png');
},
function() {
$("#backgroundImage").attr('src', 'img/bureau.png');
});
$(".computerHover").click(function() {
$("#backgroundImage").attr('src', 'img/bureau3.png');
});
#pagina2 {
width: 100%;
height: 100%;
}
#backgroundImage {
height: 100vh;
width: 100vw;
z-index: 0;
display: block;
}
.computerHover {
width: 105px;
height: 75px;
position: absolute;
right: 28vw;
top: 40vh;
z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="pagina2">
<div id="pagina2Background">
<img id="backgroundImage" src="img/bureau.png">
<div class="computer">
<a class="computerHover"></a>
</div>
</div>
</div>

Seems to me, what you are trying to do, is an image map. But for the sake of your question, I will focus on one particular link.
The reason the click generated image disappears when you move the mouse, is because it is still bound to the previous hover event. The hover method is a shortcut for mouseenter and mouseleave. In order to circumvent that, you need to unbind that event handler.
EDIT:
I reworked my answer to more closely resemble the code in your question. In order to "reset" the image, I would suggest using a link that the user can click to make it less confusing for them.
function switchImage() {
$(".computerHover").hover(function() {
$("#backgroundImage").attr('src', 'http://via.placeholder.com/300x300.png?text=Computer');
},
function() {
$("#backgroundImage").attr('src', 'http://via.placeholder.com/300x300.png?text=Office');
});
}
// attach the hover events when page loads
switchImage();
$(".computerHover").on("click", function() {
$(this).off("mouseenter mouseleave");
$("#backgroundImage").attr('src', 'http://via.placeholder.com/300x300.png?text=New Background');
});
// reattach hover handlers and set image back to default
$(".reset").on("click", function() {
switchImage();
$("#backgroundImage").attr('src', 'http://via.placeholder.com/300x300.png?text=Office');
});
#pagina2 {
width: 100%;
height: 100%;
}
#backgroundImage {
height: 100vh;
width: 100vw;
z-index: 0;
display: block;
}
.computerHover {
width: 105px;
height: 75px;
position: absolute;
right: 28vw;
top: 40vh;
z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="pagina2">
<div id="pagina2Background">
<a class="reset">Start Over</a>
<img id="backgroundImage" src="http://via.placeholder.com/300x300.png?text=Office">
<div class="computer">
<a class="computerHover">Computer</a>
</div>
</div>
</div>

To do what you want you'll need to keep some sort of state that indicates that the user clicked instead of just hover. In the click handler you could add a class or data-* to #backgroundImage element that you later check when you un-hover.
Example codesanbox.

Related

onClick iframe redirect to the src url

I am trying to make a scenario where if someone clicks on the iframe, so it will open a new window to check the same URL on the web browser tab. But the scroll and other mouse events on the iframe will not affect it.
I tried different approaches but nothing worked
Approach 1: Tried to get the onClick event of the iframe itself, but the issue is of cross-origin persist
Approach 2: Tried to provide the onClick event to the parent element of iframe, but as pointer-events of the iframe are enabled it won't let the parent onClick to work.
Approach 3: Tried to make an overlay of anchor tag, above the iframe. It did work but it stops the iframe scroll.
Here is my code:
<div>
<iframe src="https://fr.wikipedia.org/wiki/Main_Page"></iframe>
</div>
iframe {
width: 100%;
height: 100vh;
pointer-events: none;
}
a {
width: 100%;
height: 100vh;
position: absolute;
top: 0;
left: 0;
}
Fiddle: here
Is it possible to achieve this scenario with the cross-origin URL?
Your code does not work because you have pointer-events: none; set to it. You can do like this that you click the "button overlay" and redirect the user with javascript, once it is clicked it "removes" the button overlay.
In my case I have set the background to be red just to make it clear, and I don't remove the button I just hide it. You can adjust to your use case. Also note that this script only allows for one of this iframes and buttons. If you have more the script have to be modified to loop through and add eventListeners to button and to look at its parent to add the class on the container (or if you just remove the button)
const redirectAction = document.querySelector('.js-open-url')
redirectAction.addEventListener('click', function() {
window.open(
redirectAction.dataset.href,
'_blank'
)
document.querySelector('.container').classList.add('container--is-open')
})
.container {
position: relative;
}
iframe {
width: 100%;
height: 100vh;
}
.button {
width: 100%;
height: 100vh;
position: absolute;
top: 0;
left: 0;
z-index: 1;
background-color: red;
}
.container--is-open .button {
display: none;
}
<div class="container">
<iframe src="https://fr.wikipedia.org/wiki/Main_Page"></iframe>
<button class="button js-open-url" data-href="https://fr.wikipedia.org/wiki/Main_Page"></button>
</div>

How to do image fading with position relative?

I am trying to integrate the code from here to change image of my slide show on click (credit to cssyphus):
$(function() {
$("input:button").click(function() {
$("img:last").fadeToggle("slow", function() {
$(this).prependTo(".frame").fadeIn()
});
});
});
function Forward() {
$("img:first").fadeToggle("slow", function() {
$(this).appendTo(".frame").fadeIn(800)
});
}
function Backward() {
$("img:last").fadeToggle("slow", function() {
$(this).prependTo(".frame").fadeIn()
});
}
.frame {
position: relative;
left: 35%;
}
img {
position: absolute;
max-width: 30%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<h1>
<input type="button" value="PrependTo" />
<button onclick="Forward()">Go Forward</button>
<button onclick="Backward()">Go Backward</button>
</h1>
<div class="frame">
<img src="http://placeimg.com/240/180/animals">
<img src="http://placeimg.com/240/180/nature">
<img src="http://placeimg.com/240/180/people">
<img src="http://placeimg.com/240/180/sepia">
</div>
The issue arise due to the effect depending position:absolute to stack the images on top of one another. Switching it to position:relative unstack the images and they are next to one another. Using position:absolute throws off all other elements in the code to integrate into. How can I remedy this problem?
It's a little difficult to imagine how the layout is affected by the slideshow, but from looking at your code I would try one of two things:
Remove the left: 35%; css from the .frame - I'm unsure why this is there but it will push the whole frame container of the slideshow over
.frame {
position: relative;
}
Adjust the CSS for the img so it only affects the nth-children after the first one, so they will be stacked on top of one another while the first one is inherit/relative:
img {
position: relative;
}
img:nth-child(n+2) {
position: absolute;
top: 0;
left: 0;
}

preventDefault() on first touch but still allow scrolling/touchmove

I have a few elements on my site in which there is content that only appears when you hover on the element. A perfect example would be the Instagram feed grid. I'm pulling in the last 8 images from an Instagram account using their API and displaying them in a grid with flexbox. When you :hover over one of the images with a mouse, a semi-transparent black overlay fades in, containing the caption of the Instagram post.
On desktop you are able to click anywhere on the image/hovered caption overlay as they are both wrapped in an <a> element and doing so takes you to the post on Instagram's website. This works perfectly on desktop, but on touch devices does not.
Because you can't :hover on touch devices, I decided to implement some javascript on the touchstart event that uses e.preventDefault() to stop the link from being clicked when you tap the Instagram image and instead adds the CSS opacity: 1 and visibility: visible to the overlay element (which is what happens when you :hover on the element). Because the overlay element is then "on top" of the image when it's made visible, the link is clickable because the touchstart event is only listened for on the image.
This all works great and means that I can tap once on the image which fades in the overlay and doesn't take me to the image on Instagram, and I can then click for the second time on the overlay, taking me to the image on Instagram.
The problem
Because I am using e.preventDefault() in the touchstart event, if you touch the image and then start dragging your finger to scroll, the page doesn't scroll at all which results in a bad user experience.
So...
How can I only preventDefault() on a single touch event, or how can I prevent the link from being clicked on the first touch of the element but not on the second whilst still allowing the user to scroll/drag the page?
Slightly simplified version of my code
function toggleHoveredStateOn(e) {
e.preventDefault();
let hoverElem = this.querySelector('.js-touch-hover');
// remove all 'visible' classes from other "hovered" items first
document.querySelectorAll('.js-touch-trigger').forEach(touchTrigger => {
let hoverElem = touchTrigger.querySelector('.js-touch-hover');
Object.assign(hoverElem.style, {
visibility: 'hidden',
opacity: '0',
pointerEvents: 'none'
});
});
// add visible to the touched element's hover element
Object.assign(hoverElem.style, {
visibility: 'visible',
opacity: '1',
pointerEvents: 'all'
});
}
function initMobileTouchFunctionality() {
let touchTriggers = [...document.querySelectorAll('.js-touch-trigger')];
touchTriggers.forEach(touchTrigger => {
touchTrigger.addEventListener('touchstart', toggleHoveredStateOn, false);
touchTrigger.querySelector('.js-touch-hover').addEventListener('touchstart', function(e) {
e.stopPropagation();
}, false);
});
}
initMobileTouchFunctionality();
.flex-grid__item {
position: relative;
height: 263px;
border: 1px solid #FFF;
&:hover {
.flex-grid--social__hover {
opacity: 1;
visibility: visible;
pointer-events: auto;
}
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.flex-grid--social__hover {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
background-color: rgba(0, 0, 0, 0.8);
padding: 20px;
transition: opacity 0.2s ease-in-out;
opacity: 0;
visibility: hidden;
overflow: hidden;
pointer-events: none;
cursor: pointer;
}
<div class="flex-grid__item js-touch-trigger">
<a href="<?php // link to instagram. php code gets this ?>">
<img class="" src="<?php // instagram image. php code gets this ?>"/>
<div class="flex-grid--social__hover js-touch-hover">
<p><?php // instagram caption. php gets this ?></p>
</div>
</a>
</div>
You can decide whether to e.preventDefault or not using the e.target to see if the user tapped the image or the overlay.
You can read more at https://developer.mozilla.org/en-US/docs/Web/API/Event/target

How to activate jQuery function with img instead of button?

I'm currently coding a website using HTML, CSS and JS. I have used a code found on here to make two images on top of each other fade out to expose the other image on the click of a button (creating the effect of a changing img).
However, I don't want there to be an ugly <input type="button"> on the page to activate the fade, instead, I would like to be able to click an image for the toggle function to be called. How would I go about changing the element that activates the function?
JS code:
$(function(){
$("input:button").click(function(){
$(".logo").fadeToggle("fast");
});
});
HTML:
<input type="button" value="Go Kitty Go"/>
CSS:
#logo1 {
position:absolute;
top:9px;
left: 46%;
height: 29px;
width: 89px;
}
#logo2 {
display:none;
position:absolute;
top: 8.5px;
left: 48.2%;
height: 28px;
width: 60px;
}
input {
position:absolute;
top: 220px;
}
I would like to swap the button with an img to activate the fadeToggle() function.
You havn't posted your full html so I don't know what your img tags look like. But assuming you have given them an id (id="someId"), do this:
$("#someId").click(function(){
$(".logo").fadeToggle("fast");
}); `});`
The only change here is that instead of listening for the click on your button, your code is now listening for the click on your img

JQuery - show hide button when mouse enter / leave an image

In my web page I have an image that has a button positioned over it. I want to show and hide the button as mouse enter and leave the image:
$('#UserImage').mouseenter(function()
{
$('#ButtonChange').show();
}).mouseout(function()
{
$('#ButtonChange').hide();
})
It is working but as the button is contained inside the image when the mouse enters the button it is considered to leave the image so the button is hidden then at tha same moment as the button is hidden the mouseenter event is triggered again and the button is shown causing a flickering effect
any suggestion to solve this?
Edit:
$('#UserImage').mouseenter(function() {
$('#ButtonChange').show();
}).mouseout(function() {
$('#ButtonChange').hide();
})
.imageUser {
width: 150px;
height: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div style="position:relative;width=150px">
<img ID="UserImage" class="imageUser" ImageUrl="~/Images/logo.jpg" />
<input type="button" ID="ButtonChange" Text="Change" style="position: absolute;top: 180px;height:25px;left:0px;width:100px;display:none">
</div>
The whole thing is also possible with pure CSS ! for such simple thing, you don't really need Jquery !
.imageUser {
width: 150px;
height: 200px;
}
.img-wrapper {
position: relative;
width: 150px
}
.img-btn {
position: absolute;
top: 180px;
height: 25px;
left: 0px;
right:0; /* gave right, to align the button in center */
margin:0 auto; /* as button as fixed width, margin aligns in center */
width: 100px;
display: none
}
.img-wrapper:hover .img-btn {display:block} /* whenever mouse hovers the image wrapper, the button is shown, other time, its hidden */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="img-wrapper">
<img ID="UserImage" class="imageUser" ImageUrl="~/Images/logo.jpg" />
<input type="button" ID="ButtonChange" Text="Change" class="img-btn">
</div>
Try hover?
$("#UserImage").hover(function () {
$('#ButtonChange').show();
}, function () {
$('#ButtonChange').hide();
});
I don't have an image so I make a div instead. See Fiddle below.
Fiddle: https://jsfiddle.net/9koswww1/1
Change mouseenter to mouseover.
https://api.jquery.com/mouseenter/
Check the bottom of the page for an example.
try this
$('#UserImage').mouseenter(function()
{
$('#ButtonChange').show();
}).mouseleave(function()
{
$('#ButtonChange').hide();
})

Categories

Resources