Toggle 2 classes via Angular - html

I'm trying to toggle between 2 classes via Angular's ng-Click & ng-Class selectors.
Basically, I want to click 1 line of text, or a button, or whatever, and change the z-index of an element by switching the styles using ng-Click.
I've tried multiple solutions but virtually none of them are working. I'm not entirely sure whether its something I'm doing wrong with Angular, or maybe my CSS?
Angular:
app.controller("naviController",function($scope){
"use strict";
$scope.toggles = [{ state: true }, { state: false }, { state: true }];
});
HTML:
<div ng-controller="naviController">
<div class="nav-container">
<div class="nav-element-block ne-1" ng-click="toggle.state = !toggle.state">Index</div>
<div class="nav-element-block ne-2" ng-click="toggle.state = !toggle.state">About</div>
<div class="nav-element-block ne-3" ng-click="toggle.state = !toggle.state">Dev</div>
</div>
<div id="index-container" ng-class="{'about-container-active' : toggle.state}">Index Container</div>
<div id="about-container" ng-class="{'about-container-active' : toggle.state}">About Container</div>
<div id="dev-container" ng-class="{'about-container-active' : toggle.state}">Dev Container</div>
</div>
CSS:
#index-container {
display: table-cell;
width: 100vw;
height: 90vh;
padding-top: 10vh;
background-color: #FFF;
overflow: hidden;
animation-name: indexcell;
animation-duration: 500ms;
box-sizing: border-box;
padding-left: 5%;
padding-right: 5%;
z-index: 5;
position: fixed;
}
.index-container-active {
z-index: 999;
}
#about-container {
display: table-cell;
width: 100vw;
height: 90vh;
padding-top: 10vh;
background-color: #f1ffff;
overflow: hidden;
animation-name: indexcell;
animation-duration: 500ms;
padding-left: 5%;
padding-right: 5%;
z-index: 4;
position: fixed;
}
.about-container-active {
z-index: 999;
}
#dev-container {
display: table-cell;
width: 100vw;
height: 90vh;
padding-top: 10vh;
background-color: #f1fff1;
overflow: hidden;
animation-name: indexcell;
animation-duration: 500ms;
padding-left: 5%;
padding-right: 5%;
z-index: 3;
position: fixed;
}
.dev-container-active {
z-index: 999;
}
What I'm actually trying to do: I have 5 divs whose class I'd like to change with, lets say 5 links and when I click one of the links I'd like to switch that related class on, and the others off. Like:
Index = Class-1-Active
About = Class-2-Inactive
Dev = Class-3-Inactive
Contact = Class-4-Inactive
Portfolio = Class-5-Inactive
Lets say we click on 'Dev', this then switches class 3 into an active state, by switching classes, and then switches all the other classes to an inactive state. Like so:
Index = Class-1-Inactive
About = Class-2-Inactive
Dev = Class-3-Active
Contact = Class-4-Inactive
Portfolio = Class-5-Inactive

There are multiple errors in your code, as the guys pointed out you're having a typo, but just that won't resolve your issues.
I'd go from start, as everything in angularjs there are many ways to do same thing. This is just one simple proposal, first your html would require ng-click to go in some kind of function in which you will change state of the active:
<button class="nav-element-block ne-1" ng-click="toggleState('index')">Index</button>
<button class="nav-element-block ne-2" ng-click="toggleState('about')">About</button>
<button class="nav-element-block ne-3" ng-click="toggleState('dev')">Dev</button>
next you need to figure out which state is which, so fix your object of states to something like this:
let toggles = [{
name: 'dev',
state: false
}, {
name: 'about',
state: false
}, {
name: 'index',
state: true
}];
and you need to create that function on $scope that you are calling on that div/button click. It will set state to false to all other objects except one named state:
$scope.toggleState = function(state) {
toggles = toggles.map(val => {
if (val.name === state) {
val.state = true;
} else {
val.state = false;
}
return val;
});
};
Then you need to assign function that will check on your divs to trigger a class by a certain div name:
<div id="index-container" ng-class="{'about-container-active' : checkActiveState('index')}">Index Container</div>
<div id="about-container" ng-class="{'about-container-active' : checkActiveState('about')}">About Container</div>
<div id="dev-container" ng-class="{'about-container-active' : checkActiveState('dev')}">Dev Container</div>
And in the end you need a function that will search that div name in your toggles array and return .state of that object and that will actually trigger your class:
$scope.checkActiveState = function(state) {
return toggles.find(x => x.name === state).state;
};
And voila, that's it, if you have any issues let me know, here's fiddle so you can play around with it: https://jsfiddle.net/pegla/mvprL5ap/1/

