Dynamically cover 2 divs with CSS - javascript

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>

Related

Modal Window on card click JS CSS PHP

So I have 6 cards on my html. Each one on click need to pop up a modal window (this modal window is the card with more informations, so each modal window is corresponding to one card).
I dont know how to do that. After a day searching on the web I'm here to ask your help.
I have tried to make the html animal_card, and my modal appart. Then all the content will change with php.
And the Javascript need to change the modal window css property to absolute on click.
Someone know how to do that with Javascript ?
HTML :
<div class="animal_card">
<div class="card_title">
<h3>title</h3>
</div>
<div class="card_image">
<img src="image.img" alt="">
</div>
<div class="card_text">
<div class="card_info">
<div class="card_info_age">
<h4>Age</h4>
<p>14</p>
</div>
<div class="card_info_gender">
<h4>Gender :</h4>
<p>Female</p>
</div>
</div>
<h4>Who am I</h4>
<p>Description Text</p>
</div>
</div>
<div class="bg-modal">
<div class="modal-content">
<div class="modal-animal">
<h1>Animal Name</h1>
<button class="close" onclick="closeModal()">&times</button>
<div><img src="img/greciaprofile.jpg" alt=""></div>
<div class="animal-informations">
<div class="left">
<label for="">Age</label>
<p>14</p>
<label for="">Sexe</label>
<p>Female</p>
</div>
<div class="right">
<label for="">Description</label>
<p>
Text
</p>
</div>
</div>
<div>
<button class="main">Adopt</button>
<button class="secondary">Support</button>
</div>
</div>
</div>
</div>
CSS :
.bg-modal {
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.7);
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: center;
}
.modal-content {
position: absolute;
margin-top: 5rem;
width: 75vw;
background-color: $white;
border-radius: 15px;
}
Javascript :
const cards = document.querySelectorAll('.animal_card');
const modal = document.getElementsByClassName('bg-modal');
const onCardClick = async (e) => {
const card = e.currentTarget;
modal.style.position = 'absolute';
}
cards.forEach(card => card.addEventListener('click', onCardClick));
function closeModal() {
modal[0].style.position = 'none';
}
const cards = document.querySelectorAll('.animal_card');
const modal = document.getElementsByClassName('bg-modal');
const getKeyMap = (modal) => {
if (modal) {
let i;
let keyMap = {};
for (i = 0; i < modal.length; i++) {
const item = modal[i];
const key = item.getAttribute('key');
keyMap[key] = item;
}
return keyMap;
}
return null;
};
const modalMap = getKeyMap(modal);
const onCardClick = async (e) => {
const card = e.currentTarget && e.currentTarget.getAttribute('key') || null;
const selectedModal = modalMap[card] || null;
if (selectedModal) {
selectedModal.style.position = 'absolute';
}
}
cards.forEach(card => card.addEventListener('click', onCardClick));
.bg-modal {
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.7);
/* position: absolute; */
top: 0;
left: 0;
display: flex;
justify-content: center;
}
.modal-content {
position: absolute;
margin-top: 5rem;
width: 75vw;
background-color: $white;
border-radius: 15px;
}
<div key="5" class="animal_card">
<div class="card_title">
<h3>title</h3>
</div>
<div class="card_image">
<img src="image.img" alt="">
</div>
<div class="card_text">
<div class="card_info">
<div class="card_info_age">
<h4>Age</h4>
<p>14</p>
</div>
<div class="card_info_gender">
<h4>Gender :</h4>
<p>Female</p>
</div>
</div>
<h4>Who am I</h4>
<p>Description Text</p>
</div>
</div>
<div class="bg-modal" key="5">
<div class="modal-content">
<div class="modal-animal">
<h1>Animal Name</h1>
<button class="close">&times</button>
<div><img src="img/greciaprofile.jpg" alt=""></div>
<div class="animal-informations">
<div class="left">
<label for="">Age</label>
<p>14</p>
<label for="">Sexe</label>
<p>Female</p>
</div>
<div class="right">
<label for="">Description</label>
<p>
Text
</p>
</div>
</div>
<div>
<button class="main">Adopt</button>
<button class="secondary">Support</button>
</div>
</div>
</div>
</div>
So the direct answer using your example is modal on the onCardClick is returning a collection, not a single element. So selecting the first one modal[0] will fix the position update. I attached an example.
If you are going to show different modals based on the card you click on, you generally need to have a method to track them. Really depends on how you want to do that, based on ids, or index position or so on. Anyways, let me know if this helps.

Programatically setting images widths based on container width

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>

Limit count of elements in div

