How to highlight an element when I click on a different element in angular - javascript

So I have this original box lets say box #1 (shown on left). Box #1 has a button on it that when it is clicked, it opens box #2 (shown on right). Box #2 contains a button on it that when that is clicked, I want box #1 to highlight to show that box #2 came from box #1. Any ideas on how to do this?
I was trying stuff with ng-click but can't figure out what exactly needs to be in it

There are many ways to achieve this with varying levels of complexity depending on what you need from the system and the components in place.
To start, here's a very basic solution that achieves what you are after, all achieved through an object which holds the state of the system. Added an *ngFor to demonstrate how you could easily achieve multiple boxes (assuming this would be beneficial). Stackblitz
.html
<div class="box-group-container">
<div
*ngFor="let box of boxes"
class="box-group">
<div
class="box box-one"
[class.is-flashing]="box.flashBoxOne">
<button (click)="box.showBoxTwo = !box.showBoxTwo">{{ !box.showBoxTwo ? 'Show' : 'Hide' }}</button>
</div>
<div
*ngIf="box.showBoxTwo"
class="box box-two">
<button (click)="box.flashBoxOne = !box.flashBoxOne">{{ !box.flashBoxOne ? 'Flash' : 'Stop' }}</button>
</div>
</div>
<button (click)="addBoxGroup()">Add Box Group</button>
</div>
.ts
boxes = [
{
showBoxTwo: false,
flashBoxOne: false,
},
]
addBoxGroup() {
this.boxes.push({
showBoxTwo: false,
flashBoxOne: false,
})
}
.scss
.box-group-container {
display: flex;
flex-direction: column;
gap: 8px;
.box-group {
display: flex;
flex-direction: row;
gap: 8px;
.box {
height: 100px;
width: 100px;
display: flex;
align-items: center;
justify-content: center;
&.is-flashing {
animation: flashing 0.5s infinite;
}
}
.box-one {
background-color: blue;
}
.box-two {
background-color: red;
}
}
}
#keyframes flashing {
0% { opacity: 1.0; }
50% { opacity: 0.0; }
100% { opacity: 1.0; }
}

Related

How do I make an element slide in after 3 seconds of page load

How do I make an element on my webpage slide in after 3 seconds, and once user get it active (select what they want), it slides out automatically.
I want the element to be hidden upon load, untill 3 seconds before it slides in. And once user selects what they want, it slides out.
I've made my research but all I can see is with a button attached. How do I make this happen without that. Automatically.
JavaScript might be involved but I don't know how to go about that.
Please I really would appreciate any suggestion
#keyframes slideInFromRight {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(0);
}
}
#mmj {
position: relative !important;
/* This section calls the slideInFromRight animation we defined above */
animation: 2s ease-out 3s 1 slideInFromRight !important;
}
<div id="mmj">
<div id="google_translate_element"></div>
<div class="vl"></div>
</div>
1- the code you provided doesn't reproduce any issue.
2- according to your words
I want the element to be hidden upon load, until 3 seconds before it slides in. And once user selects what they want, it slides out.
I simply used margin to achieve that. here is the code.
let container = document.getElementById("container");
let btns = container.children;
setTimeout(() => {
container.style.marginRight = "0px";
}, 3000); // to slide it in after 3 seconds
for (const btn of btns) {
btn.addEventListener("click", clicked =>{
container.style.marginRight = "-350px";
// to slide it out after clicking one of the cards.
})
};
body {
background: lightgrey;
display: flex;
justify-content: right;
}
#container {
background: lightcoral;
width: 300px;
height: 300px;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
margin-right: -350px;
transition: 1s;
}
.btn {
width: 33%;
height: 50%;
}
<body>
<div class="container" id="container">
<button class="btn">click me</button>
<button class="btn">click me</button>
<button class="btn">click me</button>
<button class="btn">click me</button>
<button class="btn">click me</button>
<button class="btn">click me</button>
</div>
</body>

Animate elements in and out of page

