Changing source of image with an image of different size, won't resize in IE - javascript

I'm trying to create a very simple gallery using javascript. There are thumbnails, and when they're clicked the big image's source gets updated. Everything works fine, except when I try it in IE the images' size stays the same as the inital image's size was. Let's say initial image is 200x200 and I click on a thumbnail of a 100x100 image, the image is displayed but it is streched to 200x200. I don't set any width or height values, so I guess the browser should use image's normal size, and so does for example FF.
here's some code:
function showBigImage(link)
{
var source = link.getAttribute("href");
var bigImage = document.getElementById("bigImage");
bigImage.setAttribute("src", source);
return false; /* prevent normal behaviour of <a> element when clicked */
}
and html looks like this:
<ul id="gallery">
<li>
<a href="images/gallery/1.jpg">
<img src="images/gallery/1thumb.jpg">
</a>
</li>
(more <li> elements ...)
</ul>
the big image is created dynamically:
function createBigImage()
{
var bigImage = document.createElement("img");
bigImage.setAttribute("id", "bigImage");
bigImage.setAttribute("src", "images/gallery/1.jpg");
var gal = document.getElementById("gallery");
var gal_parent = gal.parentNode;
gal_parent.insertBefore(bigImage, gal);
}
There's also some code setting the onclick events on the links, but I don't think it's relevant in this situaltion. As I said the problem is only with IE. Thanks in advance!

Sounds like IE is computing the width and height attributes for #bigImage when it is created and then not updating them when the src is changed. The other browsers are probably noting that they had to compute the image dimensions themselves so they recompute them when the src is changed. Both approaches are reasonable enough.
Do you know the proper size of the image inside showBigImage()? If you do, then set the width and height attributes explicitly when you change the src:
function showBigImage(link) {
var source = link.getAttribute("href");
var bigImage = document.getElementById("bigImage");
bigImage.setAttribute("src", source);
bigImage.setAttribute("width", the_proper_width);
bigImage.setAttribute("height", the_proper_height);
return false;
}
If you don't know the new dimensions then change showBigImage() to delete #bigImage and create a new one:
function createBigImage(src) {
var bigImage = document.createElement("img");
bigImage.setAttribute("id", "bigImage");
bigImage.setAttribute("src", src || "images/gallery/1.jpg");
var gal = document.getElementById("gallery");
gal.parentNode.insertBefore(bigImage, gal);
}
function showBigImage(link) {
var bigImage = document.getElementById("bigImage");
if(bigImage)
bigImage.parentNode.removeChild(bigImage);
createBigImage(link.getAttribute("href"););
return false;
}

Related

image overlay blinks when change css not when changing source

I have an imagemap of the Netherlands with an overlay effect on some of the areas. I can accomplish this effect in multiple ways:
1) Load every image. Set all but 1 image on 'display:none' and run JS (onMouseOver(str)) to display the image that one has the mouse on and hide all others.
css:
.verberg {
display: none;
}
JS:
var nederland = $('#Nederland');
var map1= $('#Friesland');
var map2= $('#Groningen');
var map3= $('#Drenthe');
var allmaps = $('.kaartje');
function mapOnMouseOver(str) {
var kaartnamen = ['Nederland', 'Friesland','Groningen', 'Drenthe']
var imgnamen = [nederland, map1, map2, map3]
var i = kaartnamen.indexOf(str);
if (i > -1) {
elementje = imgnamen[i];
allmaps.addClass('verberg');
elementje.removeClass('verberg');
}
}
2) Load one image and use JS (onMouseOver(str)) to change the source of the image.
JS:
function mapOnMouseOver(str) {
var kaartnamen = ['Nederland', 'Friesland','Groningen', 'Drenthe']
var urlsrc = ['nl.png','fr.png','gr.png','dr.png']
var i = kaartnamen.indexOf(str);
if (i > -1) {
newsrc = urlsrc[i];
$("#Nederland").attr("src","http://xxxxxxx/maps/"+ newsrc);
}
}
When I use the first method, everytime I load the page the image blinks when I hover an area for the first time. If I hover that area for a second time it doesn't until I reload the page again.
When I use the second method the image never blinks.
Can someone explain this different behaviour to me? I find it a bit counterintuitive. With the first method every image is already loaded, while with the second method the images are loaded when the mouse is on a specific area. It seems to me that the first method must be smoother, but it isn't...

onload triggering too early for ajax content in IE

