I am able to create progress bar with Bootstrap.
I want those numerical values to be displayed below the progress bar but not inside, something like this:
How can we achieve this? Do I need to use any JavaScript graphing libraries?
PS: Note that the main challenge I am facing is to show the numbers below divs, and not with color styling or calculating those numbers.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<div class="container pt-4">
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: 15%;">
15
</div>
<div class="progress-bar bg-success" role="progressbar" style="width: 30%;">
45
</div>
<div class="progress-bar bg-info" role="progressbar" style="width: 20%;">
65
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
One solution would be to add a div below yours and to use some JavaScript
var elements = document.getElementsByClassName('progress-bar');
var count = 0;
var values = document.getElementById('values');
var value = document.createElement('div');
value.innerHTML = "0";
value.style.width = (parseInt(elements[0].style.width.split('%')[0]) - 1.6) + "%"
values.appendChild(value);
for (var i = 0; i < elements.length; i++) {
count += parseInt(elements[i].style.width.split('%')[0]);
//elements[i].innerHTML = count;
var value = document.createElement('div');
value.innerHTML = count;
if (i < elements.length - 1)
value.style.width = parseInt(elements[i + 1].style.width.split('%')[0]) + "%"
else
value.style.width = (100 - count - 4) + "%";
values.appendChild(value);
}
var value = document.createElement('div');
value.innerHTML = "100";
values.appendChild(value);
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous" />
<div class="container">
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: 15%;"></div>
<div class="progress-bar bg-success" role="progressbar" style="width: 30%;"></div>
<div class="progress-bar bg-info" role="progressbar" style="width: 20%;"></div>
</div>
<div id="values" style="display: flex; flex-flow: row wrap;"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
A little CSS whizbang and some pseudo-elements should do. Note that I wrapped the numeric values with spans for positioning. By giving the structure a custom class we can override Bootstrap's styles without using !important, which makes work easier down the road and avoids styling all progress bars.
Also note that Bootstrap provides classes for position, overflow, and border-radius, but I've put those things in the CSS for clarity. I did use border classes on the outer element.
.progress.labels-out,
.progress.labels-out .progress-bar {
position: relative; /* allows positioning of child elements */
overflow: visible; /* lets the child elements be seen */
border-radius: 0;
}
.progress.labels-out .progress-bar span,
.progress.labels-out::before,
.progress.labels-out::after {
position: absolute;
top: calc(100% + 5px); /* shift down the height of the parent plus a bit */
left: 100%;
transform: translateX(-50%); /* shift left half its own width to center */
color: #000;
font-weight: bold;
}
.progress.labels-out::before {
content: '100';
}
.progress.labels-out::after {
content: '0';
left: 0;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<div class="container pt-4">
<div class="progress labels-out border border-2">
<div class="progress-bar" role="progressbar" style="width: 15%;">
<span>15</span>
</div>
<div class="progress-bar bg-success" role="progressbar" style="width: 30%;">
<span>45</span>
</div>
<div class="progress-bar bg-info" role="progressbar" style="width: 20%;">
<span>65</span>
</div>
</div>
</div>
Related
I want to show an horizontal scroll indicator for a scrollable DIV container.
After some testing I'm pretty sure that it's not possible wit pure CSS.
I found a snippet in an answer for a similar question.
Unfortunately I couldn't figure out how to change the script to my needs.
I'm using a simple DIV container with some elements in it.
Here's my code:
<div class="container">
<div class="scroll-wrapper">
<div class="scroll-container">
<ul class="list-inline text-white text-center">
<li class="list-inline-item" style="width: 200px;">
<div class="py-5 bg-dark"><h1 class="py-5">1</h1></div>
</li>
<li class="list-inline-item" style="width: 400px;">
<div class="py-5 bg-dark"><h1 class="py-5">2</h1></div>
</li>
[....]
</ul>
</div>
</div>
<div class="scroll-indicator">
<div class="scroll-indicator-bar"></div>
</div>
<div class="d-flex justify-content-between">
<button>Prev</button>
<button>Next</button>
</div>
</div>
And the CSS:
.scroll-wrapper {
width: 100%;
overflow-x: scroll;
overflow-y: hidden;
position: relative;
white-space: nowrap;
}
.scroll-indicator {height: 4px; width: 100%; background-color: #ddd; margin-bottom: 2rem;}
.scroll-indicator-bar {height: 4px; width: 20%; background-color: #000;}
Working example
Is there any way to animate the scrollbar indicator with CSS and/or jQuery?
EDIT: I found another good example here: https://codepen.io/mahish/pen/RajmQw
I tried to use the code in my example but the prev/next buttons doesn't work. And I also don't know how to use the scroll position to show and move a scroll indicator.
Here's the JS code from the example (change to my class names):
// duration of scroll animation
var scrollDuration = 300;
// paddles
var leftPaddle = document.getElementsByClassName('left-paddle');
var rightPaddle = document.getElementsByClassName('right-paddle');
// get items dimensions
var itemsLength = $('.item').length;
var itemSize = $('.item').outerWidth(true);
// get some relevant size for the paddle triggering point
var paddleMargin = 20;
// get wrapper width
var getMenuWrapperSize = function() {
return $('.scroll-wrapper').outerWidth();
}
var menuWrapperSize = getMenuWrapperSize();
// the wrapper is responsive
$(window).on('resize', function() {
menuWrapperSize = getMenuWrapperSize();
});
// size of the visible part of the menu is equal as the wrapper size
var menuVisibleSize = menuWrapperSize;
// get total width of all menu items
var getMenuSize = function() {
return itemsLength * itemSize;
};
var menuSize = getMenuSize();
// get how much of menu is invisible
var menuInvisibleSize = menuSize - menuWrapperSize;
// get how much have we scrolled to the left
var getMenuPosition = function() {
return $('.scroll-container').scrollLeft();
};
// finally, what happens when we are actually scrolling the menu
$('.scroll-container').on('scroll', function() {
// get how much of menu is invisible
menuInvisibleSize = menuSize - menuWrapperSize;
// get how much have we scrolled so far
var menuPosition = getMenuPosition();
var menuEndOffset = menuInvisibleSize - paddleMargin;
// show & hide the paddles
// depending on scroll position
if (menuPosition <= paddleMargin) {
$(leftPaddle).addClass('hidden');
$(rightPaddle).removeClass('hidden');
} else if (menuPosition < menuEndOffset) {
// show both paddles in the middle
$(leftPaddle).removeClass('hidden');
$(rightPaddle).removeClass('hidden');
} else if (menuPosition >= menuEndOffset) {
$(leftPaddle).removeClass('hidden');
$(rightPaddle).addClass('hidden');
}
// print important values
$('#print-wrapper-size span').text(menuWrapperSize);
$('#print-menu-size span').text(menuSize);
$('#print-menu-invisible-size span').text(menuInvisibleSize);
$('#print-menu-position span').text(menuPosition);
});
// scroll to left
$(rightPaddle).on('click', function() {
$('.scroll-container').animate( { scrollLeft: menuInvisibleSize}, scrollDuration);
});
// scroll to right
$(leftPaddle).on('click', function() {
$('.scroll-container').animate( { scrollLeft: '0' }, scrollDuration);
});
You can have your own custom horizontal scroll behavior with vanilla js, you just need to handle mousedown, mouseup and mousemove events, calculate the needed scroll value and move your elements using transform: translateX() style, and to keep track with these values,
I did some changes and added some js code, check the snippet bellow:
const scrollBar = document.getElementById('myBar');
const scrollBarWrapper = document.getElementById('barWrapper');
const scrollContent = document.getElementById('scroll-container');
scrollBar.style.width = ((scrollContent.offsetWidth * scrollBarWrapper.offsetWidth) / scrollContent.scrollWidth) + 'px';
let isScrolling = false;
let cursorX = 0;
let translateXValue = 0;
scrollBar.addEventListener('mousedown', function(e) {
e.preventDefault();
isScrolling = true;
cursorX = e.clientX;
});
document.addEventListener('mouseup', function(e) {
if (isScrolling) {
e.preventDefault();
isScrolling = false;
translateXValue += (e.clientX - cursorX);
}
});
document.addEventListener('mousemove', function(e) {
if (isScrolling && cursorX !== e.clientX) {
e.preventDefault();
const translateAmount = (translateXValue + (e.clientX - cursorX));
const scrollLength = (barWrapper.offsetWidth - scrollBar.offsetWidth);
const barScroll = Math.min(Math.max(0, translateAmount), scrollLength);
const contentTranslateRatio = (barScroll * scrollContent.scrollWidth) / scrollContent.offsetWidth;
scrollBar.style.transform = 'translateX(' + barScroll + 'px)';
scrollContent.style.transform = 'translateX(' + -contentTranslateRatio + 'px)';
}
});
.scroll-wrapper {
width: 100%;
overflow: hidden;
position: relative;
white-space: nowrap;
}
.scroll-indicator {height: 6px; width: 100%; background-color: #ddd; margin-bottom: 2rem;}
.scroll-indicator-bar {height: 6px; width: 20%; background-color: #000;}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container" id="container">
<div class="scroll-wrapper">
<div class="scroll-container" id="scroll-container">
<ul class="list-inline text-white text-center">
<li class="list-inline-item" style="width: 200px;">
<div class="py-5 bg-dark"><h1 class="py-5">1</h1></div>
</li>
<li class="list-inline-item" style="width: 400px;">
<div class="py-5 bg-dark"><h1 class="py-5">2</h1></div>
</li>
<li class="list-inline-item" style="width: 300px;">
<div class="py-5 bg-dark"><h1 class="py-5">3</h1></div>
</li>
<li class="list-inline-item" style="width: 150px;">
<div class="py-5 bg-dark"><h1 class="py-5">4</h1></div>
</li>
<li class="list-inline-item" style="width: 250px;">
<div class="py-5 bg-dark"><h1 class="py-5">5</h1></div>
</li>
<li class="list-inline-item" style="width: 300px;">
<div class="py-5 bg-dark"><h1 class="py-5">6</h1></div>
</li>
<li class="list-inline-item" style="width: 200px;">
<div class="py-5 bg-dark"><h1 class="py-5">7</h1></div>
</li>
<li class="list-inline-item" style="width: 400px;">
<div class="py-5 bg-dark"><h1 class="py-5">8</h1></div>
</li>
<li class="list-inline-item" style="width: 300px;">
<div class="py-5 bg-dark"><h1 class="py-5">9</h1></div>
</li>
</ul>
</div>
</div>
<div class="scroll-indicator" id="barWrapper">
<div class="scroll-indicator-bar" id="myBar"></div>
</div>
<div class="d-flex justify-content-between">
<button>Prev</button>
<button>Next</button>
</div>
</div>
by this code you have a dynamic scrollbar width dynamic width based on the content, and you can manage your own scroll behavior,
then, you can add custom next() and previous() functions to add translate for both scrollbar and content, as implemented in mousemove handler
I found a solution by using SimpleBar: https://github.com/Grsmto/simplebar/tree/master/packages/simplebar
I have a series of images i'd liike to output per row. I ned these image to take up the ful width of each row in question. The only way I can think to to do this is by calculating the combined widths of the images vs container width. Then use the pecenateg difference to reduce the image widths.
I have this working nearly 100% as expected, but the images do not quite fill the space in some cases. There must be a flaw in my logic as this should always fit the space based on the calculations.
As you can see from the example below, the images do not quite line up in the righthand side. I think the flaw in my logic is on this line return imageWidths + (60 * imgs.length);
Demo: http://jsfiddle.net/rev3tsuf/5/
JS:
function processImageRows(className, containerWidth) {
let imgWidths = getImageWidthCombines(className);
// initiate image width setting if too large for container
if (imgWidths > containerWidth) {
let percent = Math.ceil((containerWidth / imgWidths) * 100);
getImageWidthCombines(className, percent);
}
}
function getImageWidthCombines(className, percent = false) {
// loop through images for given row and return combined width
let imgs = document.querySelectorAll(`#image-wrapper .${ className } img.set-img`);
let imageWidths = 0;
imgs.forEach(function(el, index) {
if (percent) {
// if percentage is set that means we now set the widths as opposed to return their value
el.style.width = `${Math.floor(el.width * (percent / 100))}px`;
} else {
el.style.width = null;
imageWidths += el.offsetWidth;
}
});
// ??? needs 60 added otherwsie doesn't get right percentage.
return imageWidths + (60 * imgs.length);
}
HTML:
<div class="container">
<div class="row row-1">
<div class="col-auto">
<img src="https://via.placeholder.com/400x473.png" />
</div>
... more images
</div>
<div class="row row-2">
<div class="col-auto">
<img src="https://via.placeholder.com/473x473.png" />
</div>
... more images
</div>
<div class="row row-3">
<div class="col-auto">
<img src="https://via.placeholder.com/578x473.png" class="set-img" />
</div>
... more images
</div>
</div>
I also have a window resize event that triggers the above process, but i've left that out of the example in order to keep it simple.
Any help would be greatly appreciated. It's taken me two days to get this far, and half a day stuck on this one issue, now i'm completely stuck with nothing more to try.
EDIT
To adjust your work just customize CSS class as below:
.row {
margin-right: -4px;
margin-left: -4px;
}
.row .col-auto:first-child{
margin-left: 0!important; /* ADDED */
}
.row .col-auto:last-child{
margin-right: 0 !important; /* ADDED */
}
.row .col-auto{
margin-left: auto; /* ADDED */
margin-right:auto; /* ADDED */
}
.col-auto {
padding-right: 4px !important; /* ADDED !important */
padding-left: 4px !important; /* ADDED !important */
padding-bottom: 8px;
position: relative;
overflow: hidden;
cursor: pointer;
}
DEMO with JS CODE your code:
function processImageRows(className, containerWidth) {
let imgWidths = getImageWidthCombines(className);
// initiate image width setting if too large for container
if (imgWidths > containerWidth) {
let percent = Math.ceil((containerWidth / imgWidths) * 100);
getImageWidthCombines(className, percent);
}
}
function getImageWidthCombines(className, percent = false) {
// loop through images for given row and return combined width
let imgs = document.querySelectorAll(`#image-wrapper .${ className } img.set-img`);
let imageWidths = 0;
imgs.forEach(function(el, index) {
if (percent) {
// if percentage is set that means we now set the widths as opposed to return their value
el.style.width = `${Math.floor(el.width * (percent / 100))}px`;
} else {
el.style.width = null;
imageWidths += el.offsetWidth;
}
});
// ??? needs 60 added otherwsie doesn't get right percentage.
return imageWidths + (60 * imgs.length);
}
// this is called after each image load
function checkLoadingProgress() {
let containerWidth = document.getElementById('image-wrapper').clientWidth;
let imgsTotal = 0;
let imgsLoaded = 0;
// loop through rows
['row-1', 'row-2', 'row-3'].forEach(function(el, index) {
imgsTotal = document.querySelectorAll(`#image-wrapper .${el} img.set-img`).length;
imgsLoaded = document.querySelectorAll(`#image-wrapper .${el} img.set-img.image-loaded`).length;
// only process is all images have loaded for the given row
if (imgsLoaded > 0 && imgsLoaded == imgsTotal) {
processImageRows(el, containerWidth);
}
});
// finally all images have loaded. Updated loading class on container
let allImgsTotal = document.querySelectorAll(`#image-wrapper img.set-img`).length;
let allImgsLoaded = document.querySelectorAll(`#image-wrapper img.set-img.image-loaded`).length;
if (allImgsTotal == allImgsLoaded) {
document.getElementById('image-wrapper').classList.add('image-loaded');
document.getElementById('image-wrapper').classList.remove('image-loading');
}
}
// bind onload event to images
let imgs = document.querySelectorAll('img.set-img');
imgs.forEach(function(el, index) {
el.addEventListener('load', function() {
this.classList.add('image-loaded');
checkLoadingProgress();
}, false);
});
body {
margin: 10px;
}
.row {
margin-right: -4px;
margin-left: -4px;
}
.row .col-auto:first-child{
margin-left: 0!important; /* ADDED */
}
.row .col-auto:last-child{
margin-right: 0 !important; /* ADDED */
}
.row .col-auto{
margin-left: auto; /* ADDED */
margin-right:auto; /* ADDED */
}
.col-auto {
padding-right: 4px !important; /* ADDED !important */
padding-left: 4px !important; /* ADDED !important */
padding-bottom: 8px;
position: relative;
overflow: hidden;
cursor: pointer;
}
.image-wrapper.images-loading .col-auto {
position: absolute;
top: 0;
left: 0;
}
.image-wrapper.images-loaded .col-auto img {
max-width: 100%;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
<div class="container">
<div id="image-wrapper" class="images-loading">
<div class="row row-1">
<div class="col-auto">
<img src="https://via.placeholder.com/400x473.png" class="set-img" />
</div>
<div class="col-auto">
<img src="https://via.placeholder.com/578x473.png" class="set-img" />
</div>
<div class="col-auto">
<img src="https://via.placeholder.com/578x473.png" class="set-img" />
</div>
<div class="col-auto">
<img src="https://via.placeholder.com/400x473.png" class="set-img" />
</div>
</div>
<div class="row row-2">
<div class="col-auto">
<img src="https://via.placeholder.com/473x473.png" class="set-img" />
</div>
<div class="col-auto">
<img src="https://via.placeholder.com/1042x473.png" class="set-img" />
</div>
<div class="col-auto">
<img src="https://via.placeholder.com/473x473.png" class="set-img" />
</div>
</div>
<div class="row row-3">
<div class="col-auto">
<img src="https://via.placeholder.com/578x473.png" class="set-img" />
</div>
<div class="col-auto">
<img src="https://via.placeholder.com/474x473.png" class="set-img" />
</div>
<div class="col-auto">
<img src="https://via.placeholder.com/578x473.png" class="set-img" />
</div>
</div>
</div>
</div>
BEFORE EDIT:
From the point you know the container size or use flex box, no need to have js, you can simply use CSS by fixing a container as below:
.flexible-container{
max-height: 100%;
overflow:hidden;
position: relative;
}
And then set img with class w-100 and the below CSS:
.flexible-container img{
position: absolute;
left:50%;
top:50%;
transform: translate(-50%, -50%);
}
Images size will be respected and won't be stretch as the extra height will be hidden by container overflow: hidden;.
With class col so automatic width as you seems to have you are grid, pretty much either use grid directly or customize flex class as below:
.flex-15{
flex:1 1 15% !important;
}
.flex-30{
flex:1 1 30% !important;
}
DEMO:
.row-1, .row-2, .row-3{
height: 20vh;
margin-bottom: 10px;
}
.flexible-container{
max-height: 100%;
overflow:hidden;
position: relative;
}
.flexible-container img{
position: absolute;
left:50%;
top:50%;
transform: translate(-50%, -50%);
margin: 1px;
}
.flex-15{
flex:1 1 15% !important;
}
.flex-30{
flex:1 1 30% !important;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<div class="container">
<div class="row row-1">
<div class="col flexible-container">
<img class="w-100" src="https://via.placeholder.com/400x473.png" />
</div>
<div class="col flex-15 flexible-container">
<img class="w-100" src="https://via.placeholder.com/578x473.png" />
</div>
<div class="col flex-15 flexible-container">
<img class="w-100" src="https://via.placeholder.com/578x473.png" />
</div>
<div class="col flexible-container">
<img class="w-100" src="https://via.placeholder.com/400x473.png" />
</div>
</div>
<div class="row row-2">
<div class="col flexible-container">
<img class="w-100" src="https://via.placeholder.com/473x473.png" class="set-img" />
</div>
<div class="col flexible-container flex-30">
<img class="w-100" src="https://via.placeholder.com/1042x473.png" class="set-img" />
</div>
<div class="col flexible-container">
<img class="w-100" src="https://via.placeholder.com/473x473.png" class="set-img" />
</div>
</div>
<div class="row row-3">
<div class="col flexible-container flex-15">
<img class="w-100" src="https://via.placeholder.com/578x473.png" class="set-img" />
</div>
<div class="col flexible-container">
<img class="w-100" src="https://via.placeholder.com/473x473.png" class="set-img" />
</div>
<div class="col flexible-container flex-15">
<img class="w-100" src="https://via.placeholder.com/578x473.png" class="set-img" />
</div>
</div>
</div>
I have 2 divs that I need a shade over after a user action. The divs are just two divs next to each other:
<div class="bought">content</div>
<div class="class2">content</div>
Here is the CSS which is made visible via jQuery:
#view-hint .body > .img .bought {
display:none;
cursor:pointer;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index:2;
background: rgba(0,0,0,0.75);
}
When the event fires this is what it looks like:
That bottom white area needs to be covered dynamically as well.
The approach I thought to take was to wrap both div's in another div but it breaks the look of everything. So I tried to make the top div longer based off size but it's still not perfect...
var originalHeight = $('.bought').height();
var windowWidth = $(window).width();
if (windowWidth < 710) {
$('.bought').css('height', originalHeight * 0.6);
} else if (windowWidth > 710 && windowWidth < 1000) {
$('.bought').css('height', originalHeight * 0.698);
} else if (windowWidth > 1000 && windowWidth < 1300) {
$('.bought').css('height', originalHeight * 0.699);
} else if (windowWidth > 1300 && windowWidth < 1600) {
$('.bought').css('height', originalHeight * 0.865);
} else if (windowWidth > 1600 && windowWidth < 2000) {
$('.bought').css('height', originalHeight * 1.035);
} else {
$('.bought').css('height', "662px");
}
This mostly works for all size screens, but if you change the zoom it still causes issues.
How can I make it where both of these divs are covered by the CSS dynamically?
Edit:
Here is the full HTML with an added wrapper and an image that results:
<div id="test123">
<div class="bought">
<div class="row">
<div class="col">
<div class="body">
<?php if(Request::is('user/*')) { ?>
<div id="boughtquestion">Did you buy this for <?php echo $user->firstName ?>?</div>
<div class="options">
<!-- <a id="boughtyes" class="cbutton whiteonpurple" onclick="markPurchased(event)">Yes</a> -->
<a id="boughtyes" class="cbutton whiteonpurple">Yes</a>
<a id="boughtno" class="cbutton whiteonpurple">No</a>
</div>
<?php } else { ?>
<div>Bought?</div>
<p>Click here to send hinters a message to let them know.<br />And yes, it can still be a surprise!</p>
<?php } ?>
</div>
</div>
</div>
</div>
<div class="markedaspurchased">
<div class="row">
<div class="col">
<div class="body">
<div id="markedpurchased">Marked as Purchased</div>
<p id="markedmessage">Marking as purchased prevents duplicate gift giving. Dont worry <?php echo $user->firstName ?> doesn't get notified but you can let <?php echo ($user->gender == 'female' ? 'him' : 'her') ?> know by sending a message!</p>
<p><a id="sendmessagebutton" class="cbutton whiteonpurple purchasebutton">Send message to let them know</a></p>
<p><a id="anonymousbutton" class="cbutton whiteonpurple purchasebutton">Send anonymous message</a></p>
<p><a id="secretbutton" class="cbutton whiteonpurple purchasebutton">Keep it a secret</a></p>
</div>
</div>
</div>
</div>
</div>
<p class="description"></info-coverp>
<div class="options">
<a class="buy cbutton whiteonpurple" target="_blank">Buy</a>
<a class="hint cbutton whiteonblack" target="_blank">Hint</a>
</div>
<div class="info">
<div class="bar"></div>
<div class="rehints">10 REHINTS</div>
<div class="hinter">
<div class="picture monophoto">
<div class="text">BO</div>
<div class="img" style="background-image: url();" onclick=""></div>
</div>
<div class="content">
<div class="one">Hinted by:</div>
<div class="two"></div>
</div>
</div>
<div class="partnertext">Partnered Hint</div>
<div style="clear:both;"></div>
</div>
</div>
Since you're using Jquery, why not give the divs a separate class and then use .wrapAll to create a wrapper...then position the overlay on top of that.
$(".wrapped").wrapAll('<div class="overlay" />');
.overlay {
display: inline-block;
position: relative;
}
.overlay::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapped bought">content 1</div>
<div class="wrapped class2">content 2</div>
Trying to get this progress bar on Bootstrap to show real-time progress from a JSON API, while also showing the % of goal achieved:
Here is how it looks right now: http://puu.sh/jt2Gu/823f6a6a0f.png
Both progress bars should be centered on the page and the progress itself isnt updating and I'm not sure why, please help?
progress bar for coins sold
progress bar for amount raised
% funded (should be on top of picture)
CSS:
}
.progress {
position: absolute;
top: 80%;
z-index: 2;
text-align: center;
width: 50%;
}
HTML:
<div class="container">
<div class="banner-buynow">
<div class="col-md-2 col-md-offset-3 object-non-visible"
data-animation-effect="fadeIn">
<a class="btn btn-info" href="javascript:void(0);" onclick=
"opentac();">Buy Now<br>
<div class="ratebtc"></div></a>
</div>
<div class="progress">
<div class="progress-bar active progress-bar-striped active">
<div class="percentage-label"></div>
</div>
</div>
</div>
<div class="progress">
<div class=
"progress-bar progress-bar-success progress-bar-striped active"
style="width:1%">
<div class="goal-label"></div>
</div>
</div>
</div>
<div class="funded-label"></div>
JS
$.getJSON("https://www2.shapeshift.io/crowdsales", function (json) {
var soldT = Math.round(json.sold);
var left = json.remaining;
var total = Math.round(soldT+left);
var ratebtc = json.rateT;
var percent = Math.round(soldT/total*100);
var backers = json.orders;
var raisedtotal = Math.round(json.raised) + ' BTC';
var goal = Math.round(raisedtotal/730);
var percentsold = Math.round(percent) + '%';
var backers = json.orders + ' backers';
var funded = Math.round(json.raised/730*100);
$('.progress-bar').css('width', percentsold);
$('.percentage-label').html(soldT + " coins sold ");
$('.ratebtc').html(ratebtc );
$('.backers').html(raisedtotal + " from " + backers );
$('.progress-bar-success').css('width', goal);
$('.goal-label').html(raisedtotal + " towards goal of 730 BTC");
$('.funded-label').html(funded + " % funded");
});
JSFiddle: https://jsfiddle.net/qy1ko5xf/
you can add the div with the class funded-label inside the container if you want it to be at the bottom of the container. give it an absolute position.
here's the updated HTML
<div class="container">
<div class="banner-buynow">
<div class="col-md-2 col-md-offset-3 object-non-visible"
data-animation-effect="fadeIn">
<a class="btn btn-info" href="javascript:void(0);" onclick=
"opentac();">Buy Now<br>
<div class="ratebtc"></div></a>
</div>
<br/>
<div class="progress">
<div class="progress-bar active progress-bar-striped active">
<div class="percentage-label"></div>
</div>
</div>
</div>
<div class="progress">
<div class=
"progress-bar progress-bar-success progress-bar-striped active"
style="width:1%">
<div class="goal-label"></div>
</div>
</div>
<div class="funded-label"></div>
</div>
the CSS for the funded-label div should look like this
.funded-label{
color: white;
font-weight: bold;
position: absolute;
bottom: 0px;
background-color: #003a74;
width: 100%;
text-align: left;
padding: 5px;
}
and finally here' the updated JS
$(function(){
$.getJSON("https://www2.shapeshift.io/crowdsales", function (json) {
console.log(json);
var soldT = Math.round(json.sold);
var left = json.remaining;
var total = Math.round(soldT+left);
var ratebtc = json.rateT;
var percent = Math.round(soldT/total*100);
var backers = json.orders;
var raised = Math.round(json.raised);
var raisedtotal = raised + ' BTC';
var goal = Math.round((raised/730) * 100);
console.log(goal);
var percentsold = Math.round(percent) + '%';
var backers = json.orders + ' backers';
var funded = Math.round(raised/730*100);
$('.progress-bar').css('width', percentsold);
console.log(soldT);
console.log(total);
$('.percentage-label').html(soldT + " coins sold ");
$('.ratebtc').html(ratebtc );
$('.backers').html(raisedtotal + " from " + backers );
$('.progress-bar-success').css('width', goal + '%');
$('.goal-label').html(raisedtotal + " towards goal of 730 BTC");
$('.funded-label').html(funded + " % funded");
});
});
here's a working JSFIDDLE. hope this helps.
Please take a look at this:
http://jsfiddle.net/SHfz4/
Technically all those blue boxes are visible as in none are displayed as none so I can't use something like this:
$('.row .inner .item:visible:last');
Because that will give box 27 each time.
As you can see some boxes are visible and other's are not depending on the size of your view port, resizing will cause more boxes to go out of view or come into view.
I need a way to get the last visible item in a row. How to do this?
P.S. I have been snippets posted here on SO that show how to tell if an element is in view but some of those scripts were returning true even when they shouldn't and all of them required a specific element to be checked against, but my case requires me to just ask for the last and not specifically test a given element.
CSS:
.row { border: 1px solid red; height: 50px; overflow: hidden; }
.row .inner { width: 1000px; }
.row .inner .item { box-shadow: inset 0 0 8px blue; width: 50px; height: 50px; float: left; line-height: 50px; }
HTML:
<div class="row">
<div class="inner">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
<div class="item item-7">7</div>
<div class="item item-8">8</div>
<div class="item item-9">9</div>
<div class="item item-10">10</div>
<div class="item item-11">11</div>
<div class="item item-12">12</div>
<div class="item item-13">13</div>
<div class="item item-14">14</div>
<div class="item item-15">15</div>
<div class="item item-16">16</div>
<div class="item item-17">17</div>
<div class="item item-18">18</div>
<div class="item item-19">19</div>
<div class="item item-20">20</div>
<div class="item item-21">21</div>
<div class="item item-22">22</div>
<div class="item item-23">23</div>
<div class="item item-24">24</div>
<div class="item item-25">25</div>
<div class="item item-26">26</div>
<div class="item item-27">27</div>
</div>
</div>
Does this snippet do what you expect?
var items = document.querySelectorAll('div[class^=item]')
,row = items[0].offsetParent
,rightBoundary = row.clientLeft+row.clientWidth
,bottomBoundary = row.clientTop+row.clientHeight
,found = null;
for (var i=0;i<items.length;i+=1){
if (items[i].offsetLeft > rightBoundary ||
items[i].offsetTop > bottomBoundary){
found = items[i-1];
break;
}
}
// reports div.item item-17
See this fork of your jsFiddle
[edit] added a check for [invisible] items below the first row of items, see the full screen version of the jsFiddle
var timeout = '';
$(window).resize(function () {
clearTimeout(timeout);
timeout = setTimeout(function () {
var $row = $('.row'),
rWidth = $row.width(),
$item = $row.find('.item').filter(function () {
var $this = $(this),
l = $this.width() + $this.position().left;
return l >= rWidth;
}).first();
}, 60);
}).resize();
http://jsfiddle.net/EkA3K/