I have several images that I need to horizontally cross the page to the right, exit the page and then re-enter the page from the left. Some of the images will already be out of view, so they will have to enter first.
This is a sketch of what I've tried so far:
var elems = document.getElementsByClassName("child");
for (const elem of elems) {
elem.animate(
[
// keyframes
{transform: "translateX(300px)"},
],
{
// timing options
duration: 5000,
iterations: Infinity
},
);
}
.container {
background-color: aqua;
width: 1000px;
display: flex;
flex-direction: row;
overflow:hidden;
padding: 20px 0;
gap: 10px;
}
.child {
background-color: red;
flex: 0 0 20%;
}
<div class="container">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
<div class="child">8</div>
</div>
For start I tried to slide out all the divs, but even that I don't understand why is not working.
I'm using your code as a starting point however there are 2 major differences between my code and yours. The first is that this solution is not using JavaScript, which is a plus, but it may not be what you are looking for. The second difference is that rather of animating the div elements with the class child, this solution is animating a wrapper div with the class slider.
One important thing to note, is that some calculations must be used for the animation to work properly. Adding or removing elements will require that the values are updated. The formula is the following:
Child div size: 20% (CHILD_SIZE)
Gap between children divs: 10px (GAP)
Amount of the children: 8 (CHILDREN_AMOUNT)
So together it goes like this: translateX(calc((CHILD_SIZE - GAP) * CHILDREN_AMOUNT));
var slider = document.getElementsByClassName('slider')[0];
slider.innerHTML += slider.innerHTML;
.container {
background-color: aqua;
width: 100%;
overflow: hidden;
}
.slider {
display: flex;
flex-direction: row;
padding: 20px 0;
gap: 10px;
animation: slideRight 10s infinite linear;
}
.child {
background-color: red;
flex: 0 0 20%;
}
#keyframes slideRight {
from {
transform: translateX(calc((-20% - 10px) * 8));
}
to {
transform: translateX(100% + 10px);
}
}
<div class="container">
<div class="slider">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
<div class="child">8</div>
</div>
</div>
Updated considering the comment:
There are a few ways, the simpler way though is just to duplicate the div.child elements without touching the animation formula. This can be done just in the markup or using JavaScript to have a more dynamic solution (I have updated the code above to have the desired result).
What I consider a better way, though (not going to elaborate here as many libraries already solve this problem, just search for carousel js libraries), is to just prepend and append the necessary amount of elements to have the desired result instead of duplicating all of them.

Showing a dropdown on click instead of on hover

I am using Avada (fusion-theme) theme on Wordpress for my website (under construction).
They have a mega-menu option that I am using, but I would want it to appear when someone clicks on the main-menu item instead of hovering over it.
Site: www.paradigmtek.com
So right now if someone hovers over say "smart home" at the top, the sub menu appears (smart home tech support, smart hub or speaker setup, etc.). But I would like it to appear on click instead of on hover.
I don't think this will require not a simple CSS trick, but a JS one.
Anyone has experience with that theme or know how to do it?
You can simply add a class to change the opacity of the dropdown menu upon clicking one of the menus. In this example below, I'm adding show class to dropdown to change opacity from 0 to 1 upon clicking the menu. At the same time, I'm addding a class to the clicked menu (i.e. clicked) to give it an accent colour to indicate that it is the menu being clicked.
const menus = document.querySelectorAll('.menu')
const dropdown = document.querySelector('.dropdown')
let activeMenu = null
menus.forEach(menu => {
menu.addEventListener('click', e => {
// Removing previous active menu that is not itself
if (activeMenu && activeMenu !== menu) {
activeMenu.classList.remove('clicked')
activeMenu = menu
}
else if (activeMenu && activeMenu === menu) {
activeMenu = null
} else {
activeMenu = menu
}
menu.classList.toggle('clicked')
// If there is an active menu, show
if (activeMenu) dropdown.classList.add('show')
else dropdown.classList.remove('show')
})
})
* {
box-sizing: border-box;
font-family: Helvetica;
}
html,
body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.container {
display: flex;
justify-content: center;
background: #121212;
}
.menu {
color: white;
margin: 20px;
padding: 20px;
border-radius: 5px;
cursor: pointer;
}
.menu:hover {
color: #ff8888;
}
.menu.clicked {
color: #ff8888;
}
.dropdown {
width: 100%;
height: 100px;
background: #333333;
display: flex;
flex-direction: column;
opacity: 0;
transition: opacity 0.5s ease;
}
.dropdown.show {
opacity: 1;
}
.line {
width: 100%;
height: 3px;
background: #00a5ff;
}
<div class="container">
<div class="menu">Menu 1</div>
<div class="menu">Menu 2</div>
<div class="menu">Menu 3</div>
<div class="menu">Menu 4</div>
</div>
<div class="dropdown">
<div class="line"></div>
</div>
In the options: avada options -> menu -> submenu
You just have to specify hover / click with the select button.
You can also build your own menu by creating a layout
-> avada -> layout
In your layout you can add a menu element on which you apply the wanted options.
Getting Started With Avada Layouts
Understanding Custom Headers
How To Use The Menu Element

