JS OnLoad Images Not Being Resized - javascript

So I am sure I am missing something small here. I wrote this awhile ago but I came back to it the other day to try and remember why I stopped working on it. Then I realized it's because when you load the page for the first time it doesn't resize the images in the image gallery container.
Then on page refresh the images resize themselves the way they are supposed to. Here is the code.
var ImageGallery = (function(){
/*
Load Images expects an array of URLS for your images, then
it returns an array of new images.
*/
function loadImages(urls){
var images = [];
for(i = 0; i < urls.length; i++){
var tempImage = new Image();
tempImage.src = urls[i];
tempImage.className = "slider-images";
var image = scaleImage(tempImage, 100,100);
//adds even listener to each image
image.addEventListener('click', function(){
addMainPicture(this);
}, false);
images.push(image);
}
var imageContainer = document.getElementById("image-container");
for(i = 0; i < images.length; i++){
imageContainer.appendChild(images[i]);
}
//add main picture
var temp = new Image();
temp.src = urls[0];
temp.className = "slider-images";
var tempMainImage = scaleImage(temp,350,350);
console.log(tempMainImage);
addMainPicture(tempMainImage);
}
/*
Adds the Main Picture. In here you can set the size you want the image
to be, and other styling for the image. Takes in the url for the image.
*/
function addMainPicture(image){
var mainPicture = document.getElementById("main-picture");
mainPicture.src = image.src;
//add styles
mainPicture.style.display = "block";
mainPicture.style.margin = "0px auto";
}
/*
Scales the image taken in to the maxWidth, and maxHeight
stated.Only scales down. Not up.
*/
function scaleImage(img, maxW, maxH){
var maxWidth = maxW,
maxHeight = maxH,
ratio = 0,
imgWidth = img.width,
imgHeight = img.height;
//check width
if(imgWidth > maxWidth){
ratio = maxWidth / imgWidth;
img.width = maxWidth;
img.height = imgHeight * ratio;
imgHeight = imgHeight * ratio;
imgWidth = imgWidth * ratio;
}
//check height
if(imgHeight > maxHeight){
ratio = maxHeight / imgHeight;
img.height = maxHeight;
img.width = maxWidth;
imgWidth = imgWidth * ratio;
}
return img;
}
/*
This runs it all.
*/
function init(){
var urls = ["http://placehold.it/400x400","http://placehold.it/400x400/FFF000","http://placehold.it/400x400/FF0000","http://placehold.it/400x400/0000FF"];
//load in urls for images
loadImages(urls);
var leftButton = document.getElementById("scroll-left"),
rightButton = document.getElementById("scroll-right");
leftButton.addEventListener('click', function(){
var imageContainer = document.getElementById("image-container");
var currentLeft = "";
//checks for NaN
if(imageContainer.style.left == ""){
currentLeft = 0;
}else{
currentLeft = parseInt(imageContainer.style.left);
}
var end = currentLeft + 300;
function frame(){
currentLeft+=5;
imageContainer.style.left = currentLeft+"px";
if(currentLeft == end)
clearInterval(id);
}
var id = setInterval(frame, 10);
}, false);
rightButton.addEventListener('click', function(){
var imageContainer = document.getElementById("image-container");
var currentLeft = "";
if(imageContainer.style.left == ""){
currentLeft = 0;
}else{
currentLeft = parseInt(imageContainer.style.left);
}
var end = currentLeft - 300;
function frame(){
currentLeft-=5;
imageContainer.style.left = currentLeft+"px";
if(currentLeft == end)
clearInterval(id);
}
var id = setInterval(frame, 10);
}, false);
}
return {
init: function(){
init();
}
}
}());
ImageGallery.init();
Sure I am missing something small here but would really like another set of eyes on it.
Here is the fiddle.

Use onLoad event for images. Because your images are not loaded and you need to load images first to scale them:-
tempImage.onload = function(){
scaleImage(this, 100,100);//here your scale code goes
}

You need to run ImageGallery.init(); once the document has loaded, with jQuery you would use:
$(function() {
ImageGallery.init();
});
Without jQuery, you can use
<body onload="ImageGallery.init();">

Related

jQuery - get different values from elements with same class

