How to change the property of pictures when text is hovered? - javascript

I would like to make changes to some pictures of my website when certain text is hovered. Specifically, when h6 inside section, inside a parent row class is hovered, I want the images inside a, inside section, inside parent with row class to get greyscaled.
I read in other threads that you could affect siblings and parents in different ways and I tried the suggested approaches but none of them worked (it may be because I am not fully understanding how it is done).
Here is some pseudo-code that explains what I want to do. Of course, it is not working because such nesting is impossible.
.row > section > h6:hover {
.row > section > a > img {
filter: grayscale(100%);
}
}
I would like to ask if what I am trying to do is possible and if so, how? A solution using JavaScript would also be accepted, but preferably only using CSS if possible.
Edit: Here is a quick fiddle: https://jsfiddle.net/pjo4yxLk/2/
I want that when I hover Field1 and Field 2, both pictures to get greyscaled.

For a pure CSS solution it can be done for each image by switching the place of the h6 and a in the html and putting them back in place visualy with display: flex; flex-direction: row-reverse;.
This way your code work.
section {
display: flex;
flex-direction: column-reverse;
}
.row > section > h6:hover + a > img {
filter: grayscale(100%);
}
.row {
/* just to align them in a row */
display: flex;
}
h6 {
font-size: 16px;
}
section {
display: flex;
flex-direction: column-reverse;
}
.row>section>h6:hover+a>img {
filter: grayscale(100%);
}
<div class="row container">
<section>
<h6>
Field 1
</h6>
<a href="https://www.google.com/">
<img src="https://helpx.adobe.com/content/dam/help/en/stock/how-to/visual-reverse-image-search/jcr_content/main-pars/image/visual-reverse-image-search-v2_intro.jpg" style="width: 150px;">
</a>
</section>
<section>
<h6>
Field 2
</h6>
<a href="https://www.google.com/">
<img src="https://helpx.adobe.com/content/dam/help/en/stock/how-to/visual-reverse-image-search/jcr_content/main-pars/image/visual-reverse-image-search-v2_intro.jpg" style="width: 150px;">
</a>
</section>
</div>
But if you want both images to get grayscaled when one h6 is hovered then I think you will need JS.
CSS
.row {
display: flex;
}
.grayScaler {
filter: grayscale(100%);
}
JS
var theH6s = document.querySelectorAll(".row > section > h6");
var theImages = document.querySelectorAll("section > a > img");
function grayScaler () {
for(let i = 0; i < theImages.length ; i++) {
theImages[i].classList.toggle("grayScaler");
}
}
for(let i = 0; i < theH6s.length ; i++) {
theH6s[i].addEventListener("mouseenter",grayScaler);
theH6s[i].addEventListener("mouseleave",grayScaler);
}
var theH6s = document.querySelectorAll(".row > section > h6");
var theImages = document.querySelectorAll("section > a > img");
function grayScaler() {
for (let i = 0; i < theImages.length; i++) {
theImages[i].classList.toggle("grayScaler");
}
}
for (let i = 0; i < theH6s.length; i++) {
theH6s[i].addEventListener("mouseenter", grayScaler);
theH6s[i].addEventListener("mouseleave", grayScaler);
}
h6 {
font-size: 20px;
}
.row {
display: flex;
}
.grayScaler {
filter: grayscale(100%);
}
<!--
Bootstrap docs: https://getbootstrap.com/docs
-->
<div class="row container">
<section>
<a href="https://www.google.com/">
<img src="https://helpx.adobe.com/content/dam/help/en/stock/how-to/visual-reverse-image-search/jcr_content/main-pars/image/visual-reverse-image-search-v2_intro.jpg" style="width: 150px;">
</a>
<h6>
Field 1
</h6>
</section>
<section>
<a href="https://www.google.com/">
<img src="https://helpx.adobe.com/content/dam/help/en/stock/how-to/visual-reverse-image-search/jcr_content/main-pars/image/visual-reverse-image-search-v2_intro.jpg" style="width: 150px;">
</a>
<h6>
Field 2
</h6>
</section>
</div>

That's not the proper syntax. If H6 and A tag are inside section tag, it would be like this:
.row > section > h6:hover + a > img { filter: grayscale(100%); }
Since A tag is H6 tag's next sibling, you have to use + selector to call it.

