Calculate element padding dynamically using JavaScript - javascript

I'm trying to calculate the padding-bottom property for multiple elements in an image gallery. Check out the following code for one element:
<div class="item-container fashion">
<a href="images/fashion/11-large.jpg"
data-size="600x900"
class="item"
style="padding-bottom: 150%">
<img class="lazyload"
alt="Description"
src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
data-sizes="auto"
data-src="images/fashion/11-small.jpg"/>
</a>
</div>
As you can see I define the size of the image in "data-size" attribute (600x900). In order to get the padding-bottom value which I need to prevent reflow, I simply divide calculate (height/width) x 100, which in this case yields 150 - my padding-bottom value.
Now I can easily calculate this manually and input it as I'm doing above and it works just fine. But since my gallery will contain hundreds of images all with different ratios, I'm gonna need a more automated way of calculating the padding value.
Is there anyway to achieve this by doing the calculation in JavaScript and then apply it to the respective element? If I were to include the dimensions in the filename for example and parse it maybe I could even avoid manually inputting the data-size value too...?
I would really like to avoid having to manually do hundreds of calculations, plus It'll be great to learn a new trick for the future. Thanks!
UPDATE
here's what I got so far, as you can see image1 and image2 have different dimensions and ratio. As you can see i'm doing something wrong the padding isn't working out just right. I'm setting "item" height to 0 because padding-bottom will end up taking care of the height. thoughts?
var tags = document.getElementsByClassName('item');
for (var i = 0; i < tags.length; ++i) {
/* This is the part I mentioned about, you may want to use one of the methods above depending on how your css and the rest of your code looks like*/
tags[i].style.paddingBottom = (100 * (tags[i].offsetHeight / tags[i].offsetWidth)) + 'px';
}
.item {
position: relative;
height: 0;
display: inline-block;
border: 1px solid red;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item-box fashion">
<a href="http://lorempixel.com/output/city-h-c-600-900-7.jpg" data-size="600x900" class="item">
<img width="300" height="450" class="lazyload" alt="Image description" src="http://lorempixel.com/output/city-h-c-600-900-7.jpg" data-sizes="auto" />
</a>
</div>
<div class="item-box fashion">
<a href="http://lorempixel.com/output/fashion-q-c-600-400-5.jpg" data-size="600x900" class="item">
<img width="300" height="200" class="lazyload" alt="Image description" src="http://lorempixel.com/output/fashion-q-c-600-400-5.jpg" data-sizes="auto" />
</a>
</div>

First of all why don't you have to define the dimension of the picture. You can use element.offsetWidth element.offsetHeight OR element.style.width, element.style.height (these two would have to be parsed because they return a string for instance 5px) OR element.getBoundingClientRect() (the lattest is an object containing top, left, right, bottom etc.)
Now, that being said using java you can do the following ...
var tags = document.getElementsByClassName('item');
for(var i = 0; i < tags.length; ++i){
/* This is the part I mentioned about, you may want to use one of the methods above depending on how your css and the rest of your code looks like*/
tags[i].style.paddingBottom = (100 * (tags[i].offsetHeight / tags[i].offsetWidth)) + 'px';
}
.item{
width: auto;
height: auto;
display: inline-block;
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="item-box fashion">
<a href="http://lorempixel.com/output/city-h-c-600-900-7.jpg" data-size="600x900" class="item">
<img width="300" height="450" class="lazyload" alt="Image description" src="http://lorempixel.com/output/city-h-c-600-900-7.jpg" data-sizes="auto" />
</a>
</div>
<div class="item-box fashion">
<a href="http://lorempixel.com/output/fashion-q-c-600-400-5.jpg" data-size="600x900" class="item">
<img width="300" height="200" class="lazyload" alt="Image description" src="http://lorempixel.com/output/fashion-q-c-600-400-5.jpg" data-sizes="auto" />
</a>
</div>

Related

Single Image stop in multiple images marquee

I am trying to create a photo gallery. It will contain a bunch of images moving across the screen with a marquee, and when I click on any image, it will enlarge on the above div.
What new I am trying to achieve is that, the selected image for highlighted and should stop moving, while all other images in a marquee tag will continue moving.
I am not able to achieve to task described in bold text. Please help me with that.
here's my code
function func(val) {
var current_image = document.getElementById(val);
var source = document.getElementById(val).src;
document.getElementById("img1").src = source;
current_image.style.border = "2px solid black";
}
img {
height: 200px;
width: 200px;
}
#img1 {
height: 440px;
width: 100%;
}
<img src="https://images.unsplash.com/photo-1486570318579-054c95b01160?ixlib=rb-0.3.5&s=8cb4fb1b4ac3ab4e5335a6f5961d5d86&auto=format&fit=crop&w=890&q=80" id="img1">
<div class="marqueeImage">
<marquee onmouseover="stop()" onmouseout="start()">
<img src="https://images.unsplash.com/photo-1472152083436-a6eede6efad9?ixlib=rb-0.3.5&s=93a9b1fd63f0d00e2edac3cea5650819&auto=format&fit=crop&w=749&q=80" onclick=func(1) id="1">
<img src="https://images.unsplash.com/photo-1474436799594-1974f1add7ad?ixlib=rb-0.3.5&s=f5fc0f9a97ed3dc7d8f069470b51a864&auto=format&fit=crop&w=724&q=80" onclick=func(2) id="2">
<img src="https://images.unsplash.com/photo-1475687111391-295db56c4d68?ixlib=rb-0.3.5&s=31e11f83c2196cf8c3df3afcbea3974f&auto=format&fit=crop&w=837&q=80" onclick=func(3) id="3">
<img src="https://images.unsplash.com/photo-1490237014491-822aee911b99?ixlib=rb-0.3.5&s=3b012e88f4bd20f38706d25928b51fe6&auto=format&fit=crop&w=750&q=80" onclick=func(4) id="4">
<img src="https://images.unsplash.com/photo-1482920387559-08269818bcfc?ixlib=rb-0.3.5&s=7d4daea39d40f2f10c879b75f5b7fddd&auto=format&fit=crop&w=750&q=80" onclick=func(5) id="5">
<img src="https://images.unsplash.com/photo-1486570318579-054c95b01160?ixlib=rb-0.3.5&s=8cb4fb1b4ac3ab4e5335a6f5961d5d86&auto=format&fit=crop&w=890&q=80" onclick=func(6) id="6">
</marquee>
</div>

How to pan/zoom an image and an overlay simultaneously?

I'm using jquery.panzoom to pan and zoom an image in response to mouse or touch events. This works fine, but now I'd like to zoom the image together with an overlay (either a SVG file or another image). The overlay and the image are exactly the same size, I just want them to behave as a single image with respect to pan and zoom.
I tried putting them both in a div, like this:
<div id="mydiv">
<img src="image.jpg" style="position: fixed; top: 0; left: 0; width: 500; height: 500;">
<img src="overlay.svg" style="position: fixed; top: 0; left: 0; width: 500; height: 500;">
</div>
<script>
$("#mydiv").panzoom();
</script>
The layout gets messed up when I do that.
How can I pan/zoom an image and overlay (or several images) simultaneously?
(I'd like to keep using jquery.panzoom since that seems to work very well on my target platforms, but if there is another library that does the same that could also work)
According to their documentation, this should work:
(function() {
var $section = $('#collectionId');
$section.find('.panzoom').panzoom({
$set: $section.find('.parent > div')
});
})();
<section id="collectionId">
<div class="parent">
<div class="panzoom">
<img src="image.jpg">
</div>
<div>
<img src="overlay.svg">
</div>
<div>
<img src="anotherOverlay.svg">
</div>
</div>
</section>

Mark last visible child in overflown div using CSS or JS

I have a bar with inline-block divs. Some of them are out of viewport because I set: white-space:nowrap; overflow: hidden; for the container. I'm looking for ways to select last visible child. By visible I mean that the div is placed (preferably fully) in area of it's container.
As far as I know there is selector like that neither in CSS nor in jQuery. The closest one is jQuery's :visible but it says that all the divs are visible because they consume space in the page layout.
The only way out I see is to enumerate divs on load and every resize in order to calculate if the div is still in the container by summing it's width, padding and margins.
Do you have any better ideas?
#container {
white-space:nowrap;
overflow: hidden;
}
.element {
display: inline-block;
vertical-align:top;
}
<div id="container">
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
</div>
In current, non responsive version of stack overflow on the snippet we can see 4 full divs and small part of 5th. I'd like to select 5th one (or preferably 4th div because the next one isn't fully visible).
You could use media queries. Of course, this could become very cumbersome, depending on the number of child elements you have, but it does save the overhead of using an onresize event listener.
For the below Snippet, I've assumed that the parent element is running the full width of the screen.
*{box-sizing:border-box;margin:0;padding:0;}
#container{
font-size:0;
overflow:hidden;
white-space:nowrap;
}
.element{
display:inline-block;
opacity:.5;
padding:5px;
vertical-align:top;
width:150px;
}
img{
width:100%;
}
#media (max-width:299px){
.element:first-child{opacity:1;}
}
#media (min-width:300px) and (max-width:449px){
.element:nth-child(2){opacity:1;}
}
#media (min-width:450px) and (max-width:599px){
.element:nth-child(3){opacity:1;}
}
#media (min-width:600px) and (max-width:749px){
.element:nth-child(4){opacity:1;}
}
#media (min-width:750px) and (max-width:899px){
.element:nth-child(5){opacity:1;}
}
#media (min-width:900px) and (max-width:1049px){
.element:nth-child(6){opacity:1;}
}
#media (min-width:1050px) and (max-width:1199px){
.element:nth-child(7){opacity:1;}
}
#media (min-width:1200px){
.element:nth-child(8){opacity:1;}
}
<div id="container">
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
<div class="element">
<img src="http://placehold.it/150x150" alt=""/>
</div>
</div>
i've done some JQ code, hope it helps
this works if all elements have the same width. if they have different widths the code would need some small changes
see here > JSFIDDLE
JQ CODE :
var vwidth = $(window).width() // get window width
var ewidth = $(".element").width() // get element width
var total = vwidth / ewidth // calculate how many elements fit inside the window width
var integer = parseInt(total)// get the integer from the result above
$(".element").eq( integer - 1 ).addClass("lastvisible")// -1 because eq starts from 0
solution for elements with different widths :
JQ :
var vwidth = $(window).width(); // get screen width
$(".element").each(function(){
var eleft = $(this).offset().left // each element's distance from left of the screen
var ewidth = $(this).width()// each element's width
var total = eleft + ewidth
if (total < vwidth) { // if sum between distance from left of screen + element width is smaller than the window screen
that = $(this); // all elements that are visible inside the screen
}
});
that.addClass("lastvisible") //only the last element visible inside the screen
see fiddle here > JsFiddle
This is my way to make it work but I'll welcome any better way.
Everything is being calculated by jQuery:
var cwidth = parseInt($('#container').width()); // get container width
var lastElement = $('#container .element:first'); // assume that first element is visible
$("#container .element:not(:first)").each(function(){
//get right offset for every div
var rightOffset = $(this).offset().left
+ parseInt($(this).width())
+ parseInt($(this).css('padding-left'))
+ parseInt($(this).css('margin-left'));
//if the right offset is bigger than container width then stop enumerating - previous one was the last fully visible
if (rightOffset > cwidth){
return false;
}
//offset was lower than container with so this is our new fully visible element
lastElement = $(this);
});
lastElement.addClass("lastvisible")
advantages:
Working for different element sizes
Add same recalculating on window resize and you've got a working responsive way
drawbacks:
multiple jQuery recalculations that are quite havy for the browser
in my opinion ugly code
https://jsfiddle.net/6k5xujtc/1/

