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

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'
})

Related

Is there any way in CSS to make other objects move when another object is scaled?

I have a row of elements, and they have a hover animation to make them scale up. Is it possible to make other images next to them change position on scale to prevent the overlap?
body {
background-color:#1a1a1a;
}
img{
max-width: 15%;
transition-duration: 0.5s;
transform-origin: center;
border-radius: 25px;
overflow: hidden;
margin: 50px;
}
img:hover{
cursor: pointer;
transform: scale(110%);
}
<img src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg">
<img src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg">
<img src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg">
and example of the effect I am looking for would be something that looks like this:
This will scale images up and down, dependent on classes. I've amended your css slightly for display purposes and add the JS code (left comments as clear as possible).
// define function to return all siblings of hovered element
function getAllSiblings(element, parent) {
const children = [...parent.children];
return children.filter((child) => child !== element);
}
// grab all img elements
const imgs = document.querySelectorAll('img');
imgs.forEach((i) => {
// define siblings using function above
const siblings = getAllSiblings(i, document.getElementById('parent'));
// *hover in*
i.addEventListener('mouseover', function () {
// add an active class when hovered (amended your css)
this.classList.add('active');
// add small class to all sibling elements
siblings.forEach((sibling) => {
sibling.classList.add('small');
});
});
// *hover out*
i.addEventListener('mouseleave', function () {
// remove active class and small classes so hovered element reverts to normal
this.classList.remove('active');
this.classList.contains('small') && this.classList.remove('small');
// remove class small on all siblings so that everything is reverted to initial display
siblings.forEach((sibling) => {
sibling.classList.remove('small');
});
});
});
body {
background-color: #1a1a1a;
/* added for display purposes */
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
/* added for getting parent element */
#parent {
margin: auto;
display: flex;
justify-content: center;
align-items: center;
gap: 2rem;
width: 100%;
}
img {
max-width: 15%;
transition-duration: 0.5s;
transform-origin: top;
transform-origin: left;
border-radius: 25px;
}
/* added for changing hover states */
img.active {
max-width: 17%;
cursor: pointer;
transform: scale(120%);
transform-origin: center;
}
img.small {
max-width: 17%;
transform: scale(80%);
transform-origin: center;
}
<div id="parent">
<img
src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg"
/>
<img
src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg"
/>
<img
src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg"
/>
</div>
Check this out (after hover, the shape is changing width & height):
const divs = document.querySelectorAll('div');
const reset = () => {
divs.forEach(div => div.classList.remove('active'))
}
divs.forEach(div => div.addEventListener('mouseover', () => {
reset();
div.classList.toggle('active');
}));
divs.forEach(div => div.addEventListener('mouseout', () => {
reset();
}))
section {
height: 150px;
width: 600px;
display: flex;
justify-content: space-between;
align-items: center;
border: 2px solid red;
}
div {
flex: 1;
height: 100px;
border: 2px solid black;
transition: flex .2s, transform .2s;
margin: 1em;
}
div.active {
transform: scaleY(1.5);
flex: 2;
}
<section>
<div></div>
<div></div>
<div></div>
<div></div>
</section>

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>

Having issues with vertical alignment (Flexbox) and center alignment