How to open equivalent array number on another array?

First of all, I am sorry for this title. Maybe it's not the best to explain my problem. Also, I tried going through suggested posts, but I could not exactly understand them.
I am trying to have the following.
An array with elements from the DOM, that gives:
var boxes = ["box1", "box2", "box3"]
And also an array with a popup, with display:none
var popups = ["pop1", "pop2", "pop3"]
I want to, when clicking on the boxes[i], to open the popups[i].
So my question here is how do I save that event that gives me the [i] so I can open the exact same [i] on the popups.
Sorry for not using code, but I thought it'd be more complicated. Still, feel free to construct it with this:
var boxes = document.getElementsByClassName("box");
var popupss = document.getElementsByClassName("pop");
.wrapper {
display: flex;
justify-content:space-between;
}
.box {
cursor:pointer;
display:flex;
justify-content:center;
align-items:center;
background-color: #FC543A;
padding: 50px;
border-radius: 3px;
}
.wrapper2 {
display:flex;
justify-content:center;
background-color: rgba(0,0,0,0.4);
position:fixed;
height:100%;
width:100%;
z-index:2;
overflow:auto;
}
.pop {
margin-top:6em;
background-color:white;
height: 50px;
width: 80%;
display:none;
justify-content:center;
align-items:center;
}
.hide {
display:none;
}
.show {
display:flex;
}
<div class="wrapper">
<div id="box1" class="box">Box1</div>
<div id="box2" class="box">Box2</div>
<div id="box3" class="box">Box3</div>
</div>
<div class="wrapper2">
<div class="pop" id="pop1">
Pop1!
</div>
<div class="pop" id="pop2">
Pop2!
</div>
<div class="pop" id="pop3">
Pop3!
</div>
</div>
Thank you!
The following (heavily commented) does your trick.
Stack snippet hides the results, so expand to full page.
javascript functions used:
addEventListener
Array.prototype.forEach
Bind
document.querySelectorAll
classList
//select all divs with class box and iterate them
Array.prototype.forEach.call(document.querySelectorAll("div.box"), function(element, index) {
//we use Array.prototype.map and use call to pass the node list into the map function to iterate
//assign click handlers
//when an element is clicked it will fire the function boxHandler. We use bind to pass the index of the element to the function.
element.addEventListener("click", boxHandler.bind(element, index), true);
//hide all pops
document.querySelectorAll("div.pop")[index].classList.add("hide");
});
function boxHandler(index) {
//select the div based upon the index.
var pop = document.querySelectorAll("div.pop")[index];
if (pop.getAttribute("data-clicked") != 1) {
//add show to class using classlist.add
pop.classList.add("show");
pop.classList.remove("hide");
pop.setAttribute("data-clicked", 1);
} else {
pop.classList.remove("show");
pop.classList.add("hide");
pop.setAttribute("data-clicked", 0);
}
}
.wrapper {
display: flex;
justify-content: space-between;
}
.box {
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
background-color: #FC543A;
padding: 50px;
border-radius: 3px;
}
.wrapper2 {
display: flex;
justify-content: center;
background-color: rgba(0, 0, 0, 0.4);
position: fixed;
height: 100%;
width: 100%;
z-index: 2;
overflow: auto;
}
.pop {
margin-top: 6em;
background-color: white;
height: 50px;
width: 80%;
display: none;
justify-content: center;
align-items: center;
}
.hide {
display: none;
}
.show {
display: flex;
}
<div class="wrapper">
<div id="box1" class="box">Box1</div>
<div id="box2" class="box">Box2</div>
<div id="box3" class="box">Box3</div>
</div>
<div class="wrapper2">
<div class="pop" id="pop1">
Pop1!
</div>
<div class="pop" id="pop2">
Pop2!
</div>
<div class="pop" id="pop3">
Pop3!
</div>
</div>
You are not really taking the best approach here. Whenever you find yourself duplicating code, stop and take a breath. There is no need to create 3 pop sections of HTML. You should just have one HTML placeholder for your pop message and keep the possible values for that message in a JavaScript array. This makes the HTML cleaner and eliminates the need for a .hide CSS class.
Then, you simply assign each box a click event function that sets the corresponding pop message (from the array) into the pop placeholder.
// Store possible pop messages:
var popMessages = ["Pop1!", "Pop2!", "Pop3!"];
// Get reference to pop placeholder
var pop = document.getElementById("pop");
// Use .querySelectorAll() instead of .getElementsByClassName
// since the latter doesn't perform as well due to returning
// a "live" node list. Also, convert the returned node list
// into a proper array, so that .forEach() can be used on it.
var boxes = Array.prototype.slice.call(document.querySelectorAll(".box"));
// Loop over the boxes
boxes.forEach(function(box, index){
// Set each box to have a click event handling function
box.addEventListener("click", function(){
// Use the pop message corresponding to the index of the box being clicked.
pop.textContent = popMessages[index];
});
});
.wrapper {
display: flex;
justify-content:space-between;
}
.box {
cursor:pointer;
display:flex;
justify-content:center;
align-items:center;
background-color: #FC543A;
padding: 50px;
border-radius: 3px;
}
.wrapper2 {
display:flex;
justify-content:center;
background-color: rgba(0,0,0,0.4);
position:fixed;
height:100%;
width:100%;
z-index:2;
overflow:auto;
}
.show {
display:flex;
}
<div class="wrapper">
<div id="box1" class="box">Box1</div>
<div id="box2" class="box">Box2</div>
<div id="box3" class="box">Box3</div>
</div>
<div class="wrapper2">
<div class="pop" id="pop"></div>
</div>
Try something like this:
const boxes = document.querySelectorAll('.box')
const popups = document.querySelectorAll('.pop')
const doSthAbPopup = popupIndex => {
// Replace this with whatever you want to do with the popups
console.log(popups[popupIndex].textContent)
}
[...boxes].forEach((box, index) => {
box.addEventListener('click', () => {
doSthAbPopup(index)
})
})
You may want to add some checks in to ensure that you've the same number of boxes and popups.
forEach is good for this as it provides closure over index.

