How to deactivate button once clicked Javascript - javascript

I want to stop incrementing the number of individual likes if the photo was liked(clicked) once, and increment the total number of likes for each individual photo liked(clicked)
individual photo likes likesAfterAddition
global photo likes globalNumberOfLikes
For the moment it is increasing every time I click in both individual and global likes, I know it is not the right logic!
What logic can I use please?
//increment likes on click
function incrementLikesOnClick() {
const heartIcons = Array.from(document.getElementsByClassName('heartIcon')); // multiple heart icons
heartIcons.forEach((likeIcon, index) => likeIcon.addEventListener('click', () => {
const individualLikeBox = document.getElementsByClassName('under-photo-info');
const totalLikesDivBox = document.getElementById("likesBox");
likeIcon.classList.add('activeRed');
let likesAfterAddition = likesTable[index] + 1; // add 1 like to the individual current photo
likesTable.splice(index, 1, likesAfterAddition); // replace the old value from the Array with the new value
let sum = likesTable.reduce(function(a, b){return a + b;}); // return the sum of the array
let globalNumberOfLikes = sum; // the sum of the array
individualLikeBox[index].innerHTML = `<span'>${likesAfterAddition}</span>`
totalLikesDivBox.innerHTML = `<div class="Likes">${globalNumberOfLikes}<i class="fas fa-heart"></i></div>`
console.log(likesTable)
}))
}

instead of using for loop to set event listeners which is not efficient
you can use the feature of bubbling, so when any of dom element is clicked, the event will bubble up of its parent elements sequentially till it reaches the parent dom
//increment likes on click
function incrementLikesOnClick() {
document.addEventListener("DOMContentLoaded", function(event) {
// Your code to run since DOM is loaded and ready
document.addEventListener('click', () => {
let clicked = event.target;
//element with class heartIcon is clicked and it doesnt have activeRed class
if(clicked.classList.contains('heartIcon') && !clicked.classList.contains('activeRed')){
let productContainer = clicked.parentElement.parentElement; // till you reach the product container
const individualLikeBox = productContainer.getElementsByClassName('under-photo-info');
const totalLikesDivBox = productContainer.getElementById("likesBox");
clicked.classList.add('activeRed');
// ..whatever extra logic you want to add
}
});
});
}

If the like icon is a button (which I assume it is). U can just add a 'disabled' attribute to it as part of the event handler (for the 'click' eventListener).
'When present, it specifies that the button should be disabled.
A disabled button is unusable and un-clickable.' (source)