function ratioDetect () {
var contWidth = $('.thumbnail-container').width()
var contHeight = $('.thumbnail-container').height()
var imgWidth = $('.thumbnail-container img').width()
var imgHeight = $('.thumbnail-container img').height()
var contRatio = contWidth/contHeight
var imgRatio = imgWidth/imgHeight
if (contRatio > imgRatio) {
$('.thumbnail-container img').removeClass('full-height')
$('.thumbnail-container img').addClass('full-width')
}
else{
$('.thumbnail-container img').removeClass('full-width')
$('.thumbnail-container img').addClass('full-height')
}
}
It should be pretty clear what this function does, the problem is I have 6 of these "thumbnail-container" so the script just get the values from the FIRST container only and does this math based just on the img inside this container and applies the values to all the other images.
I've tried to follow some tutorial for the ".this" usage but I failed. I need this code act separately for each individual container and his child-img because the size of each of the 6 <img>s is different.
You need to iterate over the container and process
function ratioDetect() {
$('.thumbnail-container').each(function () {
var $this = $(this),
$img = $this.find('img'),
contWidth = $this.width(),
contHeight = $this.height(),
imgWidth = $img.width(),
imgHeight = $img.height();
var contRatio = contWidth / contHeight,
imgRatio = imgWidth / imgHeight;
if (contRatio > imgRatio) {
$img.removeClass('full-height');
$img.addClass('full-width');
} else {
$img.removeClass('full-width');
$img.addClass('full-height');
}
});
}

Multiple image upload & resize freezes chrome or even crashes it

I have a Javascript that allows to resize multiple images and uploads them. So far it works until you choose more than about 5 files. From about 5 to 25 selected files Chrome browser (or others) just gets really slow, if you choose even more the browser crashes.
It seems to take a lot of memory.
Do you have any suggestions what could avoid the freezing of the browser/computer or the crash?
Thank you very much for your help!
// Once files have been selected
document.querySelector('form input[type=file]').addEventListener('change', function(event){
$( "#load" ).html( "<img src=\"http://www.maxk.at/image_uploader/ajax-loader.gif\"> Upload läuft" );
// Read files
var files = event.target.files;
// Iterate through files
var j=1;
var k=files.length;
for (var i = 0; i < files.length; i++) {
// Ensure it's an image
if (files[i].type.match(/image.*/)) {
// Load image
var reader = new FileReader();
reader.onload = function (readerEvent) {
var image = new Image();
image.onload = function (imageEvent) {
// Add elemnt to page
var imageElement = document.createElement('div');
imageElement.classList.add('uploading');
imageElement.innerHTML = '<span class="progress"><span></span></span>';
var progressElement = imageElement.querySelector('span.progress span');
progressElement.style.width = 0;
document.querySelector('form div.photos').appendChild(imageElement);
// Resize image
var canvas = document.createElement('canvas'),
max_size = 1200,
width = image.width,
height = image.height;
if (width > height) {
if (width > max_size) {
height *= max_size / width;
width = max_size;
}
} else {
if (height > max_size) {
width *= max_size / height;
height = max_size;
}
}
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(image, 0, 0, width, height);
// Upload image
var xhr = new XMLHttpRequest();
if (xhr.upload) {
// Update progress
xhr.upload.addEventListener('progress', function(event) {
var percent = parseInt(event.loaded / event.total * 100);
progressElement.style.width = percent+'%';
}, false);
// File uploaded / failed
xhr.onreadystatechange = function(event) {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
imageElement.classList.remove('uploading');
imageElement.classList.add('uploaded');
imageElement.style.backgroundImage = 'url('+xhr.responseText+')';
console.log('Image uploaded: '+j+k+'Abstand'+xhr.responseText);
j++;
if (j==k){$("#load").html("Upload beendet");}
if (k==1){$("#load").html("Upload beendet");}
} else {
imageElement.parentNode.removeChild(imageElement);
}
}
}
// Start upload
xhr.open('post', 'process.php', true);
xhr.send(canvas.toDataURL('image/jpeg'));
}
}
image.src = readerEvent.target.result;
}
reader.readAsDataURL(files[i]);
}
}
// Clear files
event.target.value = '';
});

Javascript Image resizing is not working properly in IE11 but working in remaing versions(10,9,8)