Navigation transition

I am new to jQuery and am teaching myself as I go but am struggling to figure out how to indicate that on up scroll the white navigation background moves up to show the white navigation text on panel 1?
bartaile.com is what I am using as inspiration & the changes I'm making to bartaile's navigation are---> after the user scrolls past the first panel the navigation hides, only when the user scrolls up does the navigation show again, when panel 1 comes back down the white navigation backgrouns slide up to hide and shows white text.
Any help or tips to learn how to do this would be greatly appreciated! :-)
var lastScrollTop = 0;
$(window).on('scroll', function() {
var header = $('.header');
var stage0 = $('.stage-0');
var scrollTop = $(window).scrollTop();
if (scrollTop > lastScrollTop) {
// down scroll
if (scrollTop > stage0.offset().top + stage0.height()) {
header.addClass('hide');
}
} else {
// up scroll
if (scrollTop <= stage0.offset().top + stage0.height()) {
header.removeClass('headerBGchange headerLIchange');
} else {
header.removeClass('hide').addClass('headerBGchange headerLIchange BGupTranistion');
}
}
lastScrollTop = scrollTop;
});
.header {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
height: 80px;
-webkit-transition: top .5s ease;
transition: top .5s ease;
position: fixed;
width: 100%;
top: 0;
background-color: transparent;
overflow: hidden;
}
.header ul {
margin: 20px;
padding: 0;
}
.header ul li {
display: inline-block;
margin-right: 20px;
color: white;
}
.header ul li:last-child {
margin-right: 0;
}
.hide {
top: -80px;
}
.headerBGchange {
Background: white;
}
.BGupTranistion {
}
.header.headerLIchange ul li {
color: Blue;
}
.header.headerLIchange {
border-bottom: 1px solid black;
}'
</style>
<!--stage style--><style>
.stage {
color: #fff;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
height: 100vh;
background-color: white;
border-bottom: 1px solid black;
font-size: 48px;
height: 200px;
width: 100%;
}
.stage-0 {
background: grey;
}
.stage-24 {
background: #433937;
}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<div class="header">
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
<div class="stage stage-0">1</div>
<div class="stage stage-2">3</div>
<div class="stage stage-4">5</div>
<div class="stage stage-6">7</div>
<div class="stage stage-8">9</div>
<div class="stage stage-10">11</div>
<div class="stage stage-12">13</div>
<div class="stage stage-14">15</div>
<div class="stage stage-16">17</div>
<div class="stage stage-18">19</div>
<div class="stage stage-20">21</div>
<div class="stage stage-22">23</div>
You will need to add another container to achieve the effect you're looking for. What you essentially want to have is a container at the top and another container which will fade in and out depending on your scroll behaviour. So how do you achieve that? Create a -Element on top of the page, like your gray box is there at the moment. When scrolling down, do not transform it, instead, fade in another previously hidden container to act as your navigation when not at the top of the page. Now if you scroll back up, check the scroll location, and if the two locations of both containers overlap, start fading out the container you use when not at the top of the page. I do not think there is another solution. I might try and write a codepen on it now, I will edit my post if I had success. You could also try working it out with another div inside the actual header and z-index, though that might turn out really bad.
I have done my best to achieve what you want. Here is the CodePen.
I used two different divs, one called .dynamic-header and one normal header, and I've added a function to detect jQuery In-Viewport.
$.fn.isOnScreen = function(){
var element = this.get(0);
var bounds = element.getBoundingClientRect();
return bounds.top < window.innerHeight && bounds.bottom > 0;
}
I hope this fits your needs. Also, I changed some CSS around, using the Top-Property for the transition. You can outsource all of that into CSS classes and use them instead, but I thought this was the simplest solution for demonstration purposes. Is this what you want?
Edit 1: You named bartaile.com as an example. I took a look at the effect they create and recreated it. What you have to do is basically create a structure like this:
<div class="header-bg"></div>
<div class="header-content">
<ul>
<li>YOUR HEADER</li>
</ul>
</div>
I made another CodePen for this.
The header-bg has a height of 0. The header-content has a height of, lets say, 80px, and a background-color of transparent. Now do NOT check which direction is scrolled. The only important aspect for the effect is, how far are you from the top / is a specific element in viewport? I went for 400px from top. Now when that requirement is met, just fade in the header-bg. It will be inbetween the wrapper and the content, and will provide a background. Together with that, you may also change the color of the header-content, but I did not do that. It is what bartaile.com does, tho, so you might want to include it. Enjoy!
Edit 2: I've edited the CodePen according to your comment. See it in action here. This does the following: A header is there. When scrolling down, it'll disappear. On scroll up, it'll bring up a background, but when scrolling so that scrollTop < 400, the background will fade out. As of what I understood, this is what you want. It uses the structure I posted above.
I check out "bartaile.com" and I have to point out that what they use is a third party lib called 'fullpage'.If you wanna achieve that kind of effect, you should check out this lib fullpage.js. This is a simple and easy to use plugin to create fullscreen scrolling websites (also known as single page websites or onepage sites). It allows the creation of fullscreen scrolling websites, as well as adding some landscape sliders inside the sections of the site.
This plugin can handle "full screen scrolling" and also normal scrolling. You can achieve your effect with this much more easier

Categories

Resources