I'm using javascript to display dynamic text and image, but having trouble with formatting.
I'm using display: flex to put text and image next to each other, but am having trouble horizontally aligning them. Right now, it looks like:
But I'd like to horizontally align them so that it becomes:
I've tried the following, but this didn't work
#conA #container {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
Update:
Implementing the following code but NOT setting the height of #heroText and #images the same
#conA #container {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
does center text and images horizontally when both are present. However, once the images disappear, the text jumps. Here's how it's behaving https://imgur.com/a/7yYl8zO I'd like the text to not move when images disappear
Once I set the heights of #heroText and #images the same, it then turns to this:
I'm also looking to center the whole text+image in the parent div (#conA, which takes up full screen 100vh). I tried the following:
#conA {
position: relative;
}
#conA #container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
But it looks odd b/c text keeps moving/jumping depending on whether there's an image displayed.
So when there's no image, it looks like:
When when images appear, text moves to left so that the whole thing becomes centered:
How can I fix the position of text here? I'd like the whole thing is centered when there's an image. So when there's no image:
When there's an image:
html
<section id="conA">
<div id="container">
<div id="heroText">
<div id="text-fixed">I'm a fixed text</div>
<div id="text"></div>
</div>
<div id="images"></div>
</div>
</section>
css
#conA {
height: 100vh;
position: relative;
}
#conA #container {
margin: 0;
}
#conA #text {
display: initial;
border-right: 3px solid #56525E;
}
#heroText {
line-height: 1.7;
font-size: 30px;
width: 800px;
}
#conA #container {
margin: 0;
display: flex;
}
#heroText {
height: 400px;
}
#conA #images {
height: 400px;
}
#conA img
{
display:none;
height: 400px;
}
#conA img.invisible
{
visibility: hidden;
}
#conA img.show
{
display:inline;
}
#conA img.anim1
{
animation-duration: 2000ms;
}
#conA img.anim2
{
animation-duration: 2000ms;
}
#conA img.anim3
{
animation-duration: 2000ms;
}
.fadeIn
{
animation-name: fadeIn;
}
#keyframes fadeIn
{
0% {opacity: 0;}
100% {opacity: 1;}
}
.fadeOut
{
animation-name: fadeOut;
}
javascript code for dynamic display of text and image
// List of sentences
var _CONTENT = [ "I'm the first sentence.", "I'm the second sentence."
, "I'm the third sentence.", "I'm the fourth sentence." ];
var IMAGE_URLS = ['img/image1.png', 'img/image2.jpg', 'img/image3.png', 'img/image1.png','img/image2.png','img/image3.png', 'img/image4.png','img/image5.png'];
var IMAGES = jQuery.map(IMAGE_URLS, function (url, index){
var img = document.createElement('img');
img.setAttribute('src', url);
img.classList.add('anim'+((index%2)+1));
img.classList.add('fadeOut');
document.getElementById('images').appendChild(img);
return img;
});
// Current sentence being processed
var _PART = 0;
// Character number of the current sentence being processed
var _PART_INDEX = 0;
// Holds the handle returned from setInterval
var _INTERVAL_VAL;
// Element that holds the text
var _ELEMENT = document.querySelector("#text");
// Implements typing effect
function Type() {
var text = _CONTENT[_PART].substring(0, _PART_INDEX + 1);
_ELEMENT.innerHTML = text;
_PART_INDEX++;
// If full sentence has been displayed then start to delete the sentence after some time
if(text === _CONTENT[_PART]) {
var imgIndexBase = _PART*2;
IMAGES[imgIndexBase].classList.remove('fadeOut');
IMAGES[imgIndexBase+1].classList.remove('fadeOut');
setTimeout(function () { IMAGES[imgIndexBase].classList.add('fadeIn'); }, 0);
setTimeout(function () { IMAGES[imgIndexBase].classList.add('show'); }, 0);
setTimeout(function () { IMAGES[imgIndexBase].classList.add('fadeOut'); }, 2000);
setTimeout(function () { IMAGES[imgIndexBase].classList.remove('fadeOut'); }, 3000);
setTimeout(function () { IMAGES[imgIndexBase].classList.remove('show'); }, 3000);
setTimeout(function () { IMAGES[imgIndexBase + 1].classList.add('fadeIn'); }, 0);
setTimeout(function () { IMAGES[imgIndexBase + 1].classList.add('show'); }, 0);
setTimeout(function () { IMAGES[imgIndexBase + 1].classList.add('fadeOut'); }, 2000);
setTimeout(function () { IMAGES[imgIndexBase + 1].classList.remove('fadeOut'); }, 3000);
setTimeout(function () { IMAGES[imgIndexBase + 1].classList.remove('show'); }, 3000);
clearInterval(_INTERVAL_VAL);
setTimeout(function() {
_INTERVAL_VAL = setInterval(Delete, 50);
}, 4000);
}
}
// Implements deleting effect
function Delete() {
var text = _CONTENT[_PART].substring(0, _PART_INDEX - 1);
_ELEMENT.innerHTML = text;
_PART_INDEX--;
// If sentence has been deleted then start to display the next sentence
if(text === '') {
clearInterval(_INTERVAL_VAL);
// If last sentence then display the first one, else move to the next
if(_PART == (_CONTENT.length - 1))
_PART = 0;
else
_PART++;
_PART_INDEX = 0;
// Start to display the next sentence after some time
setTimeout(function() {
_INTERVAL_VAL = setInterval(Type, 100);
}, 500);
}
}
// Start the typing effect on load
_INTERVAL_VAL = setInterval(Type, 100);
See example below using flex CSS. First section with image, second section with no images in .images div.
There is a lot to explain with flex, but it is super powerful when it comes to dynamic layout. Hope this gets you on the right track.
Also you need to relax on your id attribute usage, valid html only allow single usage of an id attribute value. Use class attribute for multiple instances, and id for single usage instances.
id attribute value should only ever be used once, never multiple times.
BODY {
padding: 1rem;
margin: 0;
}
SECTION .container {
border: 1px black solid;
padding: 2rem;
display: flex;
align-items: center;
flex-wrap: wrap;
flex-direction: initial;
min-height: 100px;
justify-content: center;
margin-bottom: 1rem;
}
SECTION .container .hero-text {
width: 50%;
background: cyan;
}
SECTION .container .images {
width: 50%;
background: red;
}
SECTION .container .images IMG {
display: block;
width: 100%;
}
<section>
<div class="container">
<div class="hero-text">
<div class="text-fixed">I'm a fixed text</div>
<div class="text">And I am loving life :)</div>
</div>
<div class="images">
<img src="https://i.imgur.com/q5Y5RCH.png" alt="" />
</div>
</div>
</section>
<section>
<div class="container">
<div class="hero-text">
<div class="text-fixed">I'm a fixed text</div>
<div class="text">And I am loving life :)</div>
</div>
<div class="images">
<!-- no images -->
</div>
</div>
</section>