I am using wicket framework (html +java) in my application where i need to resize an image when the componenet loads.This code is working fine in IE8,9,10.But it is failing sometimes in IE11.
Some times it is able to resize and but sometimes it is not able to do so.Actully it is not going into the javascript code whenver it fails.
Please help me in solving the issue.
<img wicket:id="bigImage" onload="resize_imgs(140,140,112,112)" />
Here the above image compnenet is calling following javascript code and will perfrom the image resizing.
<script type="text/javascript">
function resize_imgs(maxht, maxwt, minht, minwt) {
alert("first line");
var imgs = document.getElementsByTagName('img');
var resize_img = function (img, newht, newwt) {
img.height = newht;
img.width = newwt;
alert("in resize image function :newht" + newht + "newwt:" + newwt);
};
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
if (img.height > maxht || img.width > maxwt) {
var old_ratio = img.height / img.width;
var min_ratio = minht / minwt;
if (old_ratio === min_ratio) {
alert("ratios equal");
resize_img(img, minht, minwt);
}
else {
var newdim = [img.height, img.width];
newdim[0] = minht;
newdim[1] = newdim[0] / old_ratio;
if (newdim[1] > maxwt) {
newdim[1] = minwt;
newdim[0] = newdim[1] * old_ratio;
}
alert("ratios not equal");
resize_img(img, newdim[0], newdim[1]);
}
}
}
}
</script>
UPDATE1:
In my appllication there are lot of images in a page and when we click on image or opens that page it will take first image or clicked image and will set it in top corner of the page.So whenever that component loads (img wicket:id="bigImage" onload="resize_imgs(140,140,112,112)" /> )we will call onload event.Now i have been trying with jquery.I updated it in the question.Could you please suggest me whether it is correct or not.
<img class="resizeImage" wicket:id="bigImage" />
$(document).ready(function(){
$(".resizeImage").one("load", function() {
// do stuff
var maxht=140;
var maxwt =140;
var minht=112;
var minwt=112;
var img_height = $(this).height();
var img_width = $(this).width();
if (img_height > maxht || img_width > maxwt) {
var old_ratio = img_height / img_width;
var min_ratio = minht / minwt;
if (old_ratio === min_ratio) {
$(this).css('height',minht);
$(this).css('width',minwt);
}
else {
var newdim = [img_height, img_width];
newdim[0] = minht;
newdim[1] = newdim[0] / old_ratio;
if (newdim[1] > maxwt) {
newdim[1] = minwt;
newdim[0] = newdim[1] * old_ratio;
}
$(this).css('height',newdim[0]);
$(this).css('width',newdim[1]);
}
}}).each(function() {
if(this.complete) $(this).load();
});
If the image can be pulled from the cache immediately, then IE won't trigger the load event for the image at all.
You can check if the complete property of the image is true. Then the image is already loaded and you won't get a load event, so you can just call the function directly. Example:
var image = $('img');
if (image.prop('complete')) {
resize_imgs(140,140,112,112);
} else {
image.load(function(){
resize_imgs(140,140,112,112);
});
}

wrong image height in canvas

I have a canvas like this
<canvas id="canvas" width="600px" height="300px"></canvas>
Now I am trying to show image inside the canvas of some 260px width and height. But its showing the image full screened in canvas. What I am doing wrong?
img.onload = function(){
var im = this;
var imgWidth = im.width;
var imgHeight = im.height;
var imgScaledWidth = 0;
var imgScaledHeight = 0;
imgScaledHeight = self.conHeight - 40;
imgScaledWidth = imgScaledHeight * (imgWidth/imgHeight);
self.context.drawImage(this, 0,0,imgScaledWidth,imgScaledHeight);
}
Its showing like this
There's no reason why your code shouldn't be working based on what you've shown in the question. Here is an example based on the code you've given with some minor changes to account for not having a self variable.
<script>
var img = document.getElementById("image");
var c = document.getElementById("canvas");
var con = c.getContext("2d");
img.onload = function(){
var im = this;
var imgWidth = im.width;
var imgHeight = im.height;
var imgScaledWidth = 0;
var imgScaledHeight = 0;
var off=20;
imgScaledHeight = c.height - off;
imgScaledWidth = imgScaledHeight * (imgWidth/imgHeight);
con.drawImage(this, 0,0+(off/2),imgScaledWidth,imgScaledHeight);
}
</script>
You are stretching it. If you don't want to show the image stretched, just don't pass any size to drawImage:
self.context.drawImage(this, 0, 0);

Image() onLoad not waiting for image to load

I've figured out the centering and resizing issues, but I still can't get onLoad to work properly. Anyone have any ideas? I thought onLoad was supposed to wait for the image to be loaded completely before firing the code. As this is right now, it resizes the img for the next img, and fades it in before it's loaded, so the previous image fades in again. Once the show has run through once, it works perfectly, so obviously it's not waiting for the image to load completely before firing imageLoad().
<div id="slideShow">
<div id="slideShowImg" style="display:none; margin-right:auto; margin-left:auto;">
</div>
<div id="slideShowThumbs">
</div>
<script type="text/javascript">
loadXMLDoc('http://www.thehoppr.com/hopspots/82/82.xml', function() {
var slideShow = document.getElementById('slideShow');
var items = [];
var nl = xmlhttp.responseXML.getElementsByTagName('image');
var i = 0;
var t;
var slideShowImg = document.getElementById('slideShowImg');
var slideShow = document.getElementById('slideShow');
var maxHeight = 300;
var maxWidth = 800;
var imgNode = new Image();
function image() {
var nli = nl.item(i);
var src = nli.getAttribute('src').toString();
var width = parseInt(nli.getAttribute('width').toString());
var height = parseInt(nli.getAttribute('height').toString());
imgNode.onLoad = imageLoad();
imgNode.src = src;
imgNode.height = height;
imgNode.width = width;
imgNode.setAttribute("style", "margin-right:auto; margin-left:auto; display:block;");
var ratio = maxHeight / maxWidth;
if (imgNode.height / imgNode.width > ratio) {
// height is the problem
if (imgNode.height > maxHeight) {
imgNode.width = Math.round(imgNode.width * (maxHeight / imgNode.height));
imgNode.height = maxHeight;
}
} else {
// width is the problem
if (imgNode.width > maxHeight) {
imgNode.height = Math.round(imgNode.height * (maxWidth / imgNode.width));
imgNode.width = maxWidth;
}
}
}
function imageLoad() {
slideShowImg.appendChild(imgNode);
Effect.Appear('slideShowImg', {
duration: 1
});
t = setTimeout(nextImage, 7000);
}
function nextImage() {
slideShowImg.setAttribute("style", "display:none");
if (i < nl.length - 1) {
i++;
image();
} else {
i = 0;
image();
}
}
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//XML Loaded, create the slideshow
alert(xmlhttp.responseText);
image();
}
});
</script>
Here are some of my thoughts (it's all open discussion)...
Preloading - Since you're limited to downloading 2 resources in parallel per hostname, it may not make sense to preload everything up front. Since it's a slideshow, how about modifying image() to download the i + 1 image through an Image object that doesn't get appended to the DOM? It doesn't seem beneficial to prefetch i + 2 and beyond in a slideshow setting.
Centering the images - Regarding using the auto margin width for horizontal centering, I believe you'll have to explicitly set the image to display:block. Obviously that doesn't solve centering vertically. Are all the images the same size? Also, will the slideShowImg div have a defined height/width? If so, then some math can be applied to achieve the centering.
Hope this helps! :)
Ok so I fixed the issue with the onLoad, and I even added a little preloading to help the slideshow along as well. All I had to do was define the onload first, and then do everything else except define the src inside the onload's function. I then added a little nextImg preloading so there's little if no hiccup between images even if it's the first time the browser is loading them. Here's the final code for anyone who has similar onload issues and finds there way here:
<div id="slideShow">
<div id="slideShowImg" style="display:none; margin-right:auto; margin-left:auto;">
</div>
<div id="slideShowThumbs">
</div>
<script type="text/javascript">
loadXMLDoc('/82.xml', function() {
var slideShow = document.getElementById('slideShow');
var items = [];
var nl = xmlhttp.responseXML.getElementsByTagName('image');
var i = 0;
var t;
var slideShowImg = document.getElementById('slideShowImg');
var slideShow = document.getElementById('slideShow');
var maxHeight = 300;
var maxWidth = 800;
var curImg = new Image();
var nextImg = new Image();
function image() {
var cli = nl.item(i);
var src = cli.getAttribute('src').toString();
var width = parseInt(cli.getAttribute('width').toString());
var height = parseInt(cli.getAttribute('height').toString());
curImg.onload = function() {
curImg.height = height;
curImg.width = width;
curImg.setAttribute("style", "margin-right:auto; margin-left:auto; display:block;");
slideShowImg.appendChild(curImg);
var ratio = maxHeight / maxWidth;
if (curImg.height / curImg.width > ratio) {
// height is the problem
if (curImg.height > maxHeight) {
curImg.width = Math.round(curImg.width * (maxHeight / curImg.height));
curImg.height = maxHeight;
}
} else {
// width is the problem
if (curImg.width > maxHeight) {
curImg.height = Math.round(curImg.height * (maxWidth / curImg.width));
curImg.width = maxWidth;
}
}
}
curImg.src = src;
if (i < nl.length - 1) {
var nli = nl.item(i + 1);
var nsrc = nli.getAttribute('src').toString();
nextImg.src = nsrc;
}
Effect.Appear('slideShowImg', {
duration: 1
});
t = setTimeout(nextImage, 7000);
}
function imageLoad() {}
function nextImage() {
slideShowImg.removeChild(curImg);
slideShowImg.setAttribute("style", "display:none");
if (i < nl.length - 1) {
i++;
image();
} else {
i = 0;
image();
}
}
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//XML Loaded, create the slideshow
alert(xmlhttp.responseText);
image();
}
});
</script>

Categories