You cannot do this unless your :hover element comes before your modified element.
It can be achieved with pure CSS if you use CSS to position the text below the image but I wouldn't advise it. You can alternatively use javascript to achieve this.
Refer to this answer: On a CSS hover event, can I change another div's styling?
I have attached code to show you what I mean
.row > section > h6:hover + a > img{
filter: grayscale(100%);
}
<!--
Bootstrap docs: https://getbootstrap.com/docs
-->
<div class="row container">
<section>
<h6>
Field 1
</h6>
<a href="https://www.google.com/">
<img src="https://helpx.adobe.com/content/dam/help/en/stock/how-to/visual-reverse-image-search/jcr_content/main-pars/image/visual-reverse-image-search-v2_intro.jpg" style="width: 150px;">
</a>
</section>
<section>
<a href="https://www.google.com/">
<img src="https://helpx.adobe.com/content/dam/help/en/stock/how-to/visual-reverse-image-search/jcr_content/main-pars/image/visual-reverse-image-search-v2_intro.jpg" style="width: 150px;">
</a>
<h6>
Field 2
</h6>
</section>
</div>

Related

Gallery with bigger previews "in place"

My aim is to do a thumbnail gallery which will enlarge thumbnail in a new row after the thumbnail has been clicked [Edited for clarity]:
I am not sure how to do it properly (if there is a proper way). How would you conceptually approach this task?
Flexbox seems to be nice for the first part, but then add cell on calculated position by JS OR split the flexbox into two? And in every case redo everything completely in there was a resize?
A help would be also to know how this kind of gallery is called, because I was unable to find any info on Google. Thank you!
This is an example showing how a container could use display:flex; to show a number of div.item as pictures in a gallery.
Each of such div.item gets attached an handler for the click event, that will clone, populate and attach to dom the template defined to represent a preview.
The preview will show a bigger picture of the thumbnail clicked and some further details that the demo just limits to the item index number. Such bigger picture must be defined in the attribute data-original-image-url of the img thumbnail.
I was inspired to this question Gallery with bigger previews "in place" to craft the trick needed to determine the last item of a given row in a flex container.
Consider that the pictures url are fake here so the demo won't show any picture but just broken urls. I faked the size of items setting a arbitrary different width for each of them and setting the height fixed in a css class.
//Add click event handler to every div.item in any .gallery
let items = document.querySelectorAll('.gallery > div.item');
for(let item of items){
item.addEventListener('click', onItemClick);
}
/*
When an item gets clicked,
It shows a preview, bound to the item clicked, on the next line
*/
function onItemClick(event){
//the clicked item
//(currentTarget retrieves the item that had the listener not the actual element clicked)
//so in this case it will be always the div.item (never the picture itself)
clickedItem = event.currentTarget;
//determines the index (1 based) of the clicked item relative to its container
const itemIndex
= Array.from(clickedItem.parentElement.querySelectorAll('.item')).indexOf(clickedItem) + 1;
//removes all .preview elements inside the parent of the clicked item
clickedItem.parentElement.querySelectorAll('.preview').forEach( (o, i) => {
o.remove();
});
//retrieves the url for the bigger picture of the item clicked
let urlBiggerImage = clickedItem.querySelector('img').getAttribute('data-original-image-url');
//retrieves the last item in the row where the item clicked lays
let lastItemOfRow = getLastItemOfRow(clickedItem);
//retrieves the html template for the preview
const template = document.getElementById("template_preview");
//clones the template to prepare the node as a concrete preview for the current item
const preview = template.content.cloneNode(true);
//sets the img src of the preview using the value of this item.data[original-image-url]
preview.querySelector('img').src = urlBiggerImage;
//sets the description of the preview
preview.querySelector('.col:nth-child(2) p').innerText = `You selected the item n.${itemIndex}`;
//appends the preview item after the last item in the row where item clicked lays
lastItemOfRow.after( preview );
}
/*
Retrieves the last item in the row (of the flexbox container)
given an item determining the row to examine
Inspired by:
https://stackoverflow.com/questions/72096795/gallery-with-bigger-previews-in-place/72096982
*/
const getLastItemOfRow = (item) => {
const grid = item.parentElement;
const gridItems = Array.from(grid.querySelectorAll('.item'));
const itemIndex = gridItems.indexOf(item);
const baseOffset = item.offsetTop;
let breakIndex = gridItems.findIndex(item => item.offsetTop > baseOffset) -1;
breakIndex = (breakIndex < 0) ? itemIndex : breakIndex;
return gridItems[breakIndex];
}
.gallery{
display: flex;
flex-wrap: wrap;
gap: 10px 10px;
padding: 10px;
border: solid 1px gray;
/*Here you can define an arbitrary width for the container*/
width: 430px;
}
.item{
display: block;
height: 50px;
background: red;
color: white;
font-weight: 700;
cursor: pointer;
}
.item > img{
height: 50px;
}
.preview{
border: solid 1px black;
flex: 0 0 100%;
}
.preview > .col{
display: inline-block;
padding: 5px;
vertical-align: middle;
}
.bigger {
width: 200px;
height: 100px;
}
<template id="template_preview">
<div class="preview">
<div class="col">
<img class="bigger" src=""/>
</div>
<div class="col">
<p>You selected the picture n:</p>
</div>
</div>
</template>
<!-- You can have many .gallery container -->
<div class="gallery">
<!-- Each .item will count as an item with preview -->
<div class="item">
<img src="/img/1.jpg" title="1" style="width: 100px;" data-original-image-url="/img/bigger/1.jpg"/>
</div>
<div class="item">
<img src="/img/2.jpg" title="2" style="width: 70px;" data-original-image-url="/img/bigger/2.jpg"/>
</div>
<div class="item">
<img src="/img/3.jpg" title="3" style="width: 180px;" data-original-image-url="/img/bigger/3.jpg"/>
</div>
<div class="item">
<img src="/img/4.jpg" title="4" style="width: 220px;" data-original-image-url="/img/bigger/4.jpg"/>
</div>
<div class="item">
<img src="/img/5.jpg" title="5" style="width: 40px;" data-original-image-url="/img/bigger/5.jpg"/>
</div>
<div class="item">
<img src="/img/6.jpg" title="6" style="width: 80px;" data-original-image-url="/img/bigger/6.jpg"/>
</div>
<div class="item">
<img src="/img/7.jpg" title="7" style="width: 50px;" data-original-image-url="/img/bigger/7.jpg"/>
</div>
<div class="item">
<img src="/img/8.jpg" title="8" style="width: 50px;" data-original-image-url="/img/bigger/8.jpg"/>
</div>
<div class="item">
<img src="/img/9.jpg" title="9" style="width: 50px;" data-original-image-url="/img/bigger/9.jpg"/>
</div>
<div class="item">
<img src="/img/10.jpg" title="10" style="width: 50px;" data-original-image-url="/img/bigger/10.jpg"/>
</div>
<div class="item">
<img src="/img/11.jpg" title="11" style="width: 50px;" data-original-image-url="/img/bigger/11.jpg"/>
</div>
<div class="item">
<img src="/img/12.jpg" title="12" style="width: 50px;" data-original-image-url="/img/bigger/12.jpg"/>
</div>
<div class="item">
<img src="/img/13.jpg" title="13" style="width: 80px;" data-original-image-url="/img/bigger/13.jpg"/>
</div>
<div class="item">
<img src="/img/14.jpg" title="14" style="width: 150px;" data-original-image-url="/img/bigger/14.jpg"/>
</div>
</div>