Remove border from alt text if image url is not valid

Today is friday and this is a fun question (and a real problem). I am using border around the image but if the image url is not valid, the border appears around the alt text and looks kind of ugly. How to remove it using CSS?
<a href="#">
<img src="http://badsrc.com/blah" style="border:1px solid black" alt="Remove border from this alt text" />
</a>
I don't want to overkill it with server side script or jQuery. Interested in CSS. If no CSS solution is available then other solutions are welcome.
My actual server side script looks like this
If Not String.IsNullOrEmpty(photoURL) Then
photoUrl2="<img src="..." style="border:1px solid #000" alt="BMW for sale">"
end if
jsfiddle
You can use onerror and set the border
<a href="#">
<img src="http://badsrc.com/blah" onerror="this.style.borderWidth=0" style="border:1px solid black" alt="Remove border from this alt text" />
</a>
It would be better to not use inline styles and use classes
jsfiddle
Use .error(), it binds an event handler to the "error" JavaScript event.
$("img").error(function () {
$(this).css('border', 'none');
})
DEMO
<a href="#">
<img id="myImage" src="http://badsrc.com/blah" style="border:1px solid black" alt="Remove border from this alt text" />
</a>
<script>
var image = document.getElementById('myImage'); // or select based on classes
image.onerror = function(){
// image not found or change src like this as default image:
image.style.border = "none";
};
</script>
here is your solution with javascript.
Since you are setting it via server side, the correct thing to fix this on the server side, not in CSS or JavaScript. All you have to do is change your code to this:
photoUrl2 = String.Format("<img src='...' style='border:{0}' alt='BMW for sale' />",
If(String.IsNullOrEmpty(photoURL),
"none",
"1px solid #000"))
I know it's an old question but here is CSS only solution using pseudo elements
img:after {
content: attr(alt);
position: absolute;
z-index: 2;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #fff;
}
<img src="//placehold.foo/200x200" alt="Remove border from this alt text" />