I would calculate the total likes based on the presence of an "active" class on each button.
const totalLikesEl = document.querySelector('#total-likes');
const updateTotalLikes = () => {
totalLikesEl.textContent = document.querySelectorAll('.like.active').length;
};
const toggleLike = (e) => {
const button = e.currentTarget.classList.toggle('active');
updateTotalLikes();
};
document.querySelectorAll('.like').forEach(likeBtn => {
likeBtn.addEventListener('click', toggleLike);
});
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
flex-direction: column;
}
.cards {
display: flex;
flex-direction: row-wrap;
justify-content: center;
}
.card {
display: flex;
flex-direction: column;
padding: 0.25em;
margin: 0.5em;
border: thin solid grey;
}
.card-content {
background: grey;
width: 6em;
height: 6em;
}
.card-actions {
display: flex;
flex-direction: row;
justify-content: flex-end;
margin-top: 0.5em;
}
.like > .fa-heart {
color: grey;
}
.like.active > .fa-heart {
color: red;
}
.example-1 .card-content {
background: rgb(63,94,251);
background: radial-gradient(circle, rgba(63,94,251,1) 0%, rgba(252,70,168,1) 100%);
}
.example-2 .card-content {
background: rgb(251,63,94);
background: radial-gradient(circle, rgba(251, 63,94,1) 0%, rgba(168,252,70,1) 100%);
}
.example-3 .card-content {
background: rgb(94,63,251);
background: radial-gradient(circle, rgba(94,63,251,1) 0%, rgba(70,252,168,1) 100%);
}
.status {
text-align: center;
margin-top: 0.5em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css" rel="stylesheet"/>
<div class="cards">
<div class="card example-1">
<div class="card-content"></div>
<div class="card-actions">
<button class="like">
Like <i class="fas fa-heart"></i>
</button>
</div>
</div>
<div class="card example-2">
<div class="card-content"></div>
<div class="card-actions">
<button class="like">
Like <i class="fas fa-heart"></i>
</button>
</div>
</div>
<div class="card example-3">
<div class="card-content"></div>
<div class="card-actions">
<button class="like">
Like <i class="fas fa-heart"></i>
</button>
</div>
</div>
</div>
<div class="status">
<strong>Total Likes:</strong>
<span id="total-likes">0</span>
</div>

Related

Counter Observe when I scroll

Problem
I created a counter using HTML, CSS and JS (such as satisfied customer numbers, branch numbers, etc.)
The counter is also animated but since it's down the page, I'd like to animate it only when it gets to that point on the page. How do I do with the js?
const counters = document.querySelectorAll('.value');
const speed = 400;
counters.forEach( counter => {
const animate = () => {
const value = +counter.getAttribute('akhi');
const data = +counter.innerText;
const time = value / speed;
if(data < value) {
counter.innerText = Math.ceil(data + time);
setTimeout(animate, 1);
}else{
counter.innerText = value;
}
}
animate();
});
.counter-box {
display: block;
background: #f6f6f6;
padding: 40px 20px 37px;
text-align: center
}
.counter-box p {
margin: 5px 0 0;
padding: 0;
color: #909090;
font-size: 18px;
font-weight: 500
}
.counter {
display: block;
font-size: 32px;
font-weight: 700;
color: #666;
line-height: 28px
}
.counter-box.colored {
background: #eab736;
}
.counter-box.colored p,
.counter-box.colored .counter {
color: #fff;
}
<div class="container">
<div class="row contatore">
<div class="col-md-4">
<div class="counter-box colored">
<span class="counter value" akhi="560">0</span>
<p>Countries visited</p>
</div>
</div>
<div class="col-md-4">
<div class="counter-box">
<span class="counter value" akhi="3275">0</span>
<p>Registered travellers</p>
</div>
</div>
<div class="col-md-4">
<div class="counter-box">
<span class="counter value" id="conta" akhi="289">0</span>
<p>Partners</p>
</div>
</div>
</div>
</div>
What I have tried
i had tried with
const target = document.querySelector('.counter');
observer.observe(target);
but it doesn't seem to work. Many thanks to whoever can help me.
I would recommend, as others have suggested, to use the Intersection Observer API to animate your elements once they appear in the viewport.
The idea is simple, we'll create an observer that will observe the counters to animate and we're going to configure it so that it calls the animate function once a counter is fully visible in the viewport.
You may learn more about the options that an IntersectionObserver can accept in order to customize its behavior. Meanwhile, here's a live demo that illustrates how to make the counters animate once they appear in the screen (the code below has some helpful comments):
const counters = document.querySelectorAll('.value'),
speed = 400,
/**
* create an IntersectionObserver with the specified callback that will be executed for each intersection change for every counter we have.
* You may customize the options (2nd argument) per you requirement
*/
observer = new IntersectionObserver(
entries => entries.forEach(entry => entry.isIntersecting && animate(entry.target)),
{
threshold: 1 // tells the browser that we only need to execute the callback only when an element (counter) is fully visible in the viewport
}
),
// the animate function now accepts a counter (HTML element)
animate = counter => {
const value = +counter.dataset.akhi,
data = +counter.innerText,
time = value / speed;
if (data < value) {
counter.innerText = Math.ceil(data + time);
setTimeout(() => animate(counter), 1);
} else {
counter.innerText = value;
}
};
// attach the counters to the observer
counters.forEach(c => observer.observe(c));
.counter-box {
display: block;
background: #f6f6f6;
padding: 40px 20px 37px;
text-align: center
}
.counter-box p {
margin: 5px 0 0;
padding: 0;
color: #909090;
font-size: 18px;
font-weight: 500
}
.counter {
display: block;
font-size: 32px;
font-weight: 700;
color: #666;
line-height: 28px
}
.counter-box.colored {
background: #eab736;
}
.counter-box.colored p,
.counter-box.colored .counter {
color: #fff;
}
<div class="container">
<div class="row contatore">
<div class="col-md-4">
<div class="counter-box colored">
<!-- it is recommended to use "data-*" attributes to cache data that we might use later. The "data-akhi" contains the number to animate -->
<span class="counter value" data-akhi="560">0</span>
<p>Countries visited</p>
</div>
</div>
<div class="col-md-4">
<div class="counter-box">
<span class="counter value" data-akhi="3275">0</span>
<p>Registered travellers</p>
</div>
</div>
<div class="col-md-4">
<div class="counter-box">
<span class="counter value" id="conta" data-akhi="289">0</span>
<p>Partners</p>
</div>
</div>
</div>
</div>
As others suggested, you should use Intersection Observer.
This is how I'd do:
Scrolldown the snippet in order to see the counter animating up once is on the screen.
const counters = document.querySelectorAll('.value');
const speed = 400;
const observer = new IntersectionObserver( items => {
if(items[0].isIntersecting) {
const target = items[0].target;
const animate = () => {
const value = + target.getAttribute('akhi');
const data = + target.innerText;
const time = value / speed;
if(data < value) {
target.innerText = Math.ceil(data + time);
setTimeout(animate, 1);
}else{
target.innerText = value;
}
}
animate();
observer.unobserve(target);
}
})
counters.forEach( counter => observer.observe(counter));
.counter-box {
display: block;
background: #f6f6f6;
padding: 40px 20px 37px;
text-align: center
}
.counter-box p {
margin: 5px 0 0;
padding: 0;
color: #909090;
font-size: 18px;
font-weight: 500
}
.counter {
display: block;
font-size: 32px;
font-weight: 700;
color: #666;
line-height: 28px
}
.counter-box.colored {
background: #eab736;
}
.counter-box.colored p,
.counter-box.colored .counter {
color: #fff;
}
<div style="height: 600px;">
</div>
<div class="container">
<div class="row contatore">
<div class="col-md-4">
<div class="counter-box colored">
<span class="counter value" akhi="560">0</span>
<p>Countries visited</p>
</div>
</div>
<div class="col-md-4">
<div class="counter-box">
<span class="counter value" akhi="3275">0</span>
<p>Registered travellers</p>
</div>
</div>
<div class="col-md-4">
<div class="counter-box">
<span class="counter value" id="conta" akhi="289">0</span>
<p>Partners</p>
</div>
</div>
</div>
</div>

How to close a dropdown menu when another one is opening

I can't figure out how to close one submenu when another one is open. I'm not sure if html is needed here, so I'm just attaching JS code here:
const burgerBtn = document.querySelector(".header__burger"),
menu = document.querySelector(".menu"),
body = document.querySelector(".body"),
filter = document.querySelector(".filter"),
blockFilter = document.querySelectorAll(".block-filter"),
dropdown = document.querySelectorAll(".block-filter__dropdown");
if (filter) {
blockFilter.forEach(item => {
item.addEventListener("click", event => {
item.querySelector(".block-filter__dropdown").classList.toggle("block-filter__dropdown_state_active");
item.querySelector(".block-filter__icon").classList.toggle("block-filter__icon_state_active");
if (event.target.classList.contains("block-filter__item")) {
item.querySelector(".block-filter__value").textContent = event.target.textContent;
}
})
})
}
<div class="filter hero__filter">
<form class="filter__form">
<div class="filter__block block-filter">
<div class="block-filter__button">
<div class="block-filter__header">
<span class="block-filter__type">Purpose</span>
<div class="block-filter__icon"></div>
</div>
<span class="block-filter__value">Buy</span>
</div>
<div class="block-filter__dropdown">
<span class="block-filter__item">Buy</span>
<span class="block-filter__item">Sell</span>
</div>
</div>
Sure, just remove the class from the active one first:
item.addEventListener("click", (event) => {
// get active, and if it exists, remove active
document.querySelector(".block-filter__dropdown_state_active")?.classList.remove("block-filter__dropdown_state_active");
item.querySelector(".block-filter__dropdown").classList.toggle(
"block-filter__dropdown_state_active"
);
item.querySelector(".block-filter__icon").classList.toggle(
"block-filter__icon_state_active"
);
if (event.target.classList.contains("block-filter__item")) {
item.querySelector(".block-filter__value").textContent =
event.target.textContent;
}
});
We use ?. here to prevent us from going further (and causing an error) if there is no active dropdown already.
What you need to do is look for a currently active item first and "de-activate" them. You should also check that the currently active item is not the clicked item as you already have logic defined for that.
I've expanded on your snippet to create a solution.
NOTE: It might be useful creating a separate function/s for handling to "activate" and "de-activate" code where you pass in a .block-filter element.
const burgerBtn = document.querySelector(".header__burger"),
menu = document.querySelector(".menu"),
body = document.querySelector(".body"),
filter = document.querySelector(".filter"),
blockFilter = document.querySelectorAll(".block-filter"),
dropdown = document.querySelectorAll(".block-filter__dropdown");
if (filter) {
blockFilter.forEach(item => {
item.addEventListener("click", event => {
const active_dropdown = document.querySelector(".block-filter__dropdown_state_active");
if(active_dropdown !== null){
// get parent until we find ".block-filter"
const active_item = active_dropdown.closest(".block-filter");
// check it's not the current item
if(active_item !== null && active_item !== item){
// apply same logic as below to remove active state
active_item.querySelector(".block-filter__dropdown").classList.remove("block-filter__dropdown_state_active");
active_item.querySelector(".block-filter__icon").classList.remove("block-filter__icon_state_active");
}
}
// your original logic
item.querySelector(".block-filter__dropdown").classList.toggle("block-filter__dropdown_state_active");
item.querySelector(".block-filter__icon").classList.toggle("block-filter__icon_state_active");
if (event.target.classList.contains("block-filter__item")) {
item.querySelector(".block-filter__value").textContent = event.target.textContent;
}
})
})
}
/* base styles */
* {
box-sizing: border-box;
}
html {
font-family: sans-serif;
background-color: #f3f3f3;
}
.filter.hero__filter {
width:600px;
margin:auto;
border: 2px solid #eee;
background-color: #fff;
}
.filter__form {
display:flex;
}
.filter__block {
flex: 1;
padding: 5px;
position: relative;
}
.block-filter__header {
font-weight:600;
font-size:12px;
color: #555;
}
.block-filter__dropdown {
display:none;
position:absolute;
top:100%;
left:0;
right:0;
background-color:#fff;
border: 1px solid #ccc;
box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
border-radius:4px;
}
.block-filter__dropdown_state_active {
display: block;
}
.block-filter__item {
padding: 5px 10px;
display:block;
border-bottom: 1px solid #eee;
}
.block-filter__item:last-child {
border-bottom: none;
}
<div class="filter hero__filter">
<form class="filter__form">
<div class="filter__block block-filter">
<div class="block-filter__button">
<div class="block-filter__header">
<span class="block-filter__type">Purpose</span>
<div class="block-filter__icon"></div>
</div>
<span class="block-filter__value">Buy</span>
</div>
<div class="block-filter__dropdown">
<span class="block-filter__item">Buy</span>
<span class="block-filter__item">Sell</span>
</div>
</div>
<div class="filter__block block-filter">
<div class="block-filter__button">
<div class="block-filter__header">
<span class="block-filter__type">Second</span>
<div class="block-filter__icon"></div>
</div>
<span class="block-filter__value">Alpha</span>
</div>
<div class="block-filter__dropdown">
<span class="block-filter__item">Bravo</span>
<span class="block-filter__item">Charlie</span>
<span class="block-filter__item">Delta</span>
</div>
</div>
</form>
</div>

item.addEventListener runs automatically

I'm learning JS by following Wes Bos's class. I'm trying to select buttons and display information every time the user clicks on them. So I add an event listener, however, the fallback function seems to be executed automatically when it is located inside the event listener. I don't understand why 'hello' is displayed automatically while the function youClickTheButton is executed only when the user clicks on a button (see the below code).
Why does this happen?
const myButtons = document.querySelectorAll('.cards button');
const modalOuter = document.querySelector('.modal-outer');
function youClickTheButton(event) {
console.log(event);
modalOuter.classList.add('open');
}
myButtons.forEach(item => item.addEventListener('click', youClickTheButton));
myButtons.forEach(item => item.addEventListener('click', console.log('hello')));
// whenever you click on the button it will open a pop up with a picture with the description
// whenever you click outside of this pop up it should close itself use .closest()
// populate the modal with name and description of the card so you don't have to modify the .html file
// you could also close it by simply pressing escape
const myButtons = document.querySelectorAll('.cards button');
const modalOuter = document.querySelector('.modal-outer');
function youClickTheButton(event) {
console.log(event);
modalOuter.classList.add('open');
}
myButtons.forEach(item => item.addEventListener('click', youClickTheButton));
myButtons.forEach(item => item.addEventListener('click', console.log('hello')));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title></title>
<link rel="stylesheet" href="../../base.css">
</head>
<body>
<div class="cards">
<div class="card number1" data-description="Wes is cool">
<img src="https://picsum.photos/200?random=1" alt="Wes Bos">
<h2>Wes Bos</h2>
<button>Learn more →</button>
</div>
<div class="card number2" data-description="Scott is neat!">
<img src="https://picsum.photos/200?random=2" alt="Wes Bos">
<h2>Scott Tolinski</h2>
<button>Learn more →</button>
</div>
<div class="card number3" data-description="Kait is beautiful!">
<img src="https://picsum.photos/200?random=3" alt="Wes Bos">
<h2>Kait Bos</h2>
<button>Learn more →</button>
</div>
<div class="card number4" data-description="Snickers is a dog!">
<img src="https://picsum.photos/200?random=4" alt="Wes Bos">
<h2>Snickers the dog</h2>
<button>Learn more →</button>
</div>
</div>
<div class="modal-outer ">
<div class="modal-inner ">
<p>You clicked on the 1st one</p>
</div>
</div>
<style>
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 20px;
padding: 2rem;
}
.card {
background: white;
padding: 1rem;
border-radius: 2px;
}
.card img {
width: 100%;
}
.card h2 {
color: black;
}
.modal-outer {
display: grid;
background: hsla(50, 100%, 50%, 0.7);
position: fixed;
height: 100vh;
width: 100vw;
top: 0;
left: 0;
justify-content: center;
align-items: center;
/* Hide this modal until we need it */
opacity: 0;
pointer-events: none;
transition: opacity 0.2s;
}
.modal-outer img {
width: 100%;
}
.modal-outer.open {
opacity: 1;
pointer-events: all;
}
.modal-inner {
max-width: 600px;
min-width: 400px;
padding: 2rem;
border-radius: 5px;
min-height: 200px;
background: white;
transform: translateY(-200%);
transition: transform 2s;
}
.modal-outer.open .modal-inner {
transform: translateY(0);
}
</style>
<script src="./click-outside_5.js"></script>
</body>
</html>
Check the difference between your two item.addEventListener()s. In the first one, you pass down a function, while in the second one, you call one (no parentheses vs. parentheses).
If you pass down a callback function (i.e. first case), you don't invoke it immediately, you just say that "Here is this function I created, run it every time someone clicks on any of these buttons."
If you want to log from your second function, you need to pass a function, not the result of the function:
myButtons.forEach(item => item.addEventListener('click', () => console.log('hello')))
// OR
function logHello() {
return console.log('hello')
}
myButtons.forEach(item => item.addEventListener('click', logHello));
You can read more about it on MDN.
Anyway, you should not loop over the buttons twice, but I think you're just testing things out at the moment. console.log('hello') could be in your youClickTheButton() function.

