Show only a few users and hide others - javascript

Can anyone explain how to make a user list like as shown in the image below...
I'm making a project in Meteor and using Materialize for template and I want to display the list of assigned users. If there are more than a particular count(say 5) of users i want them to be displayed like on that image... I have tried googling this and haven't found anything useful. I also checked the Materialize website and found nothing useful. So if anyone has an idea please help share it.
Ok so this is the output html, in this case i only have one member but in real case I will have more:
<div class="row"> ==$0
<label class="active members_padding_card_view">Members</label>
<div class="toolBarUsers flex" style="float:right;">
<dic class="other-profile" style="background-color:#f06292;">
<span>B</span>
</div>
This is the .js code
Template.profile.helpers({
randomInitials: function () {
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var nLetter = chars.charAt(Math.floor(Math.random()*chars.length));
var sLetter = chars.charAt(Math.floor(Math.random()*chars.length));
return nLetter + sLetter;
},
tagColor: function () {
var colors = ["#e57373","#f06292","#ba68c8","#9575cd","#7986cb","#64b5f6","#4fc3f7","#4dd0e1","#4db6ac","#81c784","#aed581","#dce775","#fff176","#ffd54f","#ffb74d","#ff8a65","#a1887f","#e0e0e0","#90a4ae"];
return colors[Math.floor(Math.random()*colors.length)];
},
randomAllowed : function(possible) {
var count = Math.floor((Math.random() * possible) + 1);
if(count == 1) {
return;
}
return "none";
},
membersList() {
const instance = Template.instance();
const cardDataId = new Mongo.ObjectID(instance.data.cardData._id.valueOf());
return CardDataMembers.find({lkp_card_data_fkeyi_ref: cardDataId});
},
memberData: function() {
// We use this helper inside the {{#each posts}} loop, so the context
// will be a post object. Thus, we can use this.xxxx from above memberList
return Meteor.users.findOne(this.lkp_user_fkeyi_ref);
},
showMembers() {
const instance = Template.instance();
const cardDataId = new Mongo.ObjectID(instance.data.cardData._id.valueOf());
let membersCount = CardDataMembers.find({lkp_card_data_fkeyi_ref: cardDataId}).count();
////console.log(membersCount);
if (membersCount > 0) {
$('.modal-trigger').leanModal();
return true;
} else {
return false;
}
},
});
Right now if I add a lot of users I get this:

This can be done in many ways, but I've used CSS Flexbox.
I've used two <div>s one contains single user circles having class .each-user that is expanding (for reference I've taken 6) and another contains the total number of users having class .total-users.
It's a bit confusing but if you look into my code below or see this Codepen you'll get to know everything.
html, body {
width: 100%;
height: 100%;
margin: 0;
font-family: Roboto;
}
.container {
display: flex;
align-content: center;
justify-content: center;
margin-top: 20px;
}
/* Contains all the circles */
.users-holder {
display: flex;
}
/* Contains all circles (those without total value written on it) */
.each-user {
display: flex;
flex-wrap: wrap;
padding: 0 10px;
max-width: 300px;
height: 50px;
overflow: hidden;
}
/* Circle Styling */
.circle {
width: 50px;
height: 50px;
border-radius: 50%;
margin-right: 10px;
}
.each-user .circle {
background: #00BCD4;
}
.each-user .circle:last-child {
margin-right: 0;
}
/* Circle showing total */
.total-users {
padding: 0;
margin-bottom:
}
.total-users .circle {
background: #3F51B5;
margin: 0;
position: relative;
}
.total-users .circle .txt {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
}
<div class="container">
<div class="users-holder">
<div class="total-users">
<div class="circle">
<span class="txt">+12</span>
</div>
</div>
<div class="each-user">
<div class="circle user-circle"></div>
<div class="circle user-circle"></div>
<div class="circle user-circle"></div>
<div class="circle user-circle"></div>
<div class="circle user-circle"></div>
<!-- Sixth Circle -->
<div class="circle"></div>
</div>
</div>
</div>
Hope this helps!