I have div with questions
Here is it
Here is code for it
<div class="listdivright">
<div style="height: 80%; width: 100%; overflow: auto">
#foreach (var item in Model)
{
<div class="title" style="margin-top:15px;margin-left:15px; margin-bottom: 10px;">
<img class="click" src="#Url.Content("~/Images/plus_plus.png")" />
<span>
#Html.TextBoxFor(modelItem => item.question, new {#class="testclass", #readonly = "readonly" })
</span>
<a class="click2" style="margin-left:10px;">
<img src='#Url.Content("~/Images/arrow.png")' />
</a>
<a style="margin-left:25px;" href='#Url.Action("Edit", "Questions", new {id = item.QuestionId})'>
<img src='#Url.Content("~/Images/Edit.png")' />
</a>
<a href='#Url.Action("Delete", "Questions", new {id = item.QuestionId})'>
<img src='#Url.Content("~/Images/Delete.png")' />
</a>
</div>
<div class="content" style="margin-left:60px; width: 80%; height: 100px; background: white">
<div style="width: 100%">
<div style="float:left; width: 50%;">
<b>#Html.LabelFor(modelItem=>item.TimeForAnswer)</b>
<b>:</b>
<span>#Html.DisplayFor(modelItem=>item.TimeForAnswer)</span>
</div>
<div style="float:right;width: 50%;">
<b>#Html.LabelFor(modelItem => item.TimeForReady)</b>
<b>:</b>
<b>#Html.DisplayFor(modelItem => item.TimeForReady)</b>
</div>
</div>
<div style="width: 100%; text-align: center;" >
<b>#Html.LabelFor(modelItem => item.Retries)</b>
<b>:</b>
<b>#Html.DisplayFor(modelItem => item.Retries)</b>
</div>
</div>
}
</div>
I use JS to move block to left div
Code of JS script
<script type="text/javascript" >
$('.title').on('click', function () {
$(this).next().toggle();
});
$('.click2').click(function () {
var elem = $(this).closest('.title');
$('.title2').append($(elem).html()).show();
});
Here is code of left div
<div class="listdivleft">
<div style="height: 80%; width: 100%; overflow: auto">
<div class="title2" style="margin-top: 15px; margin-left: 15px; margin-bottom: 15px;padding-top: 10px">
</div>
</div>
</div>
I need to limit blocks in left div. From 0 to 10.
So it can be 0 or not more than 10
How I can do this?
You can check that if element with class title are less than 10 using length property, in that case only the new html should be appended, something like:
if($(".title").length < 10) {
var elem = $(this).closest('.title');
$('.title2').append($(elem).html()).show();
}
else {
alert("No more than 10 allowed.");
}
or if title class is reused other places as well on page, then restrict it to current parent element using listdivright class element in combination with closest and find :
if($(this).closest(".listdivright").find(".title").length < 10) {
var elem = $(this).closest('.title');
$('.title2').append($(elem).html()).show();
}
else {
alert("No more than 10 allowed.");
}
Hope it helps and gives you idea how it can be done.

Creating a star rating from an image based on a float number?

