Differentiate between vertical and horizontal image format jQuery - javascript

I want to differentiate if an image is vertical or horizontal format and add a special class. I'm use this to fill my div fully with my image.
My HTML:
<a href="images/gallerie/image-1.jpg" data-lightbox="image-1" class="impression">
<img src="images/gallerie/image-1.jpg">
</a>
My CSS:
.wide {
height: 100%;
width: auto;
}
.tall {
height: auto;
width: 100%;
}
My JS (jQuery):
$('.impression').find('img').each(function() {
if($(this).width() / $(this).height() > 1) {
$(this).addClass('wide');
}
else {
$(this).addClass('tall');
}
});
It works only sometimes, and I don't know why.
On my iPhone it works never (Chrome).
Has anybody an other solution or maybe the reason why it works sometimes?
Thanks!

You need to use a load event handler so image is loaded before you can check dimensions
$('.impression').find('img').on('load',(function() {
// image is loaded now
if($(this).width() / $(this).height() > 1) {
$(this).addClass('wide');
}
else {
$(this).addClass('tall');
}
});
The each is not needed as jQuery will use each internally and this will be image instance

Most probably, you are running the function too soon and your images have not been loaded yet. In order to make sure, you can always console.log() the values of .width() and .height().
The best way to make sure the image has loaded when you check its dimensions is to use the load event.
$('img').on('load', function(){
// do your thing...
})
The rest is wrong, as pointed out by #charlietfl. The load event for img's does not propagate.
Better yet, instead of binding a listener to each img, just bind one on body for all your images, including the ones you will load later on, using some fancy async method:
$('body').on('load', 'img', function(){
// do your thing...
})
This second version will run every time an <img> will load in your DOM, not only when you run the script.

Related

Standardize image into div

I'm working with Bootstrap and I want to put some photos into my div and I want them to be all at the same size ("standardize").
If they're too big (and they will always be) I want to resize them to fit in my div and crop them if necessary.
For the moment her is what I do :
I've tried to change the style of the image in jQuery in a function:
• If the height is bigger than the width, I switch the style to max-width:100% and height auto.
• Inversement if the width is bigger than the height.
But I'm still new to jQuery and I am probably doing something wrong; can someone light my lantern please?
Here is my jQuery
$(document).ready(function(){
photoResize();
$(window).resize(function(){
photoResize();
});
});
function photoResize(){
image_w = $('img').width();
image_h = $('img').height();
if(image_h > image_w)
{
$('img').css("max-width","100%");
$('img').height("auto");
}
else if(image_w > image_h)
{
$('img').css("max-height","100%");
$('img').width("auto");
}
}
And here is a Fiddle for a better view : https://jsfiddle.net/Baldrani/DTcHh/9801/
Simplicity
I do this quite often in the CMS we use at work for galleries etc. The method I use involves a jQuery library called imgLiquid.js.
This will turn an inline image into a background image on the parent div. It's good because you can achieve your desired effect. It will crop the image (as it technically becomes a background image) and will apply background-size: cover; and background-position: center center; as inline styles.
You can find the plugin here
To initialize the plugin you just need:
$(".myele").imgLiquid();
Overheads
The plugin is very small (roughly around 5.106 KB) so you don't need to worry about adding weight to the page. It really it the most simple method I've come across (bar using thumbnails generated from the sever-side - see note at the bottom).
Cue CSS
I've tested this thoroughly and found it gives excellent results. You may then ask... what happens to my parent divs (as technically the plugin hides the img element - which therefore means the parent element doesn't know what height to make itself).
An easy method to make things work responsively, or not:
.myelement:before{
content: "";
padding-top: 50%;
display: block;
}
This CSS will give your heights back to the wrapping element. So if you wanted certain proportions you could use this math:
h / w * 100 = your percentage for the padding-top.
Working Example
Small note
Technically if I had the control I'd advise just using thumbnails.. I assume you're using some sort of system that could technically just render cut down versions of the images? The reason I use this method — and suggested it — is that I don't have control over the CMS and I'm assuming you just want to manage the code that's being produced as it's not stated.
if you want to make your images the same size then you dont need any javascript or calculations, why not just set it in css?
.someUniqueContainer img{
width:300px;
height:300px; // or what ever height you want
}
I'm guessing that in reality you actually want to crop all your images to a set width/height. if that's the case you'll need a serverside script for that.
where are the images coming from? it would be easyer to just edit them. if they are coming from a user then you would resize/crop on the server on file upload
There were several mistakes in your code.
Please look at this jsfiddle, please see https://jsfiddle.net/DTcHh/9796/
$(document).ready(function () {
photoResize();
$(window).resize(function () {
photoResize();
});
});
function photoResize() {
image_w = $('img').width();
image_h = $('img').height();
if (image_h > image_w) {
$('img').css("max-width", "100%");
$('img').height("auto");
} else if (image_w > image_h) {
$('img').css("max-height", "100%");
$('img').width("auto");
}
}
sth like this?, although this is pure css, not jquery included, might not be suit in your case..
body {
margin-top:20px
}
.col-xs-3 {
margin: 5px 0;
width: 500px;
height:120px
}
.col-xs-3 > div {
width: 100%;
height: 120px;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
JsFiddle

JS launches before CSS

This is currently happening in chrome, in firefox I haven't had this issue (yet).
Here is a VERY simplified version of my problem.
HTML:
<div class="thumbnail">
Click me!
</div>
CSS:
div {
width: 200px;
height: 300px;
background-color: purple;
}
a {
position: absolute;
}
#media (max-width: 991px) {
div {
height: 200px;
}
}
Javascript:
$(document).ready(function () {
var $parent = $('#clickMe').parent();
function resize() {
$('#clickMe').offset({
top: $parent.offset().top + $parent.height()-$('#clickMe').height()
});
}
$(window).on('resize', resize);
resize();
});
The problem:
So what does this give when I resize (without dragging)? Well javascript launches first and sets the position of the <a></a> , then CSS applies the height change if we are < 992 px.
Logically the button is now visually at the outside of the div and not on the border like I had originally defined it to be.
Temporary solution proposed in this post.
jQuery - how to wait for the 'end' of 'resize' event and only then perform an action?
var doit;
$(window).on('resize', function(){ clearTimeout(doit); doit = setTimeout(resize, 500); });
Temporary solution is not what I'm looking for:
However, in my situation I don't really need to only call 'resize' when the resizing event is actually done. I just want my javascript to run after the css is finished loading/ or finished with it's changes. And it just feels super slow using that function to 'randomely' run the JS when the css might be finished.
The question:
Is there a solution to this? Anyone know of a technique in js to wait till css is completely done applying the modifications during a resize?
Additional Information:
Testing this in jsfiddle will most likely not give you the same outcome as I. My css file has many lines, and I'am using Twitter Bootstrap. These two take up a lot of ressources, slowing down the css application (I think, tell me if I'm wrong).
Miljan Puzović - proposed a solution by loading css files via js, and then apply js changes when the js event on css ends.
I think that these simple three steps will achieve the intended behavior (please read it carefully: I also suggest to read more about the mentioned attributes to deeply understand how it works):
Responsive and fluid layout issues should always be primarily (if not scrictly) resolved with CSS.
So, remove all of your JavaScript code.
You have positioned the inner a#clickMe element absolutely.
This means that it will be positioned within its closest relatively positioned element. By the style provided, it will be positioned within the body element, since there is no position: relative; in any other element (the default position value is static). By the script provided, it seems that it should be positioned within its direct parent container. To do so, add position: relative; to the div.thumbnail element.
By the script you provided, it seems that you need to place the a#clickMe at the bottom of div.thumbnail.
Now that we are sure that the styles added to a#clickMe is relative to div.thumbnail, just add bottom: 0px; to the a#clickMe element and it will be positioned accordingly, independently of the height that its parent has. Note that this will automatically rearrange when the window is resized (with no script needed).
The final code will be like this (see fiddle here):
JS:
/* No script needed. */
CSS:
div {
width: 200px;
height: 300px;
background-color: purple;
position: relative; //added
}
a {
position: absolute;
bottom: 0px; //added
}
#media (max-width: 991px) {
div {
height: 200px;
}
}
If you still insist on media query change detection, see these links:
http://css-tricks.com/media-query-change-detection-in-javascript-through-css-animations/
http://css-tricks.com/enquire-js-media-query-callbacks-in-javascript/
http://tylergaw.com/articles/reacting-to-media-queries-in-javascript
http://davidwalsh.name/device-state-detection-css-media-queries-javascript
Twitter Bootstrap - how to detect when media queries starts
Bootstrap: Responsitive design - execute JS when window is resized from 980px to 979px
I like your temporary solution (I did that for a similar problem before, I don't think half a second is too long for a user to wait but perhaps it is for your needs...).
Here's an alternative that you most likely have thought of but I don't see it mentioned so here it is. Why not do it all through javascript and remove your #media (max-width.... from your css?
function resize() {
var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
if(width<992){
$("div").each(function(e,obj){$(obj).height(200);});
}
$('#clickMe').offset({
top: $parent.offset().top + $parent.height()-$('#clickMe').height()
});
}
In the html page, put the link to css file in head section; next, put the link to js file just before the /body tag and see what happens. In this way css will load always before js.
Hope this help you.
Did you try to bind the resize handler not to the window but to the object you want to listen to the resize ?
Instead of
$(window).on('resize', resize);
You can try
$("#clickMe").on('resize', resize);
Or maybe
$("#clickMe").parent().on('resize', resize);
var didResize = false;
$(window).resize(function() {
didResize = true;
});
setInterval(function() {
if (didResize) {
didResize = false;
console.log('resize');
}
}, 250);
I agree with falsarella on that you should try to use only CSS to do what you are trying to do.
Anyway, if you want to do something with JS after the CSS is applied, I think you can use requestAnimationFrame, but I couldn't test it myself because I wasn't able to reproduce the behavior you explain.
From the MDN doc:
The window.requestAnimationFrame() method tells the browser that you
wish to perform an animation and requests that the browser call a
specified function to update an animation before the next repaint. The
method takes as an argument a callback to be invoked before the
repaint.
I would try something like this:
var $parent = $('#clickMe').parent();
function resize(){
$('#clickMe').offset({
top: $parent.offset().top + $parent.height()-$('#clickMe').height()
});
}
window.onresize = function(e){
window.requestAnimationFrame(resize);
}
window.requestAnimationFrame(resize);
Anyone know of a technique to wait till css is completely done loading?
what about $(window).load(function() { /* ... */ } ?
(it executes the function only when the page is fully loaded, so after css loaded)

Full Screen Background Image(s) + Rotating Images?

I know how to implement Full-Screen / Expandable background images; I typically use a jQuery method. EG: http://tinyurl.com/9yl4rbw
BUT! I'm trying to make it so the background image is different each time the page is visited. Not a slide show; but like the old javascript (EG: http://www.computerhope.com/j18.htm)
How could I combine the two; jQuery expandable background and on-page-refresh-new image javascript?
Anyone came across a quality plugin for this effect?
*Edit___*
I use the jQuery method as within the reference URL above; essentially below:
<!--Expandable BG code IE 7 +-->
<style>
#bg { position: fixed; top: 0; left: 0; }
.bgwidth { width: 100%; }
.bgheight { height: 100%; }
#page-wrap { position: relative; width: 950px; margin-left: auto; margin-right: auto;; }
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(function() {
var theWindow = $(window),
$bg = $("#bg"),
aspectRatio = $bg.width() / $bg.height();
function resizeBg() {
if ( (theWindow.width() / theWindow.height()) < aspectRatio ) {
$bg
.removeClass()
.addClass('bgheight');
} else {
$bg
.removeClass()
.addClass('bgwidth');
}
}
theWindow.resize(function() {
resizeBg();
}).trigger("resize");
});
</script>
<!--Expandable BG code IE 7 +-->
<!--Full BG Call-->
<img src="Sandwichfullbg.jpg" id="bg" >
<div id="page-wrap">
<!--End Full BG Call-->
I'd like to discover a simple solution to having the background change on new page visit or page refresh; ideally holding around 30 images. EG: Refresh page > New rad Image; Refresh page > New rad Image; (x 30)
Add this code at the top of you JS. It will set the src property of the image to a random value from Sandwichfullbg0.jpg to Sandwichfullbg29.jpg (so 30 different images in total)
$('#bg').attr('src', 'Sandwichfullbg' + Math.floor(Math.random() * 30) + '.jpg');
Why not just use the new background-size:cover, for the background, and then use jQuery to randomly change this background image as per the normal method?
I've created a jsfiddle for you, basically doing everything you need. (Keep clicking Run in jsfiddle and you'll see the background-image cycle randomly).
Be aware, background-size:cover, mainly works with newer bowers, but by using Modernizr this can be overcome.
Install Modernizr by linking it in your header
<script src="http://www.modernizr.com/downloads/modernizr-latest.js"></script>
And in your HTML tag,
<html class="no-js">
Edit: As per the comments, I've made another way that has more browser support:
jsfiddle
This time I've just made it randomly apply a class, of which this class has vendor-prefixs and fixes for ie-7/ie-8 and all the rest really. It won't look perfect in IE8, but images will fully stretch to fit the height/width of the body.
Take a look at this. View the source and check it out. I use an image with a low z-index because it makes resizing easier. Also, I would optimize your background image so its not so big. It's almost a MB and it takes way too long to load. Your version doesn't resize well when the aspect ratio isn't widescreen.

Execute Fade-In as Page initially loads?

I am working on some jQuery code to apply page transitions. What i want the jQuery code to do is basically apply a fade in effect of the page as follows:
$("body").css("display", "none");
$("body")().fadeIn(400);
Once the page loads the page reloads and then does the instructed fade in effect, but what I want to happen is a fade in effect for the whole webpage right from the start and tried:
$(document).load(function() {
However, this does not work. I also tried this code to no avail:
$("body").load().css("display", "none");
$("body").load().fadeIn(400);
Are there any visible error in my code blocks that can be rectified to apply the desired behavior or can the community please direct me to a guide that demonstrates the correct implementation of what I am aiming to do?
You could place this in a .css file -
body { display:none; }
Or even place it inline like so -
<body style="display:none;" >
And then in a $(document).ready() callback fade it in using this -
$(document).ready(function(){
$("body").fadeIn(400);
});
The browser will render the HTML according to your css file first. So when the browser comes to render the <body> tag, it'll see a css rule saying that its display property must be set to none. Only after all the HMTL is loaded and jQuery is ready ($(document).ready()) then you can call your fadeIn();
You could use CSS to set the whole page to invisible or hidden:
body {
display: none;
}
Or:
body {
visibility: hidden;
}
You can set this as inline CSS inside the <head>. Then inside jQuery you can make it fade in once loaded.
// $("body")().fadeIn(400); // this is incorrect, try with:
$('body').fadeIn(400);
That means:
$("body").css("display", "none");
$(window).load(function(){ // use "window"
$('body').fadeIn(400);
});
Or you may try to set display:none; directly from your CSS (depends on your needs)
body{
display:none;
}
You should use the load on window and not on DOM.
Try :
$(window).load(function(){
$("body").css("display", "none");
$("body").fadeIn(400);
})
And for further explination try Here

How to silently hide "Image not found" icon when src source image is not found

Do you know how to hide the classic “Image not found” icon from a rendered HTML page when an image file is not found?
Any working method using JavaScript/jQuery/CSS?
<img onerror='this.style.display = "none"'>
You can use the onerror event in JavaScript to act when an image fails to load:
var img = document.getElementById("myImg");
img.onerror = function () {
this.style.display = "none";
}
In jQuery (since you asked):
$("#myImg").error(function () {
$(this).hide();
});
Or for all images:
$("img").error(function () {
$(this).hide();
// or $(this).css({visibility:"hidden"});
});
You should use visibility: hidden instead of .hide() if hiding the images might change the layout. Many sites on the web use a default "no image" image instead, pointing the src attribute to that image when the specified image location is unavailable.
I've slightly modified the solution suggested by Gary Willoughby, because it briefly shows the broken image icon. My solution:
<img src="..." style="display: none" onload="this.style.display=''">
In my solution image is hidden initially and is shown only when it is successfully loaded. It has a disadvantage: users will not see halfloaded images. And if user has disabled JS then they will never see any images
To hide every image error, just add this JavaScript at the bottom of your page (just before the closing body tag):
(function() {
var allimgs = document.images;
for (var i = 0; i < allimgs.length; i++) {
allimgs[i].onerror = function() {
this.style.visibility = "hidden"; // Other elements aren't affected.
}
}
})();
It may be little late to answer, but here is my attempt.
When I faced the same issue I fixed it by using a div of the size of image & setting background-image to this div. If the image is not found, the div is rendered transparent, so its all done silently without java-script code.
Doing a quick research on Andy E's answer, its not possible to live() bind error.
// won't work (chrome 5)
$('img').live('error', function(){
$(this).css('visibility', 'hidden');
});
So you have to go like
$('<img/>', {
src: 'http://www.notarget.com/fake.jpg',
error: function(e){
$(this).css('visibility', 'hidden');
}
}).appendTo(document.body);
directly binding the error event handler on creating a new element.
i've found a nifty method to do exactly this, while being still functional when using ng-src directive in Angular.js and like...
<img
ng-src="{{myCtrl.myImageUrlThatWillDynamicallyChange}}"
onerror="this.src='data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='"
/>
it's basically a shortest transparent GIF (as seen
http://proger.i-forge.net/%D0%9A%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80/[20121112]%20The%20smallest%20transparent%20pixel.html )
of course this gif could be kept inside some global variable so it won't mess up the templates.
<script>
window.fallbackGif = "..."
</script>
and use
<img
ng-src="{{myCtrl.myImageUrlThatWillDynamicallyChange}}"
onerror="this.src=fallbackGif"
/>
etc.
Just simply add blank alt attribute on your <img>
Something like this: <img src="..." alt="">
Just Use simple css
.AdminImageHolder {
display: inline-block;
min-width: 100px;
max-width: 100px;
min-height: 100px;
max-height: 100px;
background: url(img/100x100.png) no-repeat;
border: 1px solid #ccc;
}

Categories