I have a page where the images are supplied dynamically and are scaled with javascript to fit within the appropriate dimensions. This was initially being done with an onload attribute in the img tag, but then I noticed that in IE, the height being returned for the image was much less in some cases than the actual height, which ended up distorting the image. I solved this by finding and resizing all the images after $(window).load() was done, which worked fine for the initial page load, but I also have the page set up to add more content with an ajax call. For the ajax content, I tried some code I found on here that improved the problem, but didn't completely solve it. Here is an example of one of my image tags
<img id="img<?php echo $prodModObj->rolloverID; ?>" class="mbImg unsized" src="<?php echo $prodModObj->img; ?>" alt="<?php echo $prodModObj->name; ?>" onerror="swapImage(<?php echo $prodModObj->rolloverID; ?>)" />
The swapImage function just swaps out the image with a placeholder if there is an error while loading. Here is my JS
function swapImage(thisImgID) {
var imgID = 'img#img' + thisImgID;
$(imgID).attr('src', '/images/NoImageAvail.jpg');
}
function checkImage(thisImgID, fitDimension, spaceDimension) {
var imgID = 'img#img' + thisImgID;
var imgHeight = $(imgID).height();
var imgWidth = $(imgID).width();
var displayHeight, displayWidth, newMargin;
if (imgHeight > imgWidth) {
displayHeight = fitDimension;
displayWidth = imgWidth*(displayHeight/imgHeight);
} else if (imgHeight < imgWidth) {
displayWidth = fitDimension;
displayHeight = imgHeight*(displayWidth/imgWidth);
} else {
displayWidth = fitDimension;
displayHeight = fitDimension;
}
$(imgID).css('height', displayHeight);
$(imgID).css('width', displayWidth);
newMargin = ((spaceDimension - displayHeight)/2);
$(imgID).css('margin-top', newMargin);
$(imgID).removeClass('mbImg unsized').addClass('mbImg sized');
}
And then on the page I have
$(window).load(function(){
// Resize product images
$('.mbImg.unsized').each( function() {
var rolloverID = $(this).attr('id').substr(3);
checkImage(rolloverID,250,270);
});
});
And then in the success portion of the ajax call, I have
$('.mbImg.unsized').each( function() {
var rolloverID = $(this).attr('id').substr(3);
if (this.complete) {
checkImage(rolloverID,250,270);
} else {
$(this).on('load', function(){
checkImage(rolloverID,250,270);
});
}
});
Images that have been cached by the browser work fine, and the images in the initial page load work fine, but about 1 in 5 of new ajax images come out distorted. Is there another method I can use to size all the ajax images correctly in IE?
Thanks for your help,
Maybe come at it another way?
I've tried to move away from html4 style tag syntax, to using simple html5 tags and a combination of JavaScript and CSS to control the "view".
Check out this fiddle:
http://jsfiddle.net/zacwolf/s1haq3mz/
A question becomes how you want your images to flow, as using this approach all of the images are technically the same size (as demonstrated by the border). Also note that the .src for the second image I tweeked the url a bit so that it was a 404 for the image file, which triggered the one error image instead.
<img id="one" class="myclass" />
<img id="two" class="myclass" />
<style>
.myclass{
height:270px;
width:250px;
background-position:center,center;
background-repeat:no-repeat;
background-size:contain;
}
</style>
<script>
var one = new Image();
one.onerror=
function(){
this.src='http://leomarketingep.com/wp-content/uploads/Sign-Error-icon.png'
}
one.onload=
function(){
$('#one').css('background-image','url('+one.src+')')
}
one.src='https://cjjulian.files.wordpress.com/2009/04/blah_blah_blah-703369.jpg';
var two = new Image();
two.onerror=
function(){
this.src='http://leomarketingep.com/wp-content/uploads/Sign-Error-icon.png';
}
two.onload=
function(){
$('#two').css('background-image','url('+two.src+')')
}
two.src='https://cjjulian.files.wordpress.com/2019/04/blah_blah_blah-703369.jpg';
</script>
If you have a lot of images, you can populate an array of Image objects, for better referencing, etc.

Cross platform Canvas image zoom and crop make selection area fixed