I've used jQuery. See this https://jsfiddle.net/q86x7mjh/26/
HTML:
<div class="user-list-container">
<div class="total-circle hidden"><span></span></div>
<div class="user-circle"><span>T</span></div>
<div class="user-circle"><span>C</span></div>
<div class="user-circle"><span>U</span></div>
<div class="user-circle"><span>M</span></div>
<div class="user-circle"><span>R</span></div>
<div class="user-circle"><span>Z</span></div>
<div class="user-circle"><span>N</span></div>
<div class="user-circle"><span>O</span></div>
<div class="user-circle"><span>M</span></div>
<div>
jQuery:
var items_to_show = 5;
if($('.user-circle').length > items_to_show){
var hide = $('.user-circle').length - items_to_show;
for(var i = 0; i < hide; i++){
$('.user-circle').eq(i).addClass('hidden');
}
$('.total-circle').removeClass('hidden');
$('.total-circle span').text('+' + hide);
}

So after quite some time I have solved the problem. I am posting my answer here for anyone that will in the future experience a similar issue...
Have a good day!
I have added the following lines of code to my template:
return CardDataMembers.find({lkp_card_data_fkeyi_ref: cardDataId},{sort: {createdAt: -1}, limit: 3});
diffMembers(){
const instance = Template.instance();
const cardDataId = new Mongo.ObjectID(instance.data.cardData._id.valueOf());
const limit = 3;
const allMembersOnCard = CardDataMembers.find({lkp_card_data_fkeyi_ref: cardDataId}).count();
let remainingMembers = allMembersOnCard - limit;
return remainingMembers;
},
And in the HTML included:
<div class="other-profile" style="background-color:#dedede;">
<span>+{{diffMembers}}</span>
</div>

Related

How to check if an element is clicked

<div class="game">
<div class="hole hole1">
<div class="mole"></div>
</div>
<div class="hole hole2">
<div class="mole"></div>
</div>
<div class="hole hole3">
<div class="mole"></div>
</div>
<div class="hole hole4">
<div class="mole"></div>
</div>
<div class="hole hole5">
<div class="mole"></div>
</div>
<div class="hole hole6">
<div class="mole"></div>
</div>
<div class="hole hole7">
<div class="mole"></div>
</div>
<div class="hole hole8">
<div class="mole"></div>
</div>
<div class="hole hole9">
<div class="mole"></div>
</div>
</div>
.game {
width: 300px;
height: 600px;
display: flex;
flex-wrap: wrap;
margin: 0 auto;
}
.hole {
flex: 1 0 33.33%;
overflow: hidden;
width: 100%;
position: relative;
}
.hole:after {
display: block;
background: url('gaura1.png') bottom center no-repeat;
background-size: 100%;
content: '';
width: 100%;
height:100%;
position: absolute;
z-index: 2;
}
.mole {
background: url('flowAlb.png') bottom center no-repeat;
background-size: 100%;
position: absolute;
width: 100%;
height:100%;
top:100%;
transition: all 0.4s;
}
.hole.up .mole {
top: -20px;
z-index:3;
}
I'm trying to learn web development with CSS, HTML and JAVASCRIPT(i'm new to all of them) and I'm working on some whack-a-mole game code that was free to work with. I understood what the code does, but I'm not sure how to work with. I have an event listener on click for each mole, but I wanna do something if the mole isn't clicked and I don't know how to check that. I tried different methods, using boolean variables or trying to check if the click was outside the element, but none of them worked. I'm pretty sure I didn't used them right, so I would really appreciate some help or information. I'll leave here the JS code. Thanks so much!
const holes = document.querySelectorAll('.hole');
const scoreBoard = document.querySelector('.score');
const moles = document.querySelectorAll('.mole');
const mySound=document.getElementById("sound");
const joc=document.getElementsByClassName("game");
let lastHole;
let timeUp = false;
let score = 0;
function randomTime(min, max) {
return Math.round(Math.random() * (max - min) + min);
}
function randomHole(holes) {
const index = Math.floor(Math.random() * holes.length);
const hole = holes[index];
if (hole === lastHole) {
return randomHole(holes);
}
lastHole = hole;
return hole;
}
function peep() {
const time = randomTime(500, 1000);
const hole = randomHole(holes);
hole.classList.add('up');
setTimeout(() => {
hole.classList.remove('up');
if (!timeUp) {
peep();
}
}, time);
}
function startGame() {
scoreBoard.textContent = 0;
timeUp = false;
score = 0;
peep();
setTimeout(() => timeUp = true, 90000)
}
function wack(e) {
if (!e.isTrusted) return;
score = score + 100;
this.parentNode.classList.remove('up');
scoreBoard.textContent = score;
}
moles.forEach(mole => mole.addEventListener('click', wack));
You can add a click event to the documentElement and check its target. Consequently you could also remove your other click handlers while doing this and check for the class mole.
;document.documentElement.onclick = function(event){
//REM: Target element of the click
var tTarget = event.srcElement || event.target;
//REM: Check which element was targted.
if(tTarget.id === 'sample'){
alert('You clicked on #sample')
}
else{
alert('You clicked on "' + tTarget.tagName + '"')
}
};
html, body{
height: 100%;
position: relative;
width: 100%
}
body{
background: yellow
}
div{
background: red
}
.sample{
background: lime;
height: 100%;
position: relative;
width: 100%
}
<div class = 'sample'>
<div id = 'sample'>click me or not</div>
</div>