recently I have wanted to turn a number into a star rating and I stumbled upon this post here: https://stackoverflow.com/a/1987545/1871869 which is exactly what I wanted to do. I have followed this explanation but I can't seem to get it to work on my local environment, and I was wondering if someone could help me out. Here is my attempt:
$.fn.stars = function() {
return $(this).each(function() {
// Get the value
var val = parseFloat($(this).html());
// Make sure that the value is in 0 - 5 range, multiply to get width
var size = Math.max(0, (Math.min(5, val))) * 16;
// Create stars holder
var $span = $('<span />').width(size);
// Replace the numerical value with stars
$(this).html($span);
});
}
$(function() {
console.log("Calling stars()");
$('.results-contents span.stars').stars();
});
.results {
font-size: 0;
padding-bottom: 16px;
}
.results-content {
font-size: 13px;
display: inline-block;
margin-left: 20px;
vertical-align: top;
}
.results .results-content span.stars span.stars span {
background: url('/resources/graphics/stars-icons.png') 0 -36px repeat-x;
width: 175px;
height: 80px;
}
.results .results-content span.stars {
max-width: 80px;
background-position: 0 0;
}
<script type="text/template" id="results-template">
<div class="results">
<div class="results-content">
<span class="stars">4.0</span>
</div>
</div>
</script>
Image of stars:
What I wanted to do was to simply have the empty stars show, and then based on the rating, show the orange stars on top of the empty stars so that I can show full and half star ratings. However, all I get is a number to show up. My console.log above seems to be called but it seems like the actual rendering of the image and calculation of the star rating is not working. Any help would be appreciated. Thanks!
You had multiple issues from CSS styles being wrong to your selector being wrong. Below is not perfect, but it is rendering.
$.fn.stars = function() {
return this.each(function() {
// Get the value
var val = parseFloat($(this).html());
// Make sure that the value is in 0 - 5 range, multiply to get width
var size = Math.max(0, (Math.min(5, val))) * 36.5;
// Create stars holder
var $span = $('<span> </span>').width(size);
// Replace the numerical value with stars
$(this).empty().append($span);
});
}
$(function() {
console.log("Calling stars()");
$('.results-content span.stars').stars();
});
.results {
font-size: 0;
padding-bottom: 16px;
}
.results-content {
font-size: 13px;
display: inline-block;
margin-left: 20px;
vertical-align: top;
background: url('https://i.stack.imgur.com/rwkqF.png') 0 0 repeat-x;
width: 185px;
height: 35px;
}
.results .results-content span.stars span {
background: url('https://i.stack.imgur.com/rwkqF.png') 0 -36px repeat-x;
display: inline-block;
height: 35px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="results">
<div class="results-content">
<span class="stars">0.0</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">0.5</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">1.0</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">1.5</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">2.0</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">2.0</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">2.5</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">3.0</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">3.5</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">4.0</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">4.5</span>
</div>
</div>
<div class="results">
<div class="results-content">
<span class="stars">5.0</span>
</div>
</div>

How to make an element appear on right or left depending of the position of the element clicked?

I’m working on a project where i have a mosaic of images (4 images per row) and when user mouses over an image, it makes appear a sidebar with some content inside.
The thing is if the user hovers image 1 or 2, the side bar is on right, if he hovers image 3 or 4 the side bar is on left.
I’m trying with a click for now as i find it easiest to do.
But at a certain point, a bug appears and the side bar is not on right side.
Here is my code :
The html in the snippet is a copy of the source code but i use php and a foreach loop to build the sidebar and the mosaic of images.
Try the snippet below.
HTML & PHP
<!-- Side bar -->
<div id="sidebar_content">
<div class="sidebar_content_wrapper">
<img id="bt_close_sidebar_content" class="bt_close pull-right pointer" src="img/site/bt-close.png" />
<?php
$i = 1;
foreach ($allDatasEquipe AS $equipe):
?>
<div id="membre_<?php echo $equipe['alias']; ?>" class="contenu_sidebar">
<h2><?php echo nl2br(htmlspecialchars($equipe['nom'], ENT_QUOTES, 'UTF-8')) ?></h2>
<h3><?php echo nl2br(htmlspecialchars($equipe['fonction'], ENT_QUOTES, 'UTF-8')) ?></h3>
<p><?php echo $equipe['texte']; ?></p>
</div>
<?php
$i ++;
endforeach;
reset($allDatasEquipe);
?>
</div>
</div><!-- fin sidebar_content_right -->
<!-- Images -->
<div class="container container_agence">
<div class="row mosaique_equipe">
<?php
$i = 1;
foreach ($allDatasEquipe AS $equipe):
if ($i == 1 || $i == 2) {
$class = 'sidebar_left';
} else {
$class = 'sidebar_right';
}
?>
<div class="col-md-3 col-lg-3">
<div id="<?php echo $equipe['alias']; ?>" class="img_mosaique_equipe toggle-sidebar pointer <?php echo $class; ?>">
<img src="img/equipe/<?php echo nl2br(htmlspecialchars($equipe['image'], ENT_QUOTES, 'UTF-8')) ?>" alt="<?php echo nl2br(htmlspecialchars($equipe['nom'], ENT_QUOTES, 'UTF-8')) ?>"/>
</div>
</div>
<?php
$i ++;
if ($i > 4) {
$i = 1;
}
endforeach;
reset($allDatasEquipe);
?>
</div>
</div>
JS / jQuery
$sidebar_content = $('#sidebar_content');
$('.images').click(function() {
var id = $(this).attr('id');
console.log('id : ' + id);
var position_sidebar = $('.contenu_sidebar').hasClass('sidebar_left');
if ($sidebar_content.hasClass('visible')) {
if ($(this).hasClass('sidebar_left')) {
$('#sidebar_content').css({
"text-align": "left",
"right": "0"
});
$sidebar_content.animate({
"right": "-1000px"
}, "slow").removeClass('visible');
console.log('sidebar_left closed');
position_sidebar_content = 'right';
} else if ($(this).hasClass('sidebar_right')) {
$('#sidebar_content').css({
"text-align": "right",
"right": "0"
});
$('#sidebar_content').css({
"left": "0"
});
$sidebar_content.animate({
"left": "-1000px"
}, "slow").removeClass('visible');
position_sidebar_content = 'left';
console.log('sidebar_right closed');
}
} else {
if ($(this).hasClass('sidebar_left')) {
$('#sidebar_content').css({
"right": "-1000px"
});
position_sidebar_content = 'right';
$sidebar_content.animate({
"right": "0px"
}, "slow").addClass('visible');
console.log('sidebar_left open');
} else if ($(this).hasClass('sidebar_right')) {
$('#sidebar_content').css({
"left": "-1000px"
});
position_sidebar_content = 'left';
$sidebar_content.animate({
"left": "0px"
}, "slow").addClass('visible');
console.log('sidebar_right open');
}
}
});
/* side bar content */
#sidebar_content {
width: 50%;
position: fixed;
border-right: 1px solid #4c565c;
/* right: -50%;*/
right: -1000px;
top: 0;
height: 100%;
overflow: auto;
background: black;
z-index: 1000;
background-color: #999;
text-align: left;
}
.contenu_sidebar {
display: none;
}
.sidebar_content_wrapper {
position: relative;
height: 100%;
overflow: auto;
padding: 115px 50px 50px 50px;
}
.images {
width: 30px;
height: 30px;
background-color: red;
margin-bottom: 5px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-sm-3 col-md-3 col-lg-3">
<div id="1" class="images sidebar_left"></div>
</div>
<div class="col-sm-3 col-md-3 col-lg-3">
<div id="2" class="images sidebar_left"></div>
</div>
<div class="col-sm-3 col-md-3 col-lg-3">
<div id="3" class="images sidebar_right"></div>
</div>
<div class="col-sm-3 col-md-3 col-lg-3">
<div id="4" class="images sidebar_right"></div>
</div>
<div class="col-sm-3 col-md-3 col-lg-3">
<div id="5" class="images sidebar_left"></div>
</div>
<div class="col-sm-3 col-md-3 col-lg-3">
<div id="6" class="images sidebar_left"></div>
</div>
<div class="col-sm-3 col-md-3 col-lg-3">
<div id="7" class="images sidebar_right"></div>
</div>
<div class="col-sm-3 col-md-3 col-lg-3">
<div id="8" class="images sidebar_right"></div>
</div>
</div>
<div id="sidebar_content">
<div class="sidebar_content_wrapper">
<p id="bt_close_sidebar_content" class="bt_close pull-right pointer">bt close </p>
<div id="membre_1" class="contenu_sidebar">
<p>text</p>
</div>
<div id="membre_2" class="contenu_sidebar">
<p>text</p>
</div>
<div id="membre_3" class="contenu_sidebar">
<p>text</p>
</div>
<div id="membre_4" class="contenu_sidebar">
<p>text</p>
</div>
<div id="membre_5" class="contenu_sidebar">
<p>text</p>
</div>
<div id="membre_6" class="contenu_sidebar">
<p>text</p>
</div>
<div id="membre_7" class="contenu_sidebar">
<p>text</p>
</div>
<div id="membre_8" class="contenu_sidebar">
<p>text</p>
</div>
</div>
</div>
I didn't try your code but I think the example below shows a way of doing what you need.
<html>
<head>
<style>
.my-image {
display: inline-block;
background-color: #0f0;
with: 96px;
height: 72px;
margin: 1px;
}
.my-popup {
position: absolute; display: inline-block; z-index: 1000; background-color: red; with: 48px; height: 48px;
}
</style>
</head>
<body>
<div class="my-image">Lorem ipsum ad his scripta blandit partiendo</div>
<div class="my-image">Lorem ipsum ad his scripta blandit partiendo</div>
<div class="my-image">Lorem ipsum ad his scripta blandit partiendo</div>
<div class="my-image">Lorem ipsum ad his scripta blandit partiendo</div>
<script src="jquery.js"></script>
<script>
(function ($) {
var toDisplay = $('<div class="my-popup">Hey whats up</div>')
.appendTo($('body'))
.hide(0);
var images = $('.my-image');
$.each(images, function (index, el) {
var displayPos = calculatePosition(el, index >= images.length / 2);
var $el = $(el);
$el.on('mouseover', function () {
toDisplay.show(0).offset(displayPos);
});
$el.on('mouseout', function () {
toDisplay.hide(0);
});
});
function calculatePosition (image, right) {
var $image = $(image);
var pos = $image.offset(); // image position relative to document
if (right) {
pos.left -= toDisplay.width();
} else {
pos.left += $image.width();
}
return pos;
}
})(window.jQuery);
</script>
</body>
</html>
The idea is to set the displaying element position to absolute and calculate the new coordinates on each hover event and set them using jquery.

Categories

Resources