Heavily inspired by this, I have made a plugin that works in mobiles and desktops to crop an image
What I made is added touch support, added dynamic canvas size based on image dimensions and trying to add functionality of moving an image rather selection area like here. I wanted to buy this item but it has failed my test case in devices (I am sorry to mention here). So thought of customizing the first mentioned source.
Here is the fiddle.
my html is
<div class="container">
<canvas id="panel" width="779" height="519"></canvas>
</div>
<input type="button" value="crop Selection" id="crop-image" />
<img id="croppedSelection" height="100px" width="100px" />
And calling it like
var Cropper = new CanvasCrop(document.getElementById('panel'), 'http://www.script- tutorials.com/demos/197/images/image.jpg');
$('#crop-image').on('click', function(){
var src = Cropper.getBase64();
$('#croppedSelection').attr('src', src);
});
My only problem is now, how can I keep the selection area on screen while image parent is being scrolled as here.
Thanks, help will be greatly appreciated.
Source code is huge to fit here, so added a working fiddle.. Thanks
Edit
Updated fiddle fixed canvas height and width issue
I wrote this code because I was bored.
Add this class above your code. you do not need the class if you only want one viewer on the page, you can put this all in a simple object. perhaps you need more:
function viewer (html_viewer)
{
this.html_viewer=html_viewer;
Object.defineProperty (html_viewer,"viewer_instance",{writeable:false,configureable:false,enumerable:false,value:this});
this.Selections=new Array ();
html_viewer.addEventListener ("mousedown",this.startScrolling);
html_viewer.addEventListener ("mouseup", this.endScrolling);
html_viewer.addEventListener ("scroll",this.setSelectionPosition);
}
viewer.prototype.startScrolling=function ()
{
var Selections=this.viewer_instance.Selections, Selection;
var l=Selections.length;
for (var i=0;i<l;i++)
{
Selection=Selections[i];
Selection.startLeft=Selection.x;
Selection.startTop=Selection.y;
Selection.viewer_startScrollLeft=this.scrollLeft;
Selection.viewer_startScrollTop=this.scrollTop;
}
}
viewer.prototype.setSelectionPosition=function ()
{
var Selections=this.viewer_instance.Selections, Selection;
var l=Selections.length;
for (var i=0;i<l;i++)
{
Selection=Selections[i];
Selection.x=this.scrollLeft-Selection.viewer_startScrollLeft+Selection.startLeft;
Selection.y=this.scrollTop-Selection.viewer_startScrollTop+Selection.startTop;
}
this.viewer_instance.drawScene ();
}
viewer.prototype.endScrolling=function ()
{
var Selections=this.viewer_instance.Selections, Selection;
var l=Selections.length;
for (var i=0;i<l;i++)
{
Selection=Selections[i];
Selection.startLeft=null;
Selection.startTop=null;
Selection.viewer_startScrollLeft=null;
Selection.viewer_startScrollTop=null;
}
}
viewer.prototype.addSelection=function (Selection)
{
Selection.startLeft=null;
Selection.startTop=null;
Selection.viewer_startScrollLeft=null;
Selection.viewer_startScrollTop=null;
Selection.viewerIndex=this.Selections.length;
this.Selections.push (Selection);
}
viewer.prototype.removeSelection=function (viewerIndex)
{
var Selections=this.Selections, l=Selections.length, i;
Selection=Selections[viewerIndex];
delete Selection.startLeft;
delete Selection.startTop;
delete Selection.viewer_startScrollLeft;
delete Selection.viewer_startScrollTop;
delete Selection.viewerIndex;
for (i=viewerIndex+1;i<l;i++)
Selections[i].viewerIndex=i-1;
Selections.splice (viewerIndex,1);
}
var imageViewer= new viewer (document.getElementById("panel").parentNode);
After line 27
theSelection = new Selection(64, 64, 64, 64);
Add
imageViewer.addSelection (theSelection);
imageViewer.drawScene=drawScene;
That's all, if you have problems let me know.
need further discussion how to implement image crop. do you want a selection inside the canvas or do you want to resize the complete imageCropper container and make a crop
// look at
http://jsfiddle.net/ThorstenArtnerAustria/5qdDW/1/

jQuery and Canvas loading behaviour