How to Output chosen DIV elements that are stored in an array

I'm creating a card game where the user chooses 2 out of 3 cards. I then store those cards into an array and want to be able to print out the cards that were stored in the array with the actual image of the cards that the user chose.
I've tried looping through the array and then using innerHTML to push the results to a specific div but I keep getting "[object HTMLDivElement]". It also prints that out 3 times instead of 2 (since we are choosing 2 cards there should only be two elements to print out, I suspect the loop is running an extra time).
The below is the loop I have tried but I also am including a codepen for further clarity.
https://codepen.io/cramos2/pen/pMVjez
var holder = document.getElementById("cardResults");
for(var i=0; i < chosenCards.length; i++){
holder.innerHTML += "<p>" + chosenCards[i] + "</p><br>";
}
let chosenCards = new Array();
class tarot {
//constructor
constructor(cards) {
this.cardsArray = cards;
}
startReading() {
this.shuffleCards(this.cardsArray);
//call shuffle method
}
//Adds class "flipped" to the cards
flipCard(card, cards) {
if (this.canFlipCard(card)) {
if (chosenCards.length >= 2) {
console.log("removing1");
//from here
for (let card0 in cards) {
let list = card0.classList;
if (list) {
if (!list.contains('visible')) {
card0.removeEventListener('click', card0.fn);
}
}
}
} //to here
else if (!card.classList.contains('visible')) {
debugger;
card.classList.add('visible');
chosenCards.push(card);
console.log(chosenCards);
//this is where print out
var holder = document.getElementById("cardResults");
for (var i = 0; i < chosenCards.length; i++) {
holder.innerHTML += "<p>" + chosenCards[i] + "</p><br>";
}
card.removeEventListener('click', card.fn);
}
}
}
//Need a Shuffle method in here
shuffleCards(cardsArray) {
for (let i = cardsArray.length - 1; i > 0; i--) {
const randIndex = Math.floor(Math.random() * (i + 1));
[cardsArray[i], cardsArray[randIndex]] = [cardsArray[randIndex], cardsArray[i]];
}
cardsArray = cardsArray.map((card, index) => {
card.style.order = index;
});
}
//gets the card
getCardType(card) {
return card.getElementsByClassName('card-value')[0].src;
}
//returns card
canFlipCard(card) {
return card
}
}
//this will call the reading to start when page is loaded
if (document.readyState == 'loading') {
document.addEventListener('DOMContentLoaded', ready)
} else {
ready()
}
function ready() {
//declares card's' & sets it to the card class in HTML
let cards = Array.from(document.getElementsByClassName('card'));
//creates new instance of tarot class
let tarotReading = new tarot(cards);
let over = Array.from(document.getElementsByClassName('over'));
over.forEach(overlay => {
overlay.addEventListener('click', () => {
overlay.classList.remove('visible');
tarotReading.startReading();
});
});
//flips the cards
cards.forEach(card => {
card.addEventListener('click', card.fn = function clicked() {
tarotReading.flipCard(card, cards);
//remove cards that dont have visible tag
});
})
console.log(chosenCards[0]);
}
h1 {
color: #7B68EE;
padding left: 50px;
padding right: 50px;
padding-top: 5px;
text-align: center;
}
.container {
display: grid;
grid-template-columns: repeat(6, auto);
grid-gap: 10px;
margin: 50px;
justify-content: center;
perspective: 500px;
}
.card {
position: relative;
height: 175px;
width: 125px;
}
.card-face {
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
backface-visibility: hidden;
border-radius: 12px;
border-width: 1px;
border-style: solid;
transition: transform 500ms ease-in-out;
}
.card.visible .card-back {
transform: rotateY(-180deg);
}
.card.visible .card-front {
transform: rotateY(0)
}
.card-back {
background-color: black;
border-color: white;
color: white;
}
.card-front {
background-color: black;
border-color: white;
color: white;
transform: rotateY(180deg);
}
<body>
<h1>Tarot</h1>
<div class="container">
<div class="card">
<div class="card-back card-face card1" id="card1">
<p> 1
<p>
</div>
<div class="card-front card-face">
<p> The Hermit
<p>
</div>
</div>
<div class="card">
<div class="card-back card-face card2">
2
</div>
<div class="card-front card-face">
The Fool
</div>
</div>
<div class="card">
<div class="card-back card-face card3">
3
</div>
<div class="card-front card-face">
The Empress
</div>
</div>
</div>
<button type="button" class="over container">Shuffle</button>
</div>
<hr>
<div id="cardResults">
</div>
</body>
The expected result would be the flipped over card with the text (not the number of the card) that the user has chosen.
You could try something like this:
for(var i=0; i < chosenCards.length; i++){
holder.appendChild(chosenCards[i].cloneNode(true));
}