How can I place/drop an image every time you click the mouse button

How to make a div appear on click
You can achieve this by using event listeners on mouse click and appending images to the div element like below code snippet:
const addImageDiv = document.getElementsByClassName('add-image')[0];
addImageDiv.addEventListener('click', (event) => {
const elem = document.createElement("img");
addImageDiv.appendChild(elem);
elem.src = 'https://australiahouse.us/sticker-1.png';
elem.setAttribute('style', `left: ${event.clientX}px; top: ${event.clientY}px; width: 25vw;`);
});
.add-image {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
border: 1px solid lightgrey;
}
body img {
pointer-events: none;
position: absolute;
transform: translate(-50%,-50%) scale(.35);
}
<div class="add-image">
<span>some content</span>
</div>
EDIT:
It's a bit trickier to produce a random image of a small set of images, but the best practical way I suggest to create an array of images, then produce a random number and after that get the floor of random number and array length to produce a random index, and at last you can get a random image on each click. (keep in mind in this method, in a small set of images you have to try several times to get a new image on click!)
const addImageDiv = document.getElementsByClassName('add-image')[0];
const imagesArray = ['https://australiahouse.us/sticker-1.png', 'https://australiahouse.us/sticker-2.png', 'https://australiahouse.us/sticker-3.png'];
const imagesArrayLength = imagesArray.length;
addImageDiv.addEventListener('click', (event) => {
const randomNumber = Math.random();
const randomIndex = Math.floor(randomNumber * imagesArrayLength);
const elem = document.createElement("img");
addImageDiv.appendChild(elem);
elem.src = imagesArray[randomIndex];
elem.setAttribute('style', `left: ${event.clientX}px; top: ${event.clientY}px; width: 25vw;`);
});
.add-image {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
border: 1px solid lightgrey;
}
body img {
pointer-events: none;
position: absolute;
transform: translate(-50%,-50%) scale(.35);
}
<div class="add-image">
<span>some content</span>
</div>