Remove ACTIVE classes from all other buttons when I click an other button in vanilla javascript

I want to assign "active" to a button which I clicked on and remove active from the other buttons when I do so, I want to do this in Vanilla JS since I want to practice my skills. I have tried out similar issues on SO, however I can't get my code to work.
Ultimately I want to create a gallery filter for images taken from my DB in PHP which I added to my code as seen bellow based on button which is acive I want to show / hide the categories. The image receive a class = someCategory from the image_category column in my DB.
Help is appreciated.
I've tried to take similar issues under consideration. But I failed to make it work.
Vanilla JS remove class from all other elements besides 'active' class
HTML & PHP CODE:
<div id="category-buttons">
<h5>Choose image category</h5>
<button id="All" class="catgory-button active" >All Categories</button>
<button id="CNC_Machining_button" class="catgory-button">CNC_Machining</button>
<button id="HP_Die_Casting" class="catgory-button">HP Die Casting</button>
<button id="Iron_Casting" class="catgory-button">Iron Casting</button>
<button id="Steel_Casting" class="catgory-button">Steel Casting</button>
<button id="Precision_Casting" class="catgory-button">Precision Casting</button>
<button id="Aluminium_Casting" class="catgory-button">Aluminum Casting</button>
</div>
<section class="gallery-links">
<div class="wrapper">
<h2 class="product-gallery-title">Product Gallery</h2>
<div class="gallery-container">
<?php
include_once 'includes/dbh.inc.php';
$sql = 'SELECT * FROM gallery ORDER BY orderGallery DESC';
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt,$sql)) {
echo 'SQL statement failed!';
} else {
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while ($row = mysqli_fetch_assoc($result)) {
//what's echoed out by the database
echo ' <a class="images '.$row["image_category"].'" style="background-repeat:no-repeat; background-image: url(gallery/'.$row["imgFullNameGallery"].')">
<div class="color-overlay">
<h3>'.$row["titleGallery"].'</h3>
<p>'.$row["descGallery"].'</p>
</div>
</a>';
}
}
?>
</div>
</div>
<?php
JS Code:
let btns = Array.from(document.querySelectorAll('.category-button'));
const handleClick = (e) => {
e.preventDefault();
btns.forEach(node => {
node.classList.remove('active');
});
e.currentTarget.classList.add('active');
}
btns.forEach(node => {
node.addEventListener('click', handleClick)
});
Relevant CSS CODE:
#category-buttons {
float: left;
display: flex;
flex-wrap: wrap;
flex-direction: column;
width: 12.5%;
margin: 10vh 10px;
}
.category-button {
padding: 20px;
margin: 2px 0;;
color: white;
background: rgb(153, 124, 124);
}
.product-gallery-title {
text-transform: uppercase;
}
.wrapper {
text-align: center;
width: 65%;
margin: auto;
}
.gallery-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 13px;
margin: auto;
width: 100%;
background: rgb(236, 236, 236);
justify-content: center;
}
.images{
height: 300px;
width: 300px;
max-width: 300px;
max-height: 300px;
text-decoration: none;
}
Expected Result:
On click, button receives active class and other buttons in scope lose them.
What you could do for example is to store the active button in a global variable and use that variable to remove the class from it when another button is clicked.
So something like this:
let btns = Array.from(document.querySelectorAll('.category_btn'));
let activeButton = null;
// The button which would be used to add 'active' class to
// all the buttons.
let allButton = document.querySelector('#All');
const handleClick = (e) => {
e.preventDefault();
e.currentTarget.classList.add('active');
// Checks that the activeButton is defined (initially it's null).
// Also checks that the button that was clicked is not the button which is
// already active to avoid removing the active class on double click.
if (activeButton != null && activeButton != e.currentTarget) {
activeButton.classList.remove('active');
}
activeButton = e.currentTarget;
}
btns.forEach(node => {
node.addEventListener('click', handleClick)
});
// Listen to a click event from the "allButton" and when it's clicked,
// loop through the buttons array and add 'active' class to all buttons
// in it.
allButton.addEventListener('click', function() {
btns.forEach(btn => {
btn.classList.add('active');
})
});
I'm not currently anywhere where I can test and verify that it works, but I see no reason why it would not work.

Show only a few users and hide others

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>

Categories