EDIT: You can see my code working here: unf.edu/~n00804716/site/work.html
I am attempting to blur a section with jQuery when I open an iframe. The iframe is initially hidden, but appears as a fixed element above everything when a button is clicked. I have found one way to do this, but it requires an excessive amount of code. So, I tried to cut down a little, but can't get it to work. Here is what I have:
$('#slides iframe').hide();
$("span").click(function() {
$("#slides iframe").fadeIn(300);
});
$('#slides iframe').each(function(){
if ( $(this).css('display') == 'block')
{
$("section").css({
'filter': 'blur(15px) greyscale(80%)'
});
} else {
$("section").css({
'filter': 'blur(0px) greyscale(0%)'
});
}
});
This is how my HTML is setup:
<div id="slides">
<div id="slide-2" class="slide">
<iframe class="zoo-video"></iframe>
<section>
<span></span>
/*other content*/
</section>
</div>
</div>
CSS:
#slides iframe {
width: 90%;
margin: 0 auto;
height: 90%;
z-index: 9999;
position: absolute;
right: 0;
left: 0;
top: 5%;
bottom: 0;
}
#slides,
section {
width: 100%;
}
Also, I'm not entirely sure if the vendor prefixes are necessary. Is there a much simpler way to do this? The trick is, the iframe is a vimeo player that takes up 90% of the screen. So, I also need the iframe to close/collapse when the page is scrolled vertically or if the user clicks outside of the iframe. When it collapses, I need it the section to no longer have a blur or grayscale. Here is the code I'm using to collapse the iframe when the user clicks outside of it:
$(document).mouseup(function (e) {
var container = $("#slides iframe");
if (!container.is(e.target)
&& container.has(e.target).length === 0)
{
container.fadeOut(230);
}
});
http://jsfiddle.net/721nma0g/
$(document).ready(function () {
var video = $("#slides iframe");
$(document).mouseup(function (e) {
if (!video.is(e.target) && !video.has(e.target).length) {
video.removeClass("visible-video");
}
});
$("button").click(function() {
video.addClass("visible-video");
});
});
Instead of doing so much with jQuery, I often just use JS to set a class. You can do so much more with CSS than you'd think. Of importance is the CSS. You had a small spelling error (US vs UK spelling) greyscale vs grayscale. But as you can see the + selector is very useful here! Select the element following .visible-video and you can target the section that you want!
iframe {
display: none; /* Hide the video initially */
width: 90%;
margin: auto 5%;
position: fixed;
z-index: 20;
top: 48px;
box-shadow: 0 4px 36px rgba(0,0,0,0.72), 0 0 8px rgba(0,0,0,0.48);
}
.visible-video {
display: block; /* show the video when the class has been set */
}
section {
margin: 24px auto;
width: 80%;
}
.visible-video + section {
-webkit-filter: blur(15px) grayscale(80%);
filter: blur(15px) grayscale(80%);
}
EDIT: I improved the CSS code of the iframe, so it'll scale better, and I included some JS that will detect if the user has clicked on the scrollbar or not. Without this addition, the iframe will also close when clicking the scrollbar.
Full screen result here: https://jsfiddle.net/721nma0g/5/embedded/result/
Edited jQuery:
if (!video.is(e.target) && !video.has(e.target).length && (e.target != $('html').get(0))) {
video.removeClass("visible-video");
}
Edited CSS:
iframe {
display: none;
max-width: 90%;
position: fixed;
z-index: 20;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 4px 36px rgba(0, 0, 0, 0.72), 0 0 8px rgba(0, 0, 0, 0.48);
}
Works great on mobile too.
Related
Background
I have an HTML div which contains a ‘tooltip’-like feature (i.e., a text box pops up when a certain element is clicked or hovered over); this tooltip has decorative pseudo-elements to make it look like a ‘speech bubble,’ added in css as :before and :after .
I have a JS script, which is intended to show and hide the tooltip and decoration, in response to click events (i.e., toggle them between ‘show’ and ‘hide’ states).
Problem
I can’t get the decorative pseudo-elements to hide when the tooltip is hidden; as pseudo-elements, they are not part of the DOM and so I can’t use normal selectors to manipulate them.
When the tooltip is hidden on click, the decorative pseudo-elements persist, which is not a usable result.
I can’t do away with the decorative elements, they are part of the work specification.
Approach tried so far
Based on this question, my thought was to add an empty span with its own class, to which I’d prepend and append these pseudo-elements. Then, add or remove the class on click based on whether it exists already, or not.
I have also tried setting the class to which the pseudo-elements are pre/appended to display:none on click, but this also seems not to work
However, I cannot convince the pseudo-elements to hide on click.
I’ve included a screenshot of what these remnant pseudo-elements look like in the live environment.
Note: I tried to work up a running simulation for the purpose of this question, but I wasn’t able to and the original css file is massive; the code included below is for reference only.
All guidance is much appreciated!
const barContainer = document.querySelector(".bar-container");
const decorationElement = document.querySelector("#decoration");
document.addEventListener('click', function(event) {
console.log('click event listener triggered');
if (event.target.closest('.link') || event.target.classList.contains('link')) {
if (barContainer.classList.contains('open')) {
barContainer.classList.remove('open')
decorationElement.classList.remove('decoration')
document.querySelector('.tooltip-container').setAttribute('style', 'display:none');
} else {
barContainer.classList.add('open')
decorationElement.classList.add('decoration')
document.querySelector('.tooltip-container').setAttribute('style', 'display:block');
}
} else {
barContainer.classList.remove('open')
decorationElement.classList.remove('decoration')
document.querySelector('.tooltip-container').setAttribute('style', 'display:none');
}
});
.foo-container {
height: auto;
position: relative;
}
.bar-container {
height: auto;
position: relative;
text-align: center;
}
.bar-container:hover .tooltip-container,
.tooltip-container:hover,
.bar-container.open .tooltip-container {
position: absolute;
display: block;
text-align: left;
background-color: #ffffff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
bottom: 50px;
right: 5%;
border-radius: 4%;
font-weight: 300;
max-width: 90%;
font-size: 14px;
padding: 20px 0;
}
/*the below two rule sets create the rotated 'decoration' */
.bar-container:hover .tooltip-container:before,
.tooltip-container:hover:before,
.bar-container.open .tooltip-container:before,
.foo-container .bar-container:hover .decoration:before {
content: "";
width: 65px;
height: 35px;
position: absolute;
overflow: hidden;
transform: rotate(-180deg);
z-index: 10;
bottom: 0;
left: 170px;
background-color: white;
}
.foo-container .bar-container.open .decoration:before,
.foo-container .bar-container:hover .decoration:before {
content: "";
position: absolute;
width: 30px;
height: 30px;
background: #fff;
transform: rotate(45deg);
left: 30px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
z-index: 2;
top: -42px;
}
/* end 'deocration' */
<div class="foo-container">
<div class="bar-container">
<p>text <span class='link'>the-link<span id='decoration' class='decoration'></span></span>
</p>
<div class='tooltip-container'>
<p>lorem </p>
</div>
</div>
</div>
Screenshot of the undesirable 'persistent pseudo-elements' behavior -->
In mobile, I'm trying to create a toggle that appears on top of an image, that when tapped on, makes text appear on top of the image too.
I basically want to recreate how The Guardian newspaper handles the little (i) icon in the bottom right corner on mobile.
And on desktop, the the text is there by default under the image and the (i) icon is gone.
So far I've managed to find a similar solution elsewhere online but it's not quite working right as I need it to.
function toggleText() {
var text = document.getElementById("demo");
if (text.style.display === "none") {
text.style.display = "block";
} else {
text.style.display = "none";
}
}
#blog {
width: 100%;
}
#blog figure {
position: relative;
}
#blog figure figcaption {
display: none;
position: absolute;
bottom: 0;
left: 0;
box-sizing: border-box;
width: 100%;
color: black;
text-align: left;
background: rgba(0, 0, 0, 0.5);
}
#blog figure button {
position: absolute;
bottom: 0;
right: 0;
color: black;
border: 5px solid black;
}
<div id="blog">
<figure>
<img src="https://cdn2.hubspot.net/hubfs/4635813/marble-around-the-world.jpg" alt="A photo of a slab of marble for example">
<figcaption id="demo" style='display: none'>A photo of a slab of marble for example</figcaption>
<button type='button' onclick="toggleText()">(i)</button>
</figure>
</div>
Don't use IDs. Your code should be reusable!
Don't use inline JS on* handlers, use Element.addEventListener() instead
Don't use inline style attributes.
Don't use el.style.display === "something" to check for display styles. Use Element.classList.toggle() instead
This straightforward example uses JavaScript to simply toggle a className "is-active" on the button's parent, the figure Element.
Everything else (icon symbol change, caption animation etc...) is handled purely by CSS:
document.querySelectorAll("figure button").forEach(EL_btn => {
EL_btn.addEventListener("click", () => {
EL_btn.closest("figure").classList.toggle("is-active");
});
});
/* QuickReset */ * {margin: 0; box-sizing: border-box;}
img {
max-width: 100%; /* Never extend images more than available */
}
figure {
position: relative;
overflow: hidden; /* overflow hidden to allow figcaption hide bottom */
}
figure img {
display: block; /* prevent "bottom space" caused by inline elements */
}
figure figcaption {
position: absolute;
width: 100%;
bottom: 0;
padding: 1rem;
padding-right: 4rem; /* Prevent text going under the button icon */
color: #fff;
background: rgba(0, 0, 0, 0.5);
transform: translateY(100%); /* Move down, out of view */
transition: transform 0.3s; /* Add some transition animation */
}
figure.is-active figcaption {
transform: translateY(0%); /* Move into view */
}
figure button {
position: absolute;
width: 2rem;
height: 2rem;
bottom: 0.5rem;
right: 0.5rem;
border-radius: 50%;
color: #fff;
background: rgba(0, 0, 0, 0.5);
border: 0;
cursor: pointer;
}
figure button::before {
content: "\2139"; /* i icon */
}
figure.is-active button::before {
content: "\2A09"; /* x icon */
}
<figure>
<img src="https://cdn2.hubspot.net/hubfs/4635813/marble-around-the-world.jpg" alt="A photo of a slab of marble for example">
<figcaption>A photo of a slab of marble for example</figcaption>
<button type="button"></button>
</figure>
The above will work for any number of such elements on your website without the need to add any more CSS or JS.
I see a couple things that could mess this up, one is the fact that there is nothing to make your image adjust to your mobile screen, more-over there is also margin that is there by default, so I suggest these changes to the CSS:
First I'd set box-sizing to border-box and margin to 0, this should be a regular practice by the way.
*{
box-sizing: border-box;
margin: 0;
}
Then select the image and make it adjust to your page as such
#blog figure img{
height: auto;
width:100%;
}
Finally, for some styling you can add some padding to your blog div to make the image slightly smaller on your screen
#blog {
width: 100%;
padding: 35px;
}
This is the Fiddle for it.
Here's the challenge:
I have two divs layered on top of one another in an HTML file. The top div is mostly transparent using CSS the bottom div has an image as its background. On mouseenter, I want the top div to disappear and on mouseleave I want the top div to come back.
$(document).ready(function() {
$('.dimmer').on('mouseenter', event => {
$(this).hide();
}).on('mouseleave', event => {
$(this).show();
});
});
.experience {
background: url("cmu-110.png") no-repeat center;
height: 110px;
width: 110px;
z-index: 2;
}
.dimmer {
background: rgba(238, 238, 238, .25);
position: relative;
top: -128px;
z-index: 3;
}
<div>
<div class="experience"></div>
<div class="dimmer"></div>
</div>
The jquery code snippet above is in a separate file and called in the html's head.
<head>
<!--- Some head stuff like title, meta, calling css in separate file, etc --->
<!--jquery-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="interaction.js"></script>
</head>
Full transparency: I am new to jquery and trying to use it for the first time. Despite working through the full codecademy jquery tutorial, reading w3C school tutorial, searching other stackoverflow posts, and spending more than a reasonable amount of time, I can't seem to get this to work--probably due to a dumb mistake.
Thank you for your help!
I believe a jquery '.on( "mouseout", handler )' on the bottom div should be sufficient to make the top div visible/fade in.
This post should help you: jquery .mouseover() and .mouseout() with fade
If not (if that does not work) what I would do/suggest is:
When mouse enters the top div activate a setTimeout polling functiion or .mouseMove that runs every 1 second or so which checks the mouse position and hide the top div.
If the mouse is not on the bottom div (mousemove) , then display the top div and disable the polling.
You can seach this forum for how to write a setTimeout polling function, etc. If I have some time over the weekend I will give it a whirl...
Trust this helps.
You can set the css visibility property to hidden and visible on mouseenter and mouseleave. I put some space between two divs to make the effect visible clearly.
$(document).ready(function() {
$('.dimmer').on('mouseenter', () => {
$('.dimmer').css("visibility","hidden");
}).on('mouseleave', () => {
$('.dimmer').css("visibility","visible");
});
});
.experience {
background: red;
height: 110px;
width: 110px;
z-index: 0;
}
.dimmer {
background: blue;
position: absolute;
top: -10px;
height: 110px;
width: 110px;
z-index: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div class="experience"></div>
<div class="dimmer"></div>
</div>
jQuery(document).ready(function(){
jQuery(".dimmer").on({
mouseenter: function () {
jQuery(this).css('opacity', '0');
},
mouseleave: function () {
jQuery(this).css('opacity', '1');
}
});
});
.experience {
background: url("http://lorempixel.com/400/200/") no-repeat center;
height: 110px;
width: 110px;
z-index: 2;
}
.imparant{
position:relative;
height: 110px;
width: 110px;
}
.dimmer {
background: rgba(238, 238, 238, .25);
position: absolute;
top: 0;
left:0;
right:0;
bottom:0;
z-index: 3;
transition:opacity 320ms;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<div class="imparant">
<div class="experience"></div>
<div class="dimmer"></div>
</div>
You don't really need to use jQuery or javascript at all for this. You can do it with a single div, a pseudo-element, and a hover style:
.container{
position:relative;
height: 110px;
width: 110px;
background-image: url("https://randomuser.me/api/portraits/men/41.jpg");
}
.container::before{
content: '';
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0,0,0,0.5);
transition: opacity 0.4s;
}
.container:hover::before{
opacity: 0;
}
<div class="container"></div>
If for some reason you wanted to keep the extra divs you could still do it but you'd want to change the CSS hover rule slightly. If you were ok moving the .dimmer before .experience you could just do the hover directly on the .dimmer element:
.dimmer:hover { opacity: 0 }
Otherwise you'd need to use a descendant selector:
.outerDiv:hover .dimmer { opacity: 0 }
Ok so Im new to jQuery and a little confused how to achieve my goal here. The goal is whenever the browser is less than 780px wide I want to disable all hover effects. So I did a lot of research and still cant figure out a specific way that works for me, though I have come close. Below is the jQuery and HTML. So the class .allHover is what is triggering the hover effects. So I thought to remove the hover effect when the browser is less than 780px I would use a .removeClass method which would break the hover effect. The jQuery code below works, however when I resize the window to less than 780 px then refresh my browser the hover effect comes back and I dont want that. Is there something I can add to ensure the class .allHover doesnt come back when the page is less than 780px wide and the page is refreshed? Thank you in advance.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(window).on("load resize", function mobileViewUpdate() {
var viewportWidth = $(window).width();
if (viewportWidth <= 780) {
$(".allHover").removeClass("allHover").addClass("gallery-mobile");
}
});
</script>
<style>
.stockDesign_image, .customDesign_image {
width: 340px;
height: 382px;
margin: 30px auto;
transition: all 0.2s ease-in-out;
}
div.allHover:hover .stockDesign_image, div.allHover:hover .customDesign_image {
width: 360px;
}
.prodBoxes_header {
background-color: #4c2e90;
}
div.allHover:hover .prodBoxes_header {
background-color: #5E3EA6;
}
.prodBoxes_headerright {
background-color: #ff6600;
}
div.allHover:hover .prodBoxes_headerright {
background-color: #fb8332;
}
.viewAll_button {
background-image: url(images/VIEW-ALL.png);
width: 141px;
height: 34px;
float: right;
overflow: hidden;
position: relative;
margin: 8px 5px 0 0;
}
div.allHover:hover .viewAll_button {
background-position: 0 -34px;
}
</style>
<div class="allHover">
<div class="prodBoxes_header">
<p class="medalHeader_text">CHOOSE FROM<br>1000+Insert designs...</p>
</div>
<div class="stockDesign_image"></div>
<div class="prodBoxes_footer">
<p class="footer_asLOWas">as low as <span class="asLOWas_price">$<?=($prod[1]->sale_price ?: $prod[1]->aslow_price);?></span></p>
<div class="viewAll_button"></div>
</div>
</div>
You need to call the hiding functionality also when the page is loaded. This can be done in the ready-function. I moved the hdiding funtionality to fucntion checkViewportWidth and call in both cases.
It seems that on('load') is not executed on page refresh.
$(document).ready(function() {
function checkViewportWidth() {
var viewportWidth = $(window).width();
console.log(viewportWidth);
if (viewportWidth <= 780) {
$(".allHover").removeClass("allHover").addClass("gallery-mobile");
}
}
$(window).on('load resize', function mobileViewUpdate() {
checkViewportWidth();
});
checkViewportWidth();
});
Please see also Plunker
An example of how to accomplish this with media queries (given the hover effect is done with css.) The style will only work when screen size is <780.
#media only screen and (min-width: 780px) {
.allHover:hover {
...
}
}
But if you need this to be js, you'll just need to add an else:
function checkViewportWidth() {
var viewportWidth = $(window).width();
console.log(viewportWidth);
if (viewportWidth <= 780) {
$(".allHover").removeClass("allHover").addClass("gallery-mobile");
}
else{
$(".allHover").addClass("allHover").removeClass("gallery-mobile");
}
}
A CSS only approach would be to add your :hover CSS in a #media query with min-width: 780px since you want :hover effects to fire when the window is > 780px.
#media (min-width: 780px) {
div.allHover:hover .stockDesign_image,
div.allHover:hover .customDesign_image {
width: 360px;
}
div.allHover:hover .prodBoxes_header {
background-color: #5E3EA6;
}
div.allHover:hover .prodBoxes_headerright {
background-color: #fb8332;
}
div.allHover:hover .viewAll_button {
background-position: 0 -34px;
}
}
.stockDesign_image, .customDesign_image {
width: 340px;
height: 382px;
margin: 30px auto;
transition: all 0.2s ease-in-out;
}
.prodBoxes_header {
background-color: #4c2e90;
}
.prodBoxes_headerright {
background-color: #ff6600;
}
.viewAll_button {
background-image: url(images/VIEW-ALL.png);
width: 141px;
height: 34px;
float: right;
overflow: hidden;
position: relative;
margin: 8px 5px 0 0;
}
<div class="allHover">
<div class="prodBoxes_header">
<p class="medalHeader_text">CHOOSE FROM<br>1000+Insert designs...</p>
</div>
<div class="stockDesign_image"></div>
<div class="prodBoxes_footer">
<p class="footer_asLOWas">as low as <span class="asLOWas_price">$<?=($prod[1]->sale_price ?: $prod[1]->aslow_price);?></span></p>
<div class="viewAll_button"></div>
</div>
</div>
Edit: I fixed my problem, apparently jQuery 2.1.4.js wasn't found. #stupidmistakesthatyouoverlook thanks to all who responded and helped! It was very useful!
The Problem
I want a link to remove a class from a div so that it will show the contents and fade-in or out depending on the situation; however, my code (shown below) isn't accomplishing that task and I don't know why? Any Ideas?
My Code
Assume that I have an index.html that includes nav.jade and about.jade. For reference, I am using Jekyll.
(nav.jade)
section.nav
ul#navList
li
a(href="#")#video-link
i.fa.fa-youtube-play
| Music Video
(about.jade)
.video-overlay.hide
.video-container
<iframe width="853" height="480" src="https://www.youtube.com/embed/EN5xqCNbf9c" frameborder="0" allowfullscreen></iframe>
a(href="#").hide-cta Close this Video
(about.sass)
.video-overlay
display: flex
justify-content: center
align-items: center
position: fixed
left: 0
right: 0
top: 0
bottom: 0
background-color: rgba(0, 0, 0, 0.5)
z-index: 50
.video-container
width: 853px
height: 480px
background-color: black
padding: 5px
.hide-cta
position: absolute
top: 80%
left: calc(50% - 85px)
text-align: center
text-decoration: none
padding: 5px 10px
color: white
border: 2px solid white
transition: all 0.3s ease-in-out
margin-top: 30px
&:hover
color: black
background: white
border: 2px solid white
.hide
display: none
(functions.js)
$(function() {//shorthand for $('document').ready(function () {}
$('#video-link').on('click', function() { //check if link was clicked
$('.video-overlay').removeClass('.hide'); //unhide the div
$('.video-overlay').fadeIn('slow'); //fade the div in
return false; //if it wasn't clicked return false
});
$('#hide-cta').on('click', function() { //check if link was clicked
$('.video-overlay').addClass('.hide'); //make the div hide itself
$('.video-overlay').fadeOut('slow'); //fade the div out
return false; //if it wasn't clicked return false
});
});
This is a common syntax error that many people stumble into. I have been guilty of it in the past as well. Do not user selectors in the addClass and removeClass function calls. Just use the class name.
So the calls should look like
$('.video-overlay').removeClass('hide'); //unhide the div
and
$('.video-overlay').addClass('hide'); //make the div hide itself
respectively.