Visible intersectionObserver

I am trying to learn about Javascript's IntersectionObserver.
After reading several articles and the documentation I have decided to make a CodePen to try it myself: IntersectionObserver CodePen
I would like to display the "block that is visible" on the top message. The CodePen "almost" works, but not completely. Sometimes it shows the correct block, sometimes it doesn't.
Here is my JS:
let message = document.querySelector('#block-number');
// INTERSECTION OBSERVER STUFF
const io = new IntersectionObserver(entries => {
if(entries[0].isIntersecting) {
message.innerHTML = entries[0].target.textContent;
}
}, {
threshold: [.25]
});
// ELEMENTS TO OBSERVE
const blk1 = document.querySelector('#block1');
const blk2 = document.querySelector('#block2');
const blk3 = document.querySelector('#block3');
const blk4 = document.querySelector('#block4');
const blk5 = document.querySelector('#block5');
const blk6 = document.querySelector('#block6');
// START OBSERVING ELEMENTS
io.observe(blk1);
io.observe(blk2);
io.observe(blk3);
io.observe(blk4);
io.observe(blk5);
io.observe(blk6);
Any ideas on what i am doing wrong?
i have also tried (without luck) something like:
if(entries[0].intersectionRatio !== 0)
Thank you!
The function passed to the IntersectionObserved is executed when the intersection state changes. So what happens when you are at block 3 and scroll a bit so block 4 is shown? The intersection changes for block 4 and so the message is changed. WHen you scroll back up the intersection is changed again for block 4, but it does not enter the if condition. The intersection for block 3 on the other hand is not changed - it was visible before, even though not fully, it's visible still.
There are few ways you can fix this.
One is to define intersection ratio, and going above and below that ratio will be considered change in the state (pass options hash as second argument, containing threshold key with value 0 - 1, e.g. 0.5 for 50% visibility)
You can also add the same observer for all of the blocks and iterate trough entries in the function, checking which block has the best intersection ratio.
You have set the threshold to 25%.
The problem with this, is that the previous block leaves its last 25% of the viewport after the next block enters the viewport by 25%.
This was easy to see with the following console.log:
console.log(entries[0].target.textContent, ": ", entries[0].intersectionRatio)
let message = document.querySelector('#block-number');
// INTERSECTION OBSERVER STUFF
const io = new IntersectionObserver(entries => {
if(entries[0].isIntersecting ) {
console.log(entries[0].target.textContent, ": ", entries[0].intersectionRatio)
message.innerHTML = entries[0].target.textContent;
}
}, {
threshold: [.25]
});
// ELEMENTS TO OBSERVE
const blk1 = document.querySelector('#block1');
const blk2 = document.querySelector('#block2');
const blk3 = document.querySelector('#block3');
const blk4 = document.querySelector('#block4');
const blk5 = document.querySelector('#block5');
const blk6 = document.querySelector('#block6');
// START OBSERVING ELEMENTS
io.observe(blk1);
io.observe(blk2);
io.observe(blk3);
io.observe(blk4);
io.observe(blk5);
io.observe(blk6);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: roboto;
}
.center {
display: flex;
align-items: center;
justify-content: center;
}
.container {
background-color: #eee;
width: 100%;
height: 100%;
min-height: 100vh;
}
.message {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 80px;
background-color: #ef9b8d;
color: white;
}
.blocks {
padding-top: 100px;
}
.block {
height: 85vh;
width: 90vw;
margin: 0 auto 15vh;
background-color: #999;
color: white;
}
<div class="message center">Displaying <span id="block-number">Block 1</span></div>
<div class="blocks">
<div id="block1" class="block center">Block 1</div>
<div id="block2" class="block center">Block 2</div>
<div id="block3" class="block center">Block 3</div>
<div id="block4" class="block center">Block 4</div>
<div id="block5" class="block center">Block 5</div>
<div id="block6" class="block center">Block 6</div>
</div>
To fix this, simply raise the threshold. (Depending on how much of the block needs to enter the viewport for you to consider it the current block)
Demo:
let message = document.querySelector('#block-number');
// INTERSECTION OBSERVER STUFF
const io = new IntersectionObserver(entries => {
if(entries[0].isIntersecting ) {
console.log(entries[0].target.textContent, ": ", entries[0].intersectionRatio)
message.innerHTML = entries[0].target.textContent;
}
}, {
threshold: [.8] // raised the threshold
});
// ELEMENTS TO OBSERVE
const blk1 = document.querySelector('#block1');
const blk2 = document.querySelector('#block2');
const blk3 = document.querySelector('#block3');
const blk4 = document.querySelector('#block4');
const blk5 = document.querySelector('#block5');
const blk6 = document.querySelector('#block6');
// START OBSERVING ELEMENTS
io.observe(blk1);
io.observe(blk2);
io.observe(blk3);
io.observe(blk4);
io.observe(blk5);
io.observe(blk6);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: roboto;
}
.center {
display: flex;
align-items: center;
justify-content: center;
}
.container {
background-color: #eee;
width: 100%;
height: 100%;
min-height: 100vh;
}
.message {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 80px;
background-color: #ef9b8d;
color: white;
}
.blocks {
padding-top: 100px;
}
.block {
height: 85vh;
width: 90vw;
margin: 0 auto 15vh;
background-color: #999;
color: white;
}
<div class="message center">Displaying <span id="block-number">Block 1</span></div>
<div class="blocks">
<div id="block1" class="block center">Block 1</div>
<div id="block2" class="block center">Block 2</div>
<div id="block3" class="block center">Block 3</div>
<div id="block4" class="block center">Block 4</div>
<div id="block5" class="block center">Block 5</div>
<div id="block6" class="block center">Block 6</div>
</div>