WinJS.BackButton sizes

I have this html tag which reffers to the backButton provided by the WinJS library:
<button data-win-control="WinJS.UI.BackButton"></button>
I want to change its size. How can I do that? I tried using CSS by adding the ID "backButton" and font-size OR width/height properties, like this:
#backButton {
font-size: small;
}
#backButton {
height: 30px;
width: 30px;
}
EDIT: Code added and a picture of what happens when changing the values of width/height of the button.
// For an introduction to the Page Control template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232511
(function () {
"use strict";
WinJS.UI.Pages.define("/pages/anime/anime.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
// TODO: Initialize the page here.
this.renderAnimeInfo(Identifier.file);
},
unload: function () {
// TODO: Respond to navigations away from this page.
},
updateLayout: function (element) {
/// <param name="element" domElement="true" />
// TODO: Respond to changes in layout.
},
renderAnimeInfo: function (id) {
// Path for the anime data.
var path = "data/animes.json";
// Retrieve the .json.
WinJS.xhr({ url: path }).then(
function (response) {
var json = JSON.parse(response.responseText);
for (var i = 0; i < json.length; i++) {
if (json[i].file == id) {
var animeData = json[i];
break;
}
}
},
function (error) {},
function (progress) {}
);
},
});
})();
.right {
float: right;
}
.left {
float: left;
}
.active {
background-color: blue;
}
#animeDetails {
background: red;
height: 100%;
width: 300px;
float: left;
}
#animeInfo {
display: -ms-grid;
height: 100%;
width: calc(100% - 300px);
float: right;
}
#navbar {
-ms-grid-row: 1;
padding: 20px 25px;
}
#navbar .right button {
margin-right: 4px;
}
#navbar input {
width: 150px;
}
#details {
-ms-grid-row: 2;
padding: 0 25px;
text-align: justify;
white-space: pre-line;
}
#details h3 {
width: 100%;
padding: 5px 0;
border-bottom: 1px solid #bebebe;
margin-bottom: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>anime</title>
<link href="anime.css" rel="stylesheet" />
<script src="anime.js"></script>
</head>
<body>
<div id="animeDetails"></div>
<div id="animeInfo">
<div id="navbar">
<div class="left">
<button class="left" data-win-control="WinJS.UI.BackButton"></button>
<h3>Back</h3>
</div>
<div class="right">
<button type="button" class="active">Details</button>
<button type="button">Episodes</button>
<button type="button">Characters</button>
<button type="button">Staff</button>
<input type="search" placeholder="Search" />
</div>
</div>
<div id="details">
<div id="synopsis">
<h3>Synopsis</h3>
<span>
</span>
</div>
</div>
</div>
</body>
When using the width/height properties, what happens is that the button does resize to the specified value, but the icon inside (which is not a background) doesn't. http://i.imgur.com/lMqmL0G.png
Possibly you have to set display: inline-block to button because the width of an element with display: inline (the default for buttons) is exactly the same as its content because it only takes up the space needed to display its contents so try with:
With id selector
#backButton {
height: 30px;
width: 30px;
display: inline-block;
}
<button id="backButton" data-win-control="WinJS.UI.BackButton"></button>
With style inline
<button data-win-control="WinJS.UI.BackButton" style="width: 30px; height: 30px; display: inline-block"></button>
Try to set the styles to child element .win-back
#backButton .win-back{
/*---styles---*/
}
You haven't given your button an ID. The CSS does not know what tag to link to.
<button id="backButton" data-win-control="WinJS.UI.BackButton"></button>
edit: you may find the following reference useful CSS Selectors