I have a div that contains text next to a b&w image. The entire div is set to 50% opacity. Upon hover over this div, I want to change the opacity to 100%, while also changing the source of the image (from the b&w one to the color). The functionality is fine; however, when it's hovered over, the opacity changes slightly before the image source changes, and it definitely looks a little funky. I've tried preloading the images, but that doesn't seem to change anything - still a slight delay in changing the img source.
Here is what my code looks like (the images have the almost same source, just the suffix is different, thus the strange looking code):
$('.character').on('mouseenter', function() {
var full_src = $(this).find('img').attr('src');
var half_src = full_src.split("-");
$(this).find('img').attr('src', half_src[0] + '-color.png');
$(this).css('opacity', 1);
});
$('.character').on('mouseleave', function() {
var full_src = $(this).find('img').attr('src');
var half_src = full_src.split("-");
$(this).find('img').attr('src', half_src[0] + '-bw.png');
$(this).css('opacity', .5);
});
Any ideas? Thanks in advance.
EDIT: Threw together a fiddle: http://jsfiddle.net/3WZ7J/ - does seem to work correctly most of the time, my images might be too large or not preloading correctly.
You can wait for the image to load before changing the opacity of the div
$('.character').on('mouseenter', function() {
var $this = $(this);
var full_src = $this.find('img').attr('src');
var half_src = full_src.split("-");
$this.find('img').load(function(){
$this.css('opacity', 1);
}).attr('src', half_src[0] + '-color.png');
});
FIDDLE
One thing you could try is .promise() to force the order in which the operations take place, so that the opacity won't change until the image has swapped out. Some info here: http://api.jquery.com/promise/
Related
I want to be able to dim a web page when a specific image is clicked on, using JavaScript. I had a look around and managed to get this far:
I have to create the image div on the fly, as indicated below. To change the screen opacity I created a ‘screen’ div inside the html document and set its opacity to 0. It works. The aim is to be able to add an attribute to the image div so that when it is clicked, the opacity of the screen div is changed to, say, 0.5. This solution below works, but in the sense that the screen div immediately changes opacity when I open it, rather than when the image is clicked. Also, I need to somehow figure out how to unset the opacity change once the image is clicked a second time. I guess I need a boolean + if-statement for this but can’t figure out how it might work in this situation. Any help will be greatly appreciated.
var img = document.createElement('img');
img.src = “images/myImage.jpg”;
img.onclick = dimmerSwitch();
document.body.appendChild(img);
function dimmerSwitch (){
var elem = document.getElementById("dimmer").style["opacity"] = "0.55";
}
You really don't need var elem variable in dimmerSwitch
function dimmerSwitch (){
document.getElementById("dimmer").style.opacity = "0.55";
}
would do the trick!
Also to toggle, the neater method would be to define css classes and toggle between them in your dimmerSwitch function, like
.dimmed{
opacity: 0.55;
}
Here's a neat tutorial which explains how you could do that: http://toddmotto.com/stop-toggling-classes-with-js-use-behaviour-driven-dom-manipulation-with-data-states/
The problem is my background images are of different sizes and unpredictable, so using a CSS transition will animate the stretch, which looks ugly. Thus, I really need to do this with JS.
var images = [
"http://ns223506.ovh.net/rozne/e800637ee8c7de5cdaed8df8ea3635f1/wallpaper-2585508.jpg",
"http://ns223506.ovh.net/rozne/15382371cb0d5b9319f5f4469bbc4511/wallpaper-2585497.jpg"
];
var counter = 0;
setInterval(function () {
$(".bg").css('backgroundImage', 'url("' + images[counter] + '")');
$('<img>').attr('src', images[++counter]); // preload the next image
if (counter == images.length) counter = 0;
}, 2000);
http://jsfiddle.net/mVAvF/1/
What I want to do is fade in the new background-image whilst fading out the old. Any suggestions?
You cannot fade one background into another in the same element.
You'll have to add another element on top of or behind the current background, then either fade the new element in if it is on top or fade the old one out if the new one is behind.
I answered a similar question before that contains a jsFiddle:
jQuery background image rotation script - looking to modify
I found this script on this site which helps to fadeIn/Out transparent .png's in IE without the transparent part being filled in with black during the fade effect:
var i;
for (i in document.images) {
if (document.images[i].src) {
var imgSrc = document.images[i].src;
if (imgSrc.substr(imgSrc.length-4) === '.png' || imgSrc.substr(imgSrc.length-4) === '.PNG') {
document.images[i].style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',sizingMethod='crop',src='" + imgSrc + "')";
}
}
}
This script was created by this stackoverflow user and it works perfectly well on my site. However, I want to modify it a little bit. This script finds ALL .png files on my page and applies the filter. However, this may be causing performance issues because I have many transparent .png files on my site, yet I only need to apply this filter to one of them. It's a fixed position menu DIV background image that fades in and fades out using jQuery while the page is scrolling.
Can someone help me to modify this script so that I can just provide it with one image or use getElementById("menu") and have it apply this filter. Nothing I have tried seems to work and putting the filter in my CSS didn't work either, so the javascript way seems to be the way to go. I just need to use it on one .png, not all of them.
Remember this is the background image of the div #menu, so the image itself has no ID, though of course the div does. Any help would be greatly appreciated.
According to the spec, document.images returns a collection of the img elements, so if it's background-image, that wouldn't work. However, if it's an img that being used in the background it will work. If you're just going to apply it to one image whose ID you know, then it'd be
function applyFilterToImageById(id) {
var i,
parentElement = document.getElementById(id);
for (i in parentElement.images) {
if (document.images[i].src) {
var imgSrc = document.images[i].src;
if (imgSrc.substr(imgSrc.length-4) === '.png' || imgSrc.substr(imgSrc.length-4) === '.PNG') {
document.images[i].style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',sizingMethod='crop',src='" + imgSrc + "')";
}
}
}
I have run into a strange phenomena I believe and I was wonder if anyone has a the answer to why this occurs. I have been doing a lot of manipulation of images for a photography site using a custom jQuery slideshow I created and have run into some problems.
I have a gallery here: http://www.daemondeveloper.com/photography/gallery.php
I have been adding some functions that resize the images in this gallery so that they scale to the size of the preview image size. As you can see, the very last image is panoramic and does not fill up the entire height of the div even though I have javascript telling it to resize.
If you refresh the page, the javascript seems to work all of a sudden and the pictures scales how it should.
Now try clicking on the panoramic picture of the girl and my slideshow will appear displaying the image scaled and centered vertically using jQuery. The function below is what handles clicking on the small image previews in the gallery.
If you look at where the commented changeSize() function is, that is where I USED to have the function and the scaling did not work. Then I moved it after the .show() functions which show my slideshow and now it works. So it appears that the display:none; affected how the javascript fired because when I debugged, the currentImg object was null, as if the .slides selector did not exist when it was set to display:none;. Is this really happening or am I just seeing a side effect of something else?
If this is really happening it may have something to do with the cause of the first problem I stated about the panoramic image not scaling on the first load of the gallery.php page.
$('.imgHolder').click(function(){
currentPosition = $('.imgHolder').index(this);
$('#slideShow').width(slideWidth);
// Remove scrollbar in JS
$('#slideContainer').css('overflow', 'hidden');
// Wrap all .slides with #slideInner div
slides.css({
'float' : 'left',
'width' : slideWidth
});
// Set #slideInner width equal to total width of all slides
$('#slideInner').css('width', (slideWidth * numberOfSlides));
// Hide left arrow control on first load
manageControls(currentPosition);
$('#slideInner').css('margin-left' , slideWidth*(-currentPosition));
//changeSize(); used to be here
$('#filter').show();
$('#photoWrap').show();
//Change image scale and center
changeSize();
});
And here is the changeSize() function that does the scaling and centering
function changeSize(){
currentSlide = $('.slide').get(currentPosition);
currentImg = $(currentSlide).children('img:first')[0];
imgRatio = $(currentImg).height() / $(currentImg).width();
if(imgRatio < slideRatio)
{
$(currentImg).addClass('landscape');
//Vertically align
var thisHeight = $(currentImg).height();
$(currentImg).css('margin-top', ($('#slideShow').height()/2)-(thisHeight/2));
}else{
$(currentImg).addClass('portrait');
}
}
$('#gallery ul li').each(function() {
var img = $(this).children('div').children('img').first();
var ratio = img.height() / img.width();
var goal = img.parent('div').height() / img.parent('div').width();
if (ratio < goal) {
img.addClass('portrait');
img.css('margin-left', -(img.width() / 2) + ($(this).children('div').width() / 2));
} else {
img.css('width', '100%');
}
});
Here I removed the unnecessary $() instances from your code, as you have already selected the element that you wish to call your methods on when you set the img variable. I doubt that this redundancy is the ultimate issue, but it is a good place to start.
Update your code to this and let's debug from there.
EDIT:
I think I found your error (well, I found one at least):
function configGallery()
{
var currentPosition;
var slides = $('.slide')
var currentSlide;
var currentImg;
var slideWidth = 720;
var numberOfSlides = slides.length;
...
}
Do you see what's wrong here? You forgot a semi-colon after var slides = $('.slide') and that could be your issue. Honestly, I'm surprised any of your scripts ran at all. Missing semi-colons usually crash the whole thing.
UPDATE:
Here are a few more selectors for you to remove the $() from when you get a chance:
function changeSize(){
currentSlide = $('.slide').get(currentPosition);
currentImg = $(currentSlide).children('img').first();
imgRatio = $(currentImg).height() / $(currentImg).width();
if(imgRatio < slideRatio)
{
$(currentImg).addClass('landscape');
//Vertically align
var thisHeight = $(currentImg).height();
$(currentImg).css('margin-top', ($('#slideShow').height()/2)-(thisHeight/2));
}else{
$(currentImg).addClass('portrait');
}
}
UPDATE:
Okay I wrote you a little fiddle to help you re-write your image-sizing function. I'll work on prettying it up and putting it in a plugin for you.
UPDATE:
Here's the same function again in a quick and dirty plugin: http://jsfiddle.net/Wj3RM/3/
I didn't pretty it up though - I figured it would be easier for you to adapt and modify like this.
i have a div element, with very big size background image. so, is it possible, to set a little size image as backgrount, untill the big size image loads.
thanks
I guess you could put another div element underneath it (using the z-index property) and give that the faster loading background image.
Whether that is practical to do, depends on your Layout, you'd have to give more information about that.
There's also the ages-old lowsrc HTML 4 property that still seems to be pretty well supported (I have not tried it myself since Netscape 4), but that won't work for background images.
CSS:
.that-div {
background-image:url(/path/to/small-image.png);
}
jQuery:
$(function () {
var bigImg = new Image(),
bigImgSrc = '/path/to/big-image.png';
bigImg.src = bigImgSrc;
$(bigImg).load(function(){
$('.that-div').css('background-image':'url('+bigImgSrc+')');
});
});