Adding multiple .random classes to multiple divs without a duplication

Trying to add a random class to two classes (.left & .right) but with a rule of the two random divs cannot appear at the same time
JS:
$(document).ready(function(){
var classes = ['random-1','random-2', 'random-3']; //add as many classes as u want
var randomnumber = Math.floor(Math.random()*classes.length);
$('.left').addClass(classes[randomnumber]);
});
HTML:
<div class="left">
Left
</div>
<div class="right">
Right
</div>
.left {
background: blue;
height: 100vh;
width: 50%;
float: left;
position: relative;
}
.right {
background: red;
height: 100vh;
width: 50%;
float: right;
}
.random-1 {
background: orange;
}
.random-2 {
background: yellow;
}
.random-3 {
background: pink;
}
.random-4 {
background: green;
}
.random-5 {
background: blueviolet;
}
Ideal result would be
<div class="left random-1">
Left
</div>
<div class="right random-4">
Right
</div>
https://codepen.io/anon/pen/OOJaqL
You can use a while loop that iterates until two random and unique classes have been chosen.
function getRandomClass() {
let classes = ['random-1','random-2', 'random-3'];
let index = Math.floor(Math.random() * classes.length);
return classes[index];
}
$(document).ready(function() {
let leftClass = null;
let rightClass = null;
while (leftClass == rightClass) {
leftClass = randomClass();
rightClass = randomClass();
}
$('.left').addClass(leftClass);
$('.right').addClass(rightClass);
});
Add the .random-* class to the left div, only when the right div does not have this class.
var rightHasClass = $('.right').hasClass(classes[randomnumber]);
if( ! rightHasClass){
$('.left').addClass(classes[randomnumber]);
}
var leftHasClass = $('.left').hasClass(classes[randomnumber]);
if( ! leftHasClass){
$('.right').addClass(classes[randomnumber]);
}