After being a long time lurker, this is my first post here! I've been RTFMing and searching everywhere for an answer to this question to no avail. I will try to be as informative as I can, hope you could help me.
This code is for my personal webpage.
I am trying to implement some sort of a modern click-map using HTML5 and jQuery.
In the website you would see the main image and a hidden canvas with the same size at the same coordinates with this picture drawn into it.
When the mouse hovers the main picture, it read the mouse pixel data (array of r,g,b,alpha) from the image drawn onto the canvas. When it sees the pixel color is black (in my case I only check the RED value, which in a black pixel would be 0) it knows the activate the relevant button.
(Originally, I got the idea from this article)
The reason I chose this method, is for the page to be responsive and dynamically change to fit different monitors and mobile devices. To achieve this, I call the DrawCanvas function every time the screen is re-sized, to redraw the canvas with the new dimensions.
Generally, this works OK. The thing is ,there seems to be an inconsistent behavior in Chrome and IE(9). When I initially open the page, I sometimes get no pixel data (0,0,0,0), until i re-size the browser. At first I figured there's some loading issues that are making this happen so I tried to hack it with setTimeout, it still doesn't work. I also tried to trigger the re-size event and call the drawCanvas function at document.ready, still didn't work.
What's bothering me is most, are the inconsistencies. Sometimes it works, sometimes is doesn't. Generally, it is more stable in chrome than in IE(9).
Here is the deprecated code:
<script type="text/javascript">
$(document).ready(function(){setTimeout(function() {
// Get main image object
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
// Create a hidden canvas the same size as the main image and append it to main div
var canvas = document.createElement('canvas');
canvas.height = mapWrapper.clientHeight;
canvas.width = mapWrapper.clientWidth;
canvas.fillStyle = 'rgb(255,255,255)';
canvas.style.display = 'none';
canvas.id = 'hiddencvs';
$('#map_wrapper').append(canvas);
// Draw the buttons image into the canvas
drawCanvas(null);
$("#map_wrapper").mousemove(function(e){
var canvas = document.getElementById('hiddencvs');
var context = canvas.getContext('2d');
var pos = findPos(this);
var x = e.pageX - pos.x;
var y = e.pageY - pos.y;
// Get pixel information array (red, green, blue, alpha)
var pixel = context.getImageData(x,y,1,1).data;
var red = pixel[0];
var main_img = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
if (red == 0)
{
...
}
else {
...
}
});
},3000);}); // End DOM Ready
function drawCanvas(e)
{
// Get context of hidden convas and set size according to main image
var cvs = document.getElementById('hiddencvs');
var ctx = cvs.getContext('2d');
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
cvs.width = mapWrapper.clientWidth;
cvs.height = mapWrapper.clientHeight;
// Create img element for buttons image
var img = document.createElement("img");
img.src = "img/main-page-buttons.png";
// Draw buttons image inside hidden canvas, strech it to canvas size
ctx.drawImage(img, 0, 0,cvs.width,cvs.height);
}
$(window).resize(function(e){
drawCanvas(e);
}
);
function findPos(obj)
{
...
}
</script>
I'd appreciate any help!
Thanks!
Ron.
You don't wait for the image to be loaded so, depending on the cache, you may draw an image or not in the canvas.
You should do this :
$(function(){
var img = document.createElement("img");
img.onload = function() {
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
...
// your whole code here !
...
}
img.src = "img/main-page-buttons.png";
});

How to do a process after completion of another one in JavaScript

I want to add an image by Javascript, then calculating the html element width as
window.onload=function(){
document.getElementById('x').addEventListener('click', function(e){
var el = document.getElementById('xx');
el.innerHTML = '<img src="img.jpg" />';
var width = el.offsetWidth;
.....
}, false);
}
but since JavaScript conduct all processes simultaneously, I will get the width of the element before loading the image. How can I make sure that the image has been loaded into the content; then calculating the element width?
UPDATE: Thanks for the answers, but I think there is a misunderstanding. img src="img.jpg" /> does not exist in the DOM document. It will be added later by Javascript. Then, when trying to catch the element by Id, it is not there probably.
You can give the img an ID and do the following :-
var heavyImage = document.getElementById("my-img");//assuming your img ID is my-img
heavyImage.onload = function(){
//your code after image is fully loaded
}
window.onload=function(){
document.getElementById('x').addEventListener('click', function(e){
var el = document.getElementById('xx');
var img = new Image();//dynamically create image
img.src = "img.jpg";//set the src
img.alt = "alt";
el.appendChild(img);//append the image to the el
img.onload = function(){
var width = el.offsetWidth;
}
}, false);
}
This is untested, but if you add the image to the DOM, set an onload/load event-handler and then assign the src of the image, the event-handling should fire (once it's loaded) and allow you to find the width.
This is imperfect, though, since if the image is loaded from the browser's cache the onload/load event may not fire at all (particularly in Chromium/Chrome, I believe, though this is from memory of a bug that may, or may not, have since been fixed).
For the chrome bug you can use the following:-
var BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';//create a blank source
var tImg = document.getElementById("my-img");//get the image
var origSrc = tImg.src;//get the original src
tImg.src = BLANK;//change the img src to blank.
tImg.src = origSrc;//Change it back to original src. This will lead the chrome to load the image again.
tImg.onload= function(){
//your code after the image load
}
You can use a library called PreloadJS or you can try something like this:
//Somewhere in your document loading:
loadImage(yourImage, callbackOnComplete);
function loadImage(image, callbackOnComplete){
var self = this;
if(!image.complete)
window.content.setTimeout(
function() { self.loadImage(image, callbackOnComplete)}
,1000);
else callbackOnComplete();
}
I did this when I worked with images base64 which delay on loading.

Categories

Resources