How to consolidate JS functions into one function utilizing event.target? - javascript

I have a div with 12 buttons. Each one has eventListeners for mouseenter(). When user rolls over a button, the other 11 buttons fade out. I've got enough code to make your eyes bleed. But I'm having trouble consolidating it all into one function, and just using event.target.
I can get the basics going, but am having problems inserting a for loop (with a continue needed, I believe) to fade out each of the other buttons, not including the one that is being hovered over (my event.target element). You can see in my code, that currently I have a line of code for each of the other buttons, to run an opacity fade loop on them. How can I consolidate this into a single function?
Here is the code I'm running each time a button gets rolled over:
function fadeOut01() {
var op = 1; // initial opacity
var timer = setInterval(function () {
if (op <= 0.1){
clearInterval(timer);
}
box02.style.opacity = op;
box03.style.opacity = op;
box04.style.opacity = op;
box05.style.opacity = op;
box06.style.opacity = op;
box07.style.opacity = op;
box08.style.opacity = op;
box09.style.opacity = op;
box10.style.opacity = op;
box11.style.opacity = op;
box12.style.opacity = op;
op -= op * 0.1;
}, 20);
}
And here is the html where I define the boxes:
<div id="grid01" class="grids"><div class="gridText">video</div></div>
<div id="grid02" class="grids"><div class="gridText">broadcast</div></div>
<div id="grid03" class="grids"><div class="gridText">graphics</div></div>
<div id="grid04" class="grids"><div class="gridText">digital signage</div></div>
<div id="grid05" class="grids"><div class="gridText">3d</div></div>
<div id="grid06" class="grids"><div class="gridText">virtual sets</div></div>
<div id="grid07" class="grids"><div class="gridText">print</div></div>
<div id="grid08" class="grids"><div class="gridText">technical direction</div></div>
<div id="grid09" class="grids"><div class="gridText">live events</div></div>
<div id="grid10" class="grids"><div class="gridText">photography</div></div>
<div id="grid11" class="grids"><div class="gridText">workflow automation</div></div>
<div id="grid12" class="grids"><div class="gridText">our clients</div></div>

If I understand your question correctly, this should be solvable via the following - please see the comments below for contextualized information on how this works:
/* Query all grids of the grid-wrapper and apply same hover behavior to each */
document.querySelectorAll('.grid-wrapper .grids').forEach(function(element) {
/* Get the grid wrapper that encloses the grid element */
const gridWrapper = document.querySelector('.grid-wrapper');
/* Add mouse over event and add hover classes for both the wrapper and
grid elements */
element.addEventListener('mouseover', function() {
element.classList.add('hover');
gridWrapper.classList.add('hover');
});
/* Add mouse out event and remove hover classes for both the wrapper and
grid elements */
element.addEventListener('mouseout', function() {
element.classList.remove('hover');
gridWrapper.classList.remove('hover');
});
});
.grid-wrapper .grids {
/* Set default opacity for grid-wrapper grids */
opacity: 1;
/* Specifcy the transition behavior for opacity property of .grids.
Transition will take .35s and be delayed by .1s to reduce flickering
when moving quickly between grids */
transition: opacity 0.35s linear 0.1s;
/* Extra styles just added for presentation */
display: inline-block;
width: 150px;
height: 100px;
background: grey;
margin: 10px;
}
/* When .hover modifier class is applied to the wrapper, cause the
children (.grids) to fade out by default (we'll prevent/override this
default behavior for the actual grid child being hovered to achieve
the desired final result) */
.grid-wrapper.hover .grids {
opacity: 0.1;
}
/* Override the default grid-wrapper hover for the actual grid being
hovered to ensure
that it is still visible */
.grid-wrapper.hover .grids.hover {
opacity: 1
}
<div class="grid-wrapper">
<div id="grid01" class="grids">
<div class="gridText">video</div>
</div>
<div id="grid02" class="grids">
<div class="gridText">broadcast</div>
</div>
<div id="grid03" class="grids">
<div class="gridText">graphics</div>
</div>
<div id="grid04" class="grids">
<div class="gridText">digital signage</div>
</div>
<div id="grid05" class="grids">
<div class="gridText">3d</div>
</div>
<div id="grid06" class="grids">
<div class="gridText">virtual sets</div>
</div>
<div id="grid07" class="grids">
<div class="gridText">print</div>
</div>
<div id="grid08" class="grids">
<div class="gridText">technical direction</div>
</div>
<div id="grid09" class="grids">
<div class="gridText">live events</div>
</div>
<div id="grid10" class="grids">
<div class="gridText">photography</div>
</div>
<div id="grid11" class="grids">
<div class="gridText">workflow automation</div>
</div>
<div id="grid12" class="grids">
<div class="gridText">our clients</div>
</div>
</div>
Hope that helps!

Related

How to have 2 move in effect when scroll javascript?