Related

Svelte transition seems to finish too soon

I'm trying to build a simple transition in Svelte where I have cards that animate in on page load. I've followed this answer to get it to fire correctly onMount, so that has been ok. However, the transition itself seems to "jump" to the end too quickly, and skips the last few frames.
GIF of problem running on localhost.
Oddly enough, when I copy and paste the same code into the REPL, the visual bug seems to be fixed. I've even downloaded the REPL and run locally, and the bug still appears.
Here is the code.
<script>
import { fly } from 'svelte/transition';
import { onMount } from 'svelte';
const contents = [
{
id: 1,
},
{
id: 2,
},
{
id: 3,
},
];
let ready = false;
onMount(() => (ready = true));
</script>
<main>
<div class="topBar" />
<div class="container">
{#if ready}
{#each contents as content, i}
<div
class="transCard"
transition:fly={{ y: 80, duration: 1000, delay: i * 200 }}
/>
{/each}
{/if}
</div>
</main>
<style>
main {
background: white;
width: 100vw;
height: 100vh;
overflow-y: auto;
overflow-x: hidden;
}
.container {
display: flex;
flex-direction: column;
gap: 16px;
padding: 16px;
overflow: hidden;
margin-top: 80px;
}
.topBar {
width: 100vw;
height: 80px;
background: black;
position: fixed;
top: 0;
left: 0;
z-index: 9;
}
.transCard {
width: 100%;
height: 200px;
background: gray;
}
</style>
Found the answer myself! Not sure why it fixed it, but for me changing transition to just in seems to have cured the visual bug.

OnMouseOver change the content of a (pop-up) window

I'm a visual artist with not that many coding skills. I know some HTML and some CSS but that's it. I like to create a webpage that does the following:
On the left, there is an image with lines. When hovering over a line the window on the right shows an image, movie, or plays a sound. Hovering over the next line triggers another image, movie, or sound.
Anyone can point me in the correct direction? I made a gif to show how it should work...
Simple solution:
Select HTML elements which we want to hover over (left, middle, right), and HTML elements which contain our images/videos/audio etc. (img1, sound, img2)
For every element you want to hover over, you need to add event listener (addEventListener), so you can manipulate your HTML/CSS code with JavaScript.
2.2 Inside each event listener you add or remove class: none, which has CSS value of display: none (this means element won't be shown), depending on what your goal is.
To make images disappear when we don't hover our cursor over the element, we need to again add event listener to elements which already have on mouseover event listener. In this case we use mouseover or blur. When cursor isn't on the element, JavaScript will automatically add none class to it.
const left = document.querySelector('.left-line');
const middle = document.querySelector('.middle-line');
const right = document.querySelector('.right-line');
const img1 = document.querySelector('.image-1');
const sound = document.querySelector('.sound');
const img2 = document.querySelector('.image-2');
left.addEventListener('mouseover', () => {
img1.classList.remove('none');
img2.classList.add('none');
sound.classList.add('none');
});
middle.addEventListener('mouseover', () => {
img1.classList.add('none');
img2.classList.remove('none');
sound.classList.add('none');
});
right.addEventListener('mouseover', () => {
img1.classList.add('none');
img2.classList.add('none');
sound.classList.remove('none');
});
left.addEventListener('mouseout',() => addNoneClass());
middle.addEventListener('mouseout', () => addNoneClass());
right.addEventListener('mouseout', () => addNoneClass());
function addNoneClass() {
img1.classList.add('none');
img2.classList.add('none');
sound.classList.add('none');
}
* {
padding: 0;
margin: 0;
width: 100vw;
height: 100vh;
}
main {
display: flex;
width: 100%;
height: 100%;
}
section.left {
width: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.line-container {
width: 150px;
height: 150px;
display: flex;
align-items: center;
border: 2px solid black;
}
.left-line, .middle-line, .right-line {
width: 50px;
height: 90%;
margin: 0 10px;
}
.left-line { background-color: green; }
.middle-line { background-color: red; }
.right-line { background-color: blue; }
section.right {
width: 50%;
display:flex;
align-items: center;
justify-content: center;
}
.box {
width: 200px;
height: 200px;
border: 2px solid black;
}
img {
width: 200px;
height: 200px;
}
.none {
display: none;
}
<main>
<section class="left">
<div class="line-container">
<div class="left-line">
</div>
<div class="middle-line">
</div>
<div class="right-line">
</div>
</div>
</section>
<section class="right">
<div class="box">
<div class="image-1 none">
<img src="https://play-lh.googleusercontent.com/aFWiT2lTa9CYBpyPjfgfNHd0r5puwKRGj2rHpdPTNrz2N9LXgN_MbLjePd1OTc0E8Rl1" alt="image-1">
</div>
<div class="sound none">
<img src="https://sm.pcmag.com/pcmag_uk/review/g/google-pho/google-photos_z68u.jpg" alt="sound">
</div>
<div class="image-2 none">
<img src="https://cdn.vox-cdn.com/thumbor/I2PsqRLIaCB1iYUuSptrrR5M8oQ=/0x0:2040x1360/1200x800/filters:focal(857x517:1183x843)/cdn.vox-cdn.com/uploads/chorus_image/image/68829483/acastro_210104_1777_google_0001.0.jpg" alt="image-2">
</div>
</div>
</section>
</main>
You can do this by the following code example.
HTML:
<div class="lines">
<span id='line-1'>|</span>
<span id='line-2'>|</span>
<span id='line-3'>|</span>
</div>
<div id='output'></div>
JS
const line1 = document.getElementById('line-1')
const line2 = document.getElementById('line-2')
const line3 = document.getElementById('line-3')
const output = document.getElementById('output')
line1.addEventListener('mouseover', () => {
output.innerHTML = 'Content One'
})
line2.addEventListener('mouseover', () => {
output.innerHTML = 'Content Two'
})
line3.addEventListener('mouseover', () => {
output.innerHTML = 'Content Three'
})

Addding elements to centered flexbox from left to right

I have a flex box to center 3 divs in the screen. all the three are wrapped around a flex container that has justify-content: center which centers them in the screen. However, since I am using animation and each div is being added one after another, the first div gets added at the center instead of the beginning, the second gets added such that both of the first and second are centered, and when the third is added, all of them are aligned such that the second div is exactly in the middle of the screen. I want to change that such that each div gets added in-place from left to right while all are centered in the screen.
React code:
function foo() {
const [items, set] = React.useState([]);
const transitions = useTransition(items, (item) => item.key, {
from: { transform: "translate3d(0,-40px,0)" },
enter: { transform: "translate3d(0,0px,0)" },
leave: { transform: "translate3d(0,-40px,0)" },
});
React.useEffect(() => {
for (let i = 0; i < rows.length; i++) {
setTimeout(() => {
set((items) => {
const newItems = [...items];
newItems.push({ key: i, code: rows[i] });
return newItems;
});
}, 1000 * i);
}
}, []);
return (
<center>
<div class="flex-container">
{transitions.map(({ item, props, key }) => {
return (
<animated.div key={key} style={props} class="flex-item">
{item.code}
</animated.div>
);
})}
</div>
</center>
);
}
Styling:
.flex-container {
height: 50vh;
display: flex;
justify-content: center;
img{
width: 20%;
text-align: center;
}
}
.flex-item {
flex-basis: 14%;
align-self: center;
margin: 12px;
h4{
font-family: Lato;
font-weight:700;
color: white;
}
p{
color: white;
font-family: Lato;
}
}
Changing center to flex-start shifts everything to the beginning:
Adding fixed width doesn't work as well:
To solve your problem, simply align the cards the way you want them to look after they move, then apply the following CSS:
.card {
position: relative;
top: -100px;
}
If -100px is not enough, try -200px. The goal is that the cards will be off-screen at the top. Upon whatever action you desire, whether it be clicking a button like in my snippet below, or perhaps on page load, change the "top" property to 0, and it will place the card where it belongs in the normal flow of the page.
I additionally use the setTimeout function to delay each subsequent card, and the transition property to animate the movement smoothly since it seems like that is your desired goal.
const left = document.getElementById("left");
const center = document.getElementById("center");
const right = document.getElementById("right");
function foo() {
left.style.top = "0";
setTimeout(function() {
center.style.top = "0";
setTimeout(function() {
right.style.top = "0";
}, 500)
}, 500)
}
#container {
display: flex;
justify-content: center;
}
#container>* {
width: 100px;
height: 50px;
background: red;
margin: 0 0.5em;
position: relative;
top: -100px;
transition: top 1s ease-in-out;
}
button {
margin: auto;
}
<div id="container">
<div id="left"></div>
<div id="center"></div>
<div id="right"></div>
</div>
<button onclick="foo()" id="click-me">Click me!</button>

2 blocks with overflow:scroll inside each other

I have recreated my problem in sandbox: https://codesandbox.io/s/vibrant-microservice-4rplf
I'm using custom modal and custom select. Right now I have a problem ,when I open select, it unfolds inside my modal and scroll shows up.
I want to display select over my modal , like in the picture below. I achieved this result by removing overflow:auto . But I need to leave this property in case modal gets bigger. Does anyone have an idea why this happening and how to fix it ?
.modal-block {
overflow-y: scroll;
width: 60% !important;
max-height: 300px;
margin-top: 100px;
background: #fff;
border-radius: 4px;
}
Change CSS modal.scss
.modal-block {
width: 60% !important;
margin-top: 100px;
background: #fff;
border-radius: 4px;
position: relative;
}
.modal-body {
padding: 24px;
font-size: 14px;
line-height: 1.5;
word-wrap: break-word;
max-height: 400px;
overflow-y: auto;
.pay-form {
margin: 0;
}
https://codesandbox.io/s/mystifying-lovelace-52mlg?fontsize=14&hidenavigation=1&theme=dark
You can not do this with css because child elements won't come out of the parent element even if you set the z-index to a higher number.
My solution is to use another modal inside the original modal. You can put your select element in the inner modal and in the outer modal just give a button at the bottom that looks like the select element and opens the inner modal on click.
You have to maintain separate state property for the inner modal.
Something like this:
export default class Main extends Component {
state = {
isOpen: true,
isSelectOpen: true
};
toggleCheckbox(key) {
console.log(key);
this.setState({ isChecked: key });
}
render() {
console.log(this.state.isChecked);
return (
<span className='group-block-wrapper'>
<Modal
title='Modal title'
isOpen={this.state.isOpen}
onOk={() => {}}
onClose={() => console.log("yoy")}
okText='pay'
>
he following is a guest post by Agop Shirinian.........
<Modal
isOpen={this.state.isSelectOpen}
onOk={() => {}}
onClose={() => console.log("yoy")}
okText='Ok'
>
<Select
title='select'
options={selectOptions}
onchange={idx => console.log(idx)}
/>
</Modal>
</Modal>
</span>
);
}
}

how to disable dragend animation in html5

I created a draggable element by setting its draggable attribute. When I drop the element, there is an animation of the element snapping back to its origin position:
How can the snap-back animation be disabled? I tried calling preventDefault() on the dragend event, but it had no effect on the animation.
The following snippet shows the basics:
document.getElementById('test').addEventListener(
'dragend', evt => {
evt.preventDefault();
}
);
#container {
border: 1px solid black;
min-width: 300px;
min-height: 200px;
position: relative;
}
#test {
width: 50px;
height: 50px;
background-color: red;
position: absolute;
top: 25px;
left: 40px;
}
<div id="container">
<div id="test" draggable='true'></div>
</div>
Not every browser will show the dragged #test jumping back to the original position.
In order to prevent the animation, you need the drop event to fire. For the drop event to fire, you need to call preventDefault() in the handler for dragover.
document.addEventListener('dragover', function(e) { e.preventDefault() })
Example in MDN docs shows the same thing: https://developer.mozilla.org/en-US/docs/Web/Events/drop#Example
An old blog post describing the quirks of HTML5 Drag and Drop API: https://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html
As was said earlier, you need to explicitly describe onDragOver handler on the parent's container (where you will drop your draggable element) and put .preventDefault() on event to prevent this animation.
Here is a simple React code example for better understanding of this mechanic (you can position the box inside the container by dragging it):
App.jsx
import './App.css'
const App = () => {
function handleDragOver(e) {
e.preventDefault()
}
function handleDrop(e) {
let box = document.getElementById('box')
if (box) {
box.style.top = e.clientY + 'px'
box.style.left = e.clientX + 'px'
}
}
return (
<div className="container" onDragOver={handleDragOver} onDrop={handleDrop}>
<div id="box" draggable></div>
</div>
)
}
export default App
App.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100vw;
height: 100vh;
position: relative;
}
#box {
width: 100px;
height: 100px;
background-color: lightgreen;
position: absolute;
}