Sort div element using jQuery?

i have the following html structure:
<div id='main'>
<div id='612'>
</div>
...
<div id='1'>
</div>
</div>
As you can see i have several div going in a decreasing order and i wuold like to make a button that activate a jQuery script that can sort those div in both ways (decreasing and increasing).
I already created the button and linked it to the script but i can't find a way to sort the divs. Is possible?
Edit:
Posted the entire code on pastebin:
https://pastebin.com/DZWdNMZk
Edit:
Posted the entire code on Github if it any help:
https://github.com/mattiac02/divs
This is one option. Setting the display of the parent to flex, then using js to set the order property of the children. Hopefully the demonstration helps!
document.querySelector("#orderEm")
.addEventListener("click", () => {
document.querySelectorAll("div > div")
.forEach(div => {
div.style.order = div.id;
});
});
document.querySelector("#reverse")
.addEventListener("click", () => {
document.querySelector("#container")
.classList.toggle("reverse");
});
#container {
display: flex;
justify-content: space-around;
}
#container.reverse {
flex-direction: row-reverse;
}
div > div {
height: 50px;
width: 50px;
font-size: 15pt;
border: 1px solid black;
margin: 1em;
display: flex;
justify-content: center;
align-items: center;
}
<div id="container" data-sorted="unsorted">
<div id="2">2</div>
<div id="3">3</div>
<div id="1">1</div>
</div>
<button id="orderEm">Order 'Em!</button>
<button id="reverse">Reverse 'Em!</button>
One of of doing this is to get the elements into an array and sort the array and re-append them to the main div:
$('#btnAsc').click(function() {
//gets all div children of the main div, this returns a jQuery array with the elements
var divs = $('#main div');
//sorts the divs based on the id attribute
var ordered = divs.sort(function(a, b) {
return $(a).attr('id') - $(b).attr('id');
});
//empty the main div and re-append the ordered divs
$('#main').empty().append(ordered)
});
$('#btnDesc').click(function(){
var divs = $('#main div');
var ordered = divs.sort(function(a, b) {
return $(b).attr('id') - $(a).attr('id');
});
$('#main').empty().append(ordered)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='main'>
<div id='612'>
612
</div>
<div id='1'>
1
</div>
<div id='2'>
2
</div>
<div id='3'>
3
</div>
<div id='5'>
5
</div>
</div>
<input type="button" id="btnAsc" value="Asc">
<input type="button" id="btnDesc" value="Desc">

Text hover to image with multiple columns and fixed image in center- mouseover

I've been struggling with a problem that I know the right person can easily fix in one shot.
I need to create something similar to this site:
http://www.arcadiacontemporary.com/artists/index.php
However I need multiple artist columns/tables like this site:
https://collinsgalleries.com/ARTISTS5.html
I would like the mouseover to work the same however when it grabs the image, I would rather be able to use external files and URLs vs internal.
Both site uses jquery and bootstrap, which I need to integrate into a Wordpress website. I do not know jquery or bootstrap js so I'm trying my best to create it without.
The best I've got so far for code is:
HTML
<!DOCTYPE html>
<html>
<head>
<style>
table, th, td {
border: 0px solid black;
padding: 5px;
}
table {
border-spacing: 15px;
]
</style>
</head>
<body>
<a href="#"><div class="hover-img">
<table style="width: 100%"></table>
<th>Artist Name</th>
</tr>
<span><img src="https://collinsgalleries.com/images/Artist-Page-Monks.jpg" alt="image" height="fixed" /> </span>
</div></a>
<a href="#"><div class="hover-img">
<tr>
<th>Artist Name</td>
<span><img src="https://collinsgalleries.com/images/Paul_Oxborough_Old_Friends.jpg" alt="image" height="fixed" /> </span>
</div></a>
<a href="#"><div class="hover-img">
<td>Artist Name</td>
<span><img src="https://collinsgalleries.com/images/Paul_Oxborough_Beds.jpg" alt="image" height="fixed" /> </span>
</div>
</a>
<a href="#"><div class="hover-img">
<td>Artist Name</td>
<span><img src="https://collinsgalleries.com/images/Paul_Oxborough_MacBeth-frame.jpg" alt="image" height="fixed" /> </span>
</table>
</body>
</html>
then CSS
a .hover-img {
position:static;
}
a .hover-img span {
position:absolute; left:-9999px; top:-9999px; z-index:9999;
}
a:hover .hover-img span {
top: 1vw;
left:18vw;
}
td {
display: table-cell;
vertical-align: inherit;
}
The issue with this code is - The images aren't don't size the same in the middle. if I add a 3rd line the formatting breaks. And this needs to be mobile responsive as well.
I am open to all suggestions. Thank you in advance
Ok Firstly the reason you would use bootstrap is that it caters for both Mobile and desktop screen sizes without having to run any additional boilerplate code to resize the site for the browser ...
jquery is not necessary to achieve your goal but pure Vanilla JavaScript is .
This is how I would approach it
In the first instance I would replace the table component with a Layout called a flex box This would make your code easier to read and will dynamically lay itself out ...If you would like to read up further on flex box CSS styles here is the link Flex Box
The Second thing is I would write a simple JavaScript function to change the image onMouseOver .In order to give the JavaScript engine a handle to the DOM image component you need to allocat and "id" to it . Then you can use let ObjName = document.getElementById('YourHtmlObject'). after that you can manipulate it with JS
I would use one image container and dynamically append the image source based on the artist Through a switch statement in JavaScript function
In order to get the image to zoom or scale onMouseover again I would simply place a CSS animation to do that
Vanilla JavaScript in your case would make your life allot simpler . It would be a good idea to learn the basics of it ... I have provided some code that should simplify the solution for you ... Let me know if you find this useful or need any further help
enjoy!
function ChangeImage(artistName) {
let img = document.getElementById('TheImage');
switch (artistName) {
case 'Rob':
// code block
img.src = 'https://collinsgalleries.com/images/Paul_Oxborough_Old_Friends.jpg';
break;
case 'Amy':
// code block
img.src = 'https://collinsgalleries.com/images/Paul_Oxborough_Beds.jpg';
break;
case 'Bob':
// code block
img.src = 'https://collinsgalleries.com/images/Paul_Oxborough_MacBeth-frame.jpg';
break;
case 'Clare':
// code block
img.src = 'https://collinsgalleries.com/images/Artist-Page-Monks.jpg';
break;
default:
// code block
img.src = 'https://collinsgalleries.com/images/Artist-Page-Monks.jpg';
}
}
.app-container {
display: flex;
flex-direction: row;
justify-content: space-evenly;
}
.leftcontainer {
flex-direction: column;
justify-content: space-evenly;
}
.rightcontainer {
flex-direction: column;
justify-content: space-evenly;
}
.midcontainer {
flex-direction: column;
justify-content: space-evenly;
}
.zoom {
transition: transform .2s;
/* Animation */
}
.zoom:hover {
transform: scale(1.5);
/* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
/* position:absolute;
right:0;*/
}
#TheImage {
transition: transform .2s;
}
<div class="app-container">
<div class="leftcontainer">
<div class="app-container">
<ul style="list-style: none;">
<li onmouseover="ChangeImage('Rob')">Rob</li>
<li onmouseover="ChangeImage('Amy')">Amy</li>
<li onmouseover="ChangeImage('Bob')">Bob</li>
<li onmouseover="ChangeImage('clare')">Clare</li>
</ul>
<ul style="list-style: none;">
<li onmouseover="ChangeImage('Rob')">Rob</li>
<li onmouseover="ChangeImage('Amy')">Amy</li>
<li onmouseover="ChangeImage('Bob')">Bob</li>
<li onmouseover="ChangeImage('clare')">Clare</li>
</ul>
</div>
</div>
<div class="midcontainer">
<span><img id='TheImage' class='zoom' src="https://collinsgalleries.com/images/Artist-Page-Monks.jpg" alt="image" height="300px" width="300px"/> </span>
</div>
<div class="rightcontainer">
<div class="app-container">
<ul style="list-style: none;">
<li onmouseover="ChangeImage('Rob')">Rob</li>
<li onmouseover="ChangeImage('Amy')">Amy</li>
<li onmouseover="ChangeImage('Bob')">Bob</li>
<li onmouseover="ChangeImage('clare')">Clare</li>
</ul>
<ul style="list-style: none;">
<li onmouseover="ChangeImage('Rob')">Rob</li>
<li onmouseover="ChangeImage('Amy')">Amy</li>
<li onmouseover="ChangeImage('Bob')">Bob</li>
<li onmouseover="ChangeImage('clare')">Clare</li>
</ul>
</div>
</div>
</div>

Dropzone issues - there are spots inside the dropzone that do not work. Dropping files there will open them in browser

File manager = html container that contains a table-like list of files.
I have made a drop zone as big as the file manager instead of making a designated drop-zone.
I got inspired by this design:
https://www.youtube.com/watch?v=seXXWRygRkY
I only took the drop zone highlight idea from this video.
If you watch the video you will see that at 0:15 he goes over an element and the drop-zone blinks. This happens with my drop zone in A LOT of places.
My current file manager with div hierarchy :
<template>
<section
#dragover.prevent="dragOk = true"
#drop.prevent="addFile"
#drop.stop.prevent="dragOk = false"
#dragleave="dragOk = false"
>
<div class="top_container">
<div :class="`mid_container ${dragOk ? 'drag-ok' : ''}`">
<div class="title">
<h1>
File
<span>Manager</span>
</h1>
</div>
<!-- TODO: File Manager Component -->
<div v-cloak class="file-manager-container">
<div class="file-line header">
<div class="file-name">File name:</div>
<div class="file-size">Size:</div>
<div class="action-buttons">Actions:</div>
</div>
<div
:class="`file-line ${file.status ? 'wrong-file' : ''}`"
v-for="(file, index) in currentFiles"
:key="index"
>
<!-- left -->
<div class="file-name">
{{ file.name }}
<span v-if="file.status"> - {{ file.status }}</span>
</div>
<!-- middle -->
<div class="file-size">{{ file.size }} kb</div>
<!-- right -->
<div class="action-buttons">
<span>
<i class="far fa-edit"></i>
</span>
<span #click.prevent="currentFiles.splice(index, 1)">
<i class="fa fa-trash" aria-hidden="true"></i>
</span>
</div>
</div>
</div>
<!-- <span v-if="uploading" class="progress-bar">
<progress :value="progress" max="100">{{progress}}%</progress>
</span>-->
<div class="upload-message" v-if="message">
<div>{{ message }}</div>
</div>
</div>
</div>
</section>
</template>
<style scoped>
.drag-ok {
background: pink;
opacity: 0.5;
z-index: 100;
}
</style>
Issue:
If I drag items over some borders or text the dropzone blinks from pink to the default color. If I drop files when the dropzone isn't pink, the browser will open said file.
Here is a fiddle to ilustrate the problem: http://jsfiddle.net/m3wzbyoL/23/
You will have to select a file from your OS, drag it over the area and move it around there and you will see crazy flashes.
Adding pointer-events: none; to the .drop container will cancel every event from the child element and I do not want this.
If I add pointer-events: none; to .drop .highlight will make the drag events to not work.
Two things:
Ensure you are only toggling the drag-ok class on the dragenter and dragleave events. dragover will fire every few hundred milliseconds and is only for capturing events as you are dragging.
Disable pointer-events on all the children of the drop-zone target in CSS when the drag-ok class is active (not the drop-zone target itself). This will ensure that no other events from children will interfere while dragging.
Note: code provided as a minimal example, doesn't match code in question exactly..
$('.drop').on('dragenter', function(e) {
$(this).addClass('drag-ok');
})
.on('dragleave', function(e) {
$(this).removeClass('drag-ok');
})
.drop {
height: auto;
width: 200px;
background: #aaa;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.drop.drag-ok {
border: 2px dashed black;
background: black;
opacity: 0.5;
}
/**
* The important bit:
* disable pointer events on all children elements of
* the drop zone element *only* when the dragenter
* event has fired (.drag-ok is active)
*/
.drop.drag-ok * {
pointer-events: none;
}
.img {
height: 100px;
width: 100px;
background: red;
margin: 5px 0;
}
.img:hover {
background: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div draggable="true">drag me</div>
<div class="drop">
<span>Drop here</span>
<div class="img"></div>
<div class="img"></div>
<div class="img"></div>
<div class="img"></div>
</div>

Converting multiple divs into one

I've created a module for the WPBakery plugin which allows a user to drag and drop a tab item into the tab container. Just a visual of what I'm referring to:
The outer container will generate the parent and ul class, then for each new Tab Item added, it will generate a new .tab__item class, which for me houses a header and an image.
The pseudo for a .tab__item is the following:
<div class="tab__item">
<div class="tabbedContent__left">
<!-- header will be here -->
</div>
<div class="tabbedContent__right">
<!-- image will be as a background image on this div -->
</div>
</div>
When a header is hovered upon, the .tabbedContent__right will show the according image under that .tab__item.
The issue I'm having is that for each new Tab Item that is added in the backend, it will generate a new .tab__item div which obviously has its own .tabbedContent__right div. This means that when a new header is hovered upon, the .tabbedContent__right div shifts down.
It's probably better explained with a demo:
$(document).ready(function() {
$('.tabs__li .header').click(function() {
var tab_id = $(this).attr('data-tab');
$('.tab__item').removeClass('active');
$(this).addClass('active');
$("#" + tab_id).addClass('active');
})
// add class .active on li hover
$('.tabs__li').mouseenter(function() {
$('.tab__item').removeClass('active');
$(this).parents('.tab__item').addClass('active');
});
// Change active tab every x seconds
$(function() {
var list = $(".tab__item"),
currentActive = 0;
time = 5; //interval in seconds
setInterval(function() {
currentActive = (currentActive + 1) % list.length;
list.removeClass('active').eq(currentActive).addClass('active');
}, time * 1000);
});
})
.tabbedContent ul {
margin: 0;
padding: 0;
}
.tabbedContent__left,
.tabbedContent__right {
flex-basis: 50%;
}
.tabbedContent__left {
margin: 0;
}
.tabbedContent__left .tabs__li {
list-style-type: none;
padding-left: 10px;
}
.tabbedContent__left .tabs__li span.header {
font-size: 2.313rem;
font-family: "HelveticaNeue-bold", Helvetica, sans-serif;
color: #ABABAB;
cursor: pointer;
}
.tabbedContent .tab__item.active .tabbedContent__left li.tabs__li span.header {
color: #454544;
}
.tabbedContent__right {
display: none;
min-height: 325px;
background-repeat: no-repeat;
background-size: contain;
}
.tabbedContent .tab__item.active .tabbedContent__right {
display: block;
}
<script type='text/javascript' src='https://code.jquery.com/jquery-3.4.1.min.js?ver=3.4.1'></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div class="tabbedContent">
<ul class="tabs d-flex flex-column">
<!-- container for 1 -->
<div class="tab__item d-flex flex-column flex-md-row active">
<div class="tabbedContent__left">
<li class="tabs__li" data-tab="tab-1">
<span class="header"> Header </span>
</li>
</div>
<div class="tabbedContent__right" id="tab-1'" style="background-image:url(http://oi68.tinypic.com/5a50me.jpg);"></div>
</div>
<!--------->
<!-- container for 2 -->
<div class="tab__item d-flex flex-column flex-md-row active">
<div class="tabbedContent__left">
<li class="tabs__li" data-tab="tab-2">
<span class="header"> Header 2 </span>
</li>
</div>
<div class="tabbedContent__right" id="tab-2'" style="background-image:url(http://oi65.tinypic.com/2zdr4f7.jpg);"></div>
</div>
<!--------->
<!-- container for 3 -->
<div class="tab__item d-flex flex-column flex-md-row active">
<div class="tabbedContent__left">
<li class="tabs__li" data-tab="tab-3">
<span class="header"> Header 3 </span>
</li>
</div>
<div class="tabbedContent__right" id="tab-3'" style="background-image:url(http://oi68.tinypic.com/5a50me.jpg);"></div>
</div>
<!--------->
</ul>
</div>
Working JSFiddle here
As you can see with the above demo, the height (and presence of multiple) .tabbedContent__right divs, is causing a gap between the headers.
What I want to do:
I cannot alter the markup structure (i.e. tab__item must have tabbedContent__left and tabbedContent__right). But I don't want multiple .tabbedContent__right divs to be generated, only the one. So something like this:
Is there a way I can manipulate my current markup to only show one but still function as it does in the demo via JS?
More info:
What does the JS that creates the divs look like?
I haven't created any JS for this (because I wasn't sure if it was the best approach). All my JS regarding this module is in the demo above.
After I drag and drop a tab item into the container, what happens?
This is how the backend of the module looks like:
When a Tab Item is added, the following markup is generated:
<div class="tab__item">
<div class="tabbedContent__left">
<span class="header">' . $tab_header . '</span>
</div>
<div class="tabbedContent__right" style="background-image:url('.$background_img.');"></div>
</div>

Categories

Resources