How do you make a filter for images that have tags?

I have products in a grid using the code below. I wonder how to make a filter so that when the user clicks a box that says for example "green", the site only shows the images that have a green tag.
How do you make such a filter and how to do apply tags?
ps. I dont mean <div> kind of tags, i mean "Oh that jersey is a: "Hoodie" "Green" "Zipper", ect. Just thought i'd clarify that."
thanks in advance :)
HTML:
<div id="Backgrounds">
<img id="Hajar" src="Backgrunder/Hajar.jpg">
<img id="Labyrint" src="Backgrunder/Labyrint.jpg">
<img id="Martini" src="Backgrunder/Martini.jpg">
<img id="FärgadePapper" src="Backgrunder/FärgadePapper.jpg">
<img id="Hajar" src="Backgrunder/Hajar.jpg">
<img id="Labyrint" src="Backgrunder/Labyrint.jpg">
<img id="Martini" src="Backgrunder/Martini.jpg">
<img id="FärgadePapper" src="Backgrunder/FärgadePapper.jpg">
<img id="Hajar" src="Backgrunder/Hajar.jpg">
<img id="Labyrint" src="Backgrunder/Labyrint.jpg">
<img id="Martini" src="Backgrunder/Martini.jpg">
<img id="FärgadePapper" src="Backgrunder/FärgadePapper.jpg">
<img id="Hajar" src="Backgrunder/Hajar.jpg">
<img id="Labyrint" src="Backgrunder/Labyrint.jpg">
<img id="Martini" src="Backgrunder/Martini.jpg">
</div>
CSS:
#Backgrounds img{
width: 97px;
display: inline-block;
vertical-align: top;
padding: 4px;
cursor: pointer;
}
I suggest storing a comma delimited list of strings in a data attribute, then iterating through the images and filtering that way. For example:
HTML
<div id="backgrounds">
<img id="Hajar" data-tags="hoodie,zipper,green" src="Backgrunder/Hajar.jpg">
<img id="Labyrint" data-tags="these,are,tags" src="Backgrunder/Labyrint.jpg">
</div>
JavaScript
function filterImages(tag) {
// select all the images
var query = document.querySelectorAll('#Backgrounds img');
for (var i = 0; i < query.length; i++) {
var image = query[i];
// hide the image if it doesn't contain the tag we're looking for
if (image.getAttribute('data-tags').split(',').indexOf(tag) === -1)
hideImage(image);
}
}
function hideImage(image) {
// do whatever you need to "filter" out the image
image.style.display = 'none';
}
There's a lot of ways to do this. You just have to find a way that's right for you.
I'm not sure on all of your requirements but Isotope has filtering that is pretty easy to use. Here's a demo.
If you need a little more control you can look into TaffyDB and generated the HTML based on the results of a query.

Categories