Hello guys im trying to make 2 different move in effect when i scroll on my web (show from right and shown from left). How can i make it ? can somebody help me please, i already manage to make them show from the left side, how can i make the right part
Here's my code:
Reveal from left side
<div class="container-fluid padding salimheader">
<div class="row padding">
<div class="col-lg-12 text-center reveal">
<h1>Salim Group</h1>
<hr style="width:15%; border:3px solid; color:#caa461; margin:auto;">
<br>
</div>
</div>
</div>
Reveal from right side
<div class="container-fluid padding">
<div class="row padding">
<div class="col-lg-12 text-center reveal">
<h1>Sayung Group</h1>
<hr style="width:15%; border:3px solid; color:#caa461; margin:auto;">
<br>
</div>
</div>
</div>
.reveal{
position: relative;
transform: translateX(-150px);
opacity: 0;
transition: all 1s ease;
}
.reveal.active {
transform: translateX(0px);
opacity: 1;
}
Javascript code:
window.addEventListener('scroll', reveal);
function reveal(){
var reveals = document.querySelectorAll('.reveal');
for(var i=0; i< reveals.length; i++){
var windowheight= window.innerHeight;
var revealtop = reveals[i].getBoundingClientRect().top;
var revealpoint = 150;
if(revealtop < windowheight - revealpoint){
reveals[i].classList.add('active');
}
}
You could use a second reveal class which just has a positive 150px translate instead of negative:
.reveal-right {
transform: translateX(150px);
}
You'll need to add both the reveal and the reveal-right class to any div you want this to work on.

jQuery on click cycle through images in identical .wrappers independently

I'm not a programmer, just trying to assemble a small website for myself.:)
What I'm trying to do:
A ".container" with a grid of images - each inside of an identical ".wrapper", some of them are non-clickable single-image wrappers, some of them are clickable "stacks" of 1-4 images - click again and again to see all images in that .wrapper one by one.
<div class="container">
<div class="wrapper">
<div class="content"><img src="1.png"></div>
<div class="content"><img src="2.png"></div>
<div class="content"><img src="3.png"></div>
<div class="content"><img src="4.png"></div>
</div>
<div class="wrapper">
<div class="content"><img src="5.png"></div>
</div>
<div class="wrapper">
<div class="content"><img src="6.png"></div>
<div class="content"><img src="7.png"></div>
</div>
</div>
What I have done so far: found here (JQuery cycle through text on click) this piece of code:
$(document).ready(function () {
var divs = $('div[id^="content-"]').hide(),
i = 0;
function cycle() {
divs.fadeOut(400).delay(400).eq(i).fadeIn(400);
i = ++i % divs.length;
};
cycle()
$('button').click(cycle);
// click button to show next paragraph
});
and "almost" "adapted" it for my needs :D:
<script type="text/javascript">
$(document).ready(function () {
var divs = $('.content').hide(),
i = 0;
function cycle() {
divs.fadeOut(0).delay(0).eq(i).fadeIn(0);
i = ++i % divs.length;
};
cycle()
$('.wrapper').click(function(){cycle()})
});
</script>
and also this FIDDLE - the problem looks similar to mine, maybe?
The problem and what I need: the "adapated" version of the jQuery code above works with 1 ".wrapper". But different names for all wrappers and a copy of the same script for each of them in my index.html sounds like a disastrous idea and the only way I can do it myself.:D I believe there should be an elegant tweak/fix of the jQuery code that would make it work for EACH ".wrapper" independently and only for images inside it, not interfering with other .wrappers and their images.
This is why I'm asking for your help and would appreciate any help, guys!
I believe the following will do what you want (if I understand requirements correctly). You basically need to loop over each wrapper and treat them as individual instances
$('button').on('click', function() {
// isolate each wrapper
$('.wrapper').each(function() {
// get the content within this wrapper instance
var $content = $(this).find('.content');
// don't do anything if it is a single
if ($content.length > 1) {
// current is the only visible one
var $curr = $content.filter(':visible');
// if current is last one next will be first one in this group
// otherwise will be the one right after it
var $next = $curr.is($content.last()) ? $content.first() : $curr.next();
// fade out current
$curr.fadeOut(function() {
// this function runs when fadeOut has completed
// and can now fade in the next one
$next.fadeIn()
});
}
});
});
.wrapper {
border: 2px solid #ccc;
margin: 10px;
padding: 10px
}
.content {
display: none
}
.content:first-child {
display: block
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="wrapper">
<div class="content">Wrap #1 Img #1</div>
<div class="content">Wrap #1 Img #2</div>
<div class="content">Wrap #1 Img #3</div>
<div class="content">Wrap #1 Img #4</div>
</div>
<div class="wrapper">
<div class="content">Wrap #2 Img #1</div>
</div>
<div class="wrapper">
<div class="content">Wrap #3 Img #1</div>
<div class="content">Wrap #3 Img #2</div>
</div>
</div>
<button>Toggle content</button>

Gradually fade buttons only if they aren't currently being hovered over

I have forward and backward buttons for an image gallery. Currently, they fade away when the mouse is idle. Any movement on the page will show them again. Here's the code:
//fade out previous/next buttons on mouse idle
var timer;
$(document).mousemove(function() {
if (timer) {
clearTimeout(timer);
timer = 0;
}
$('.fader').fadeIn();
timer = setTimeout(function() {
$('.fader').fadeOut(1500)
}, 1000)
})
This works fine, but I also would like the buttons to not fade out at all if they are currently being hovered.
As a test, I've tried this code:
//both buttons are stored in class .fader
//when buttons are hovered over
$(".fader").hover(
function(){
//give them this class
$(this).toggleClass('is-hover');
})
//if buttons have .is-hover class, print test statement to console
if($(".fader").hasClass('is-hover')){
console.log("true");
}
I'm hoping to see the test "true" statement printed to the console, but it's not happening.
Ultimately, I'd like to wrap the first function in the second. If buttons are not being hovered over, then perform this timed fadeout of buttons.
Here is where the buttons are in the HTML:
<!-- Swiper -->
<div ng-show="show" class="swiper-container">
<div class="swiper-wrapper"></div>
<div class="swiper-pagination"></div>
<!--The buttons-->
<div class="swiper-button-next fader"></div>
<div class="swiper-button-prev fader"></div>
</div>
You can use CSS for the button hovering...
But to track mouse movement on the document, a script is needed.
You can use both! ;)
// To track mouse movement and fadein all buttons
var timer;
$(document).on("mousemove",function(){
$(".fader").addClass("faderShowOnMouseMove");
if(typeof(timer)!="undefined"){
clearTimeout(timer);
}
timer = setTimeout(function(){
$(".fader").removeClass("faderShowOnMouseMove");
},1000);
});
/* Base style for buttons */
.fader {
opacity: 0;
transition: opacity 1s ease-in-out;
-moz-transition: opacity 1s ease-in-out;
-webkit-transition: opacity 1s ease-in-out;
}
/* For single button hovering */
.fader:hover {
opacity: 1;
}
/* Used with JS mouse movement */
.faderShowOnMouseMove{
opacity: 1;
}
/* Just for this demo ;) */
.swiper-pagination{
border:1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Swiper -->
<div ng-show="show" class="swiper-container">
<div class="swiper-wrapper">
Hover over here! <i>(right below this text)</i><br>
<div class="swiper-pagination">
<!--The buttons-->
<button class="fader">1</button>
<button class="fader">2</button>
<button class="fader">3</button>
</div>
</div>
</div>

hover over one element, transition another element

I have two divs A and B. div A is an image. Div B is a paragraph underneath div A.
I am trying to make it so that if I put the mouse over div A, the background and font colour of div B transition to different colours without affecting div A.
I currently have the :hover selector so div B changes if someone hovers over it. But I don't know how to affect div B while hovering over div A.
Any clues on how to achieve this?
EDIT:
Please see below for the structure of my code. I'm trying to make it so that if I hover over #image1, the background of #info1 and the font colour of its paragraph would change and so on so forth for the other two images.
<div class="row">
<div class="col-md-4 col-sm-12">
<div class="row">
<div class="col-md-12 col-sm-6">
<img id="image1" src="res/images/aimage1.png" class="img-responsive center-block">
</div>
<div id="info1" class="col-md-12 col-sm-6">
<p class="washed-out"> 1 </p>
</div>
</div>
</div>
<div class="col-md-4 col-sm-12">
<div class="row">
<div class="col-md-12 col-sm-6">
<img id="image2" src="res/images/aimage2.png" class="img-responsive center-block">
</div>
<div id="info2" class="col-md-12 col-sm-6">
<p class="washed-out"> 2 </p>
</div>
</div>
</div>
<div class="col-md-4 col-sm-12">
<div class="row">
<div class="col-md-12 col-sm-6">
<img id="image3" src="res/images/animage3.png" class="img-responsive center-block">
</div>
<div id="info3" class="col-md-12 col-sm-6">
<p class="washed-out"> 3 </p>
</div>
</div>
</div>
</div>
css:
.washed-out{
background: white;
color: black;
transition: background-color 300ms linear, color 1s linear;
}
.washed-out:hover{
background: black;
color: white;
}
You use the sibling selector ~ or the immediate sibling selector +
img:hover + div {
color: red;
}
<img src="http://placehold.it/100">
<div>Hey there...I get red when you hover the image</div>
Update based on comment, possible CSS version
.hoverme:hover + div .washed-out {
color: red;
background: black;
}
<div class="col-md-12 col-sm-6 hoverme">
<img id="image1" src="res/images/aimage1.png" class="img-responsive center-block">
</div>
<div id="info1" class="col-md-12 col-sm-6">
<p class="washed-out">1</p>
</div>
Update based on comment, possible JS version
window.addEventListener('load', function() {
var imglist = document.querySelectorAll('img.img-responsive');
for (var i = 0; i < imglist.length; i++) {
imglist[i].addEventListener('mouseover', function(e) { e.target.parentElement.nextElementSibling.classList.add('infos');
})
imglist[i].addEventListener('mouseout', function(e) { e.target.parentElement.nextElementSibling.classList.remove('infos');
})
}
})
div.infos .washed-out {
color: red;
background: black;
}
<div class="col-md-12 col-sm-6">
<img id="image1" src="res/images/aimage1.png" class="img-responsive center-block">
</div>
<div id="info1" class="col-md-12 col-sm-6">
<p class="washed-out">1</p>
</div>
You're looking for the adjacent sibling selector - element:hover + element:
.container {
width: 100px;
height: 100px;
background: red;
transition: all 0.5s;
}
.container:first-child {
margin-bottom: 10px;
}
/** if the 1st element is hovered, changed the 2nd **/
.container:hover + .container {
background: blue;
color: white;
}
<div class="container">Div 1</div>
<div class="container">Div 2</div>
What you want can be done by javascript event handler.
Something like this:
var d1 = document.getElementById("div1"); // on hover on this div
var d2 = document.getElementById("div2"); // bring changes to this
d1.addEventListener("hover", callfun, false);
function callfun(){
d2.style.backgroundColor = 'blue';
}
Good luck
Basically you need to register a hovering in and out handler as shown in the following answer:
Event listener hover changing other element
Here is a slightly modified version of it to fit more closely to your need.
document.getElementById("Div-A").addEventListener("mouseenter",function (){
document.getElementById("Div-B").style.backgroundColor = "red";
document.getElementById("Div-B").style.backgroundColor = "Yellow";
});
document.getElementById("Div-A").addEventListener("mouseout",function (){
document.getElementById("Div-B").style.backgroundColor = "";
document.getElementById("Div-B").style.text = "";
});
Use successor siblings ~ or immediate successor siblings + to make any change on hover
img:hover ~ div {
color: red;
}
<img src="http://placehold.it/100">
<div>Hey there...I get red when you hover the image</div>
<div>Hey there...I also get red when you hover the image</div>
<script>
function Myfunc1(){
document.getElementById("div1").style.backgroundColor = "green"
document.getElementById("div2").style.backgroundColor = "white"}
function Myfunc2(){
document.getElementById("div2").style.backgroundColor = "red"
document.getElementById("div1").style.backgroundColor = "white"}
</script>
<pre><div id="div1" onmouseover="Myfunc1()"><img src=""><p> look</p></div>
<div id="div2" onmouseover="Myfunc2()"><p>here</p></div></pre>

Select the last two items of a parent element, add class and apply changes to both of them->not working

This jsfiddle example can explain more or less what I mean
Click here
This is my actual code
JS
loadMore : function(){
var limit = initial_rows+1; //initial_rows begin being 2
var number_of_rows_to_append = initial_rows+2; // 4
$card.css('height', $card.find('.title-box').height() + number_of_rows_to_append * 70); //update card height
for(var i = initial_rows; i<=limit; i++){
$(template(content[i])).appendTo($contentJQuery);
}
$contentJQuery.find('.normal-box').slice(-2).addClass('show');
initial_rows+=2;
}
},
CSS
.normal-box{ /*Container of other tiny boxes*/
height: 70px;
border-bottom: 1px solid;
border-bottom-color: gainsboro;
overflow: hidden;
opacity: 0;
transition: opacity 0.5s ease 0.5s;
}
.normal-box.show{
opacity: 1;
}
HTML
<div class="card">
<div class="content">
<div class="normal-box">
</div>
<div class="normal-box">
</div>
<div class="normal-box">
</div>
<div class="normal-box">
</div>
</div>
</div>
Basically there is a function which creates the card and appends only 2 normal-boxes at the beginning(there opacity is set to 1 automatically). When loadMore() function is triggered 2 more rows have to be appended with the opacity transition as shown in the jsfiddle example(in my case the rows appear, in the jsfiddle they disappear). The transition consists in the card getting bigger(thats why card height gets updated) with a blank space, then the 2 last normal-boxes appear with transition
The problem is that in my case the last row appears without transition and the penultimate appears with transition, no idea why. Any help will be appreciated
Updated Fiddle:
Perhaps this is what you intended:
revised jsFiddle
$('.btn').on('click', function(){
$('li').each(function(){
var txt = $(this).text().slice(0,-2); //or .slice(-1) ?
$(this).text(txt).addClass('change');
});
});

Categories

Resources