Fill parent div with the image being hovered over

I am still fairly new to JS, and I am trying to replace the HTML of a div with a picture that is being moused over, and when the mouse leaves I want it to return to it's normal state. I thought that I did everything right but my code doesn't seem to be working. I've looked through stack overflow and I see a lot of jQuery solutions to my 'problem,' but I would like an answer in pure JavaScript (I'm trying to "maser" this first), along with an explanation so I can understand why the answer IS the answer. Thanks.
I'll try to explain myself (my code). I grabbed reference to the image holder, and I grabbed reference to the the images. I thought I made a function that looped through the array of images and added an event listener to whichever image ( image[i] ) was being moused over. Then, I added an event listener that is supposed to return the image holder to it's default state by inserting the original HTML. I just don't understand how to fix this.
var holder = document.getElementById('holder');
var images = document.getElementsByTagName('img');
var popImage = function () {
for (i = 0; i < images.length; i++) {
images[i].addEventListener('mouseover', = function () {
holder.innerHTML = images[i];
});
images[i].addEventListener('mouseout', function () {
holder.innerHTML =
'<div class='col-md-3 img-fluid' id='img1'><img src='photo1.jpg'></div>
<div class='col-md-3 img-fluid' id='img2'><img src='photo2.jpg'></div>
<div class='col-md-3 img-fluid' id='img3'><img src='photo3.2.jpg'></div>
<div class='col-md-3 img-fluid' id='img4'><img src='photo4.jpg'></div>'
});
};
};
popImage();
You said you are new to JS and just learning which is great but an important part of learning JS is learning when not to use it. As #Yoda said if this was for production you really should use CSS instead of JS.
Here is one way you could accomplish this with pure CSS
<style>
.img {
width: 100px;
height: 100px;
background: #bada55;
border: 2px solid #333;
float: left;
}
.holder:hover > .img {
opacity: 0;
}
.holder:hover > .img:hover {
opacity: 1;
}
</style>
<div class="holder">
<!-- Using div.img for simplicity, these whould be your <img/> tags -->
<div class="img">1</div>
<div class="img">2</div>
<div class="img">3</div>
<div class="img">4</div>
</div>
For the purpose of learning, here's how you'd do it in JS:
var holder = document.getElementById('holder');
var images = document.querySelectorAll('.img');
var filter = false;
function popImage () {
// Use for (var i = 0 . . .
// Instead of for (i = 0 . . .
// Because without var, i will be stored in the global scope
for (var i = 0; i < images.length; i++) {
(function (_i) {
images[_i].addEventListener('mouseover', function () {
holder.innerHTML = '';
// We can't set innerHTML to images[_i]
// because it's a DomNode not a string
holder.appendChild(images[_i]);
});
})(i);
}
holder.addEventListener('mouseout', function (e) {
if (e.target !== holder)
return;
holder.innerHTML = '';
// Again, use var j = 0 . . .
for (var j = 0; j < images.length; j++) {
holder.appendChild(images[j]);
}
});
}
popImage();
.img {
width: 100px;
height: 100px;
background: #bada55;
border: 2px solid #333;
display: inline-block;
}
#holder {
position: relative;
width: 100%;// So doesn't collape and trigger mouseout
height: 100px;
background: red;
padding: 20px 0;
}
<div id="holder">
<!-- Again, these would be your image tags -->
<div class="img">1</div>
<div class="img">2</div>
<div class="img">3</div>
<div class="img">4</div>
</div>
I had 10 mins before leaving work so I had a crack at this to see how I would do it and give you some ideas.
Here is my implementation (https://jsfiddle.net/hg7s1pyh/)
I guess the main thing here is that I've broken it down into lots of smaller parts, this makes solving problems far easier, each method is concerned with doing one thing only.
You will also note the use of classes to show and hide content rather than removing it entirely, this takes lots of the arduous work out of this feature.
function attachEvents() {
var images = getImages();
images.forEach(function(image) {
attachMouseOverEvent(image);
attachMouseLeaveEvent(image);
});
}
function attachMouseOverEvent(element) {
element.addEventListener('mouseover', function(e) {
var clonedImage = e.target.cloneNode();
addImageToPreview(clonedImage);
});
}
function attachMouseLeaveEvent(element) {
element.addEventListener('mouseleave', function(e) {
removeImageFromPreview();
});
}
function getImages() {
return document.querySelectorAll('.js-image');
}
function getImagePreviewElement() {
return document.querySelector('.js-image-box');
}
function addImageToPreview(imageElement) {
var previewElement = getImagePreviewElement();
previewElement.classList.add('previewing');
previewElement.appendChild(imageElement);
}
function removeImageFromPreview() {
var previewElement = getImagePreviewElement();
previewElement.classList.remove('previewing');
var image = previewElement.querySelector('.js-image');
image.remove();
}
attachEvents();
.image-box {
position: relative;
min-height: 400px;
width: 400px;
border: 1px solid #000;
text-align: center;
}
.image-box .placeholder {
position: absolute;
top: 50%;
text-align: center;
transform: translateY(-50%);
width: 100%;
}
.image-box.previewing .placeholder {
display: none;
}
.image-box .image {
position: absolute;
top: 50%;
text-align: center;
transform: translate(-50%, -50%);
height: 100%;
width: 100%;
}
.images {
margin-top: 10px;
}
<div class="js-image-box image-box">
<div class="placeholder">
Placeholder
</div>
</div>
<div class="images">
<div class="col-md-3 img-fluid"><img class="js-image image" src="http://placehold.it/350x150"></div>
<div class="col-md-3 img-fluid"><img class="js-image image" src="http://placehold.it/150x150"></div>
<div class="col-md-3 img-fluid"><img class="js-image image" src="http://placehold.it/400x400"></div>
<div class="col-md-3 img-fluid"><img class="js-image image" src="http://placehold.it/350x150"></div>
</div>

Categories