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.
Related
I have a carousel (Owl Carousel) with vertically centered controls. Because of the structure, I have to absolutely position the previous and next arrow. Because the page is responsive, their position is dynamic. The size of the controls may also change.
I've written a function that runs on load and resize. It gets the height of the image and the height of the controls, subtracts the latter from the former, divides by two, and then uses that number as the controls' margin-top.
It works, but I'm questioning if I'm getting and using all the variables correctly. Does JavaScript read in order? Where it runs the first line, then the next, then the next... I'm strong in CSS but JS has always been a crutch.
Can I write this more efficiently?
function centerCarouselControls() {
var carouselImage = $('.carousel-card > img');
var carouselControls = $('.owl-nav > div');
var carouselHeight = carouselImage.outerHeight();
var controlHeight = carouselControls.outerHeight();
var controlMargin = (carouselHeight - controlHeight) / 2;
carouselControls.css('margin-top', controlMargin);
}
$('.carousel-card > img').load(centerCarouselControls);
$(window).on('resize', centerCarouselControls);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I feel like this might be the type of question that gets flagged on here for not being specific enough. If that's the case, could someone please point me to a community where this would be more appropriate? Thanks!
In some browsers your code works like firefox 51, but it is more complete code this:
carouselControls.css('margin-top', controlMargin + 'px');
Let me start of by saying, I'm just now learning JS and Jquery, so my knowledge is very limited.
I've been looking around for 2 days now, and tried all sorts of combinations. But I just can't get this to work.
Below is an example of the layout
I'm looking for a way to trigger an event when div 1 is X px from the top of the screen. Or when div 1 collides with div 2.
What I'm trying to accomplish is to change the css of div 2 (the fixed menu) when div 1 is (in this case) 100px from the top of screen (browser window). Alternatively, when div1 passes div2 (I'm using responsive design, so the fixed height from top might become a problem on smaller screens right? Seeing as the header for example won't be there on a hand held.). So maybe collision detection is better here? Would really appreciate some thoughts and input on this matter.
Another issue is, div2 has to revert back to is previous css once div1 passes it (going back (beyond the 100px)).
This is what I have but it has no effect
$(document).ready(function() {
var content = $('#div1');
var top = $('#div2');
$(window).on('scroll', function() {
if(content.offset().top <= 100) {
top.css({'opacity': 0.8});
}else{
top.css({'opacity': 1});
}
});
});
I am not sure of the reason but $("#content").offset().top was giving a constant value on console. So I added window.scrollTOp() to check its distance from top, here is how it works,
$(document).ready(function() {
var top = $("#menu");
$(window).on('scroll', function(){
if(($('#content').offset().top - $(window).scrollTop()) <= 100){
top.css({'opacity': 0.4});
}else{
top.css({'opacity': 1});
}
});
});
And DEMO JSFIDDLE....
I have a function that corrects and adapts the size (and vertical alignment) of three fluid columns with text and images.
The script, while not polished/efficient yet, works exactly as expected but sometimes(?) fails at the beginning.
The functions is the following:
var resetHeight = function(){
var maxHeight = 0;
$(".same-height-col").height("auto").each(function(){
maxHeight = $(this).height() > maxHeight ? $(this).height() : maxHeight;
}).height(maxHeight + 25);
var maxTextSize = 0;
var tempHeight;
$(".same-height-col").each(function(){
tempHeight = $(this).find(".links-text").height();
maxTextSize = tempHeight > maxTextSize ? tempHeight : maxTextSize;
});
var topMargin;
$(".same-height-col").each(function(){
topMargin = (maxTextSize - $(this).find(".links-text").height()) + 25;
$(this).find(".links-image").css("margin-top",topMargin);
});
}
The I call it twice:
$(document).ready(function() {
resetHeight();
$(window).resize(function() {
resetHeight();
});
});
The problem is that many times when I load the page, I see this:
That doesn't happen consistently, but it does happen pretty often, but as soon as I resize the window the script works exactly as expected:
So where could the mistake be?
The script is called for sure even at the beginning, if I put an alert in the function, and just load the page (with no resize), the alert pops up.
When you calculate the maxHeight value, you reset all the inline heights that were set in the previous resetHeight call by doing $(".same-height-col").height("auto"). However, you don't reset the margin-top properties that were added to the links-image elements.
This means that the second time that resetHeight is called (and all subsequent times), the maxHeight calculations will be different. To make sure the results are the same each time, you need to reset the margin-top property on the links-image elements before doing the calculation.
$(".same-height-col .links-image").css("margin-top","");
$(".same-height-col").height("auto").each(function(){
maxHeight = $(this).height() > maxHeight ? $(this).height() : maxHeight;
}).height(maxHeight + 25);
You may also want to make that height maxHeight+50 rather than maxHeight+25 if you think the result of the layout after the resize looked better than the intial layout on load.
As i understand your issue, you should set attribute width and height of images and use the document ready handler:
HTML for all images in .links-image DIVs: {width/height/alt attributes should always be specified for image when possible}
<div class="links-image" style="margin-top: 53px;">
<img src="img/list.png" width="210" height="92" alt="">
</div>
JS code:
$(document).ready(function() {
$(window).resize(resetHeight).trigger('resize');
});
I’m starting with the premise that you want the box content components — the title, the subtitle, and the image — vertically aligned across all the three boxes. If this is not true, just ignore this answer.
While I can’t spot the issue in the code at hand, I would try to approach it another way, without JS: clearfix the columns and fix the height of the components: let’s say I expect titles to be one line of text, subtitles three lines, and images are already fixed-height.
The fixed height will give you vertical alignment, and the clearfix will take care of the column height.
I've got a Javascript curiosity that I must satisfy. Before I begin I should let you know that I am very aware of the fact that this can be handled with CSS alone, but I want to improve my Javascript skills so humor me :)
For reference to what I'm trying to get at: http://codepen.io/cmegown/pen/CGhpa
Let say we have a potentially infinite number of images, each wrapped inside of a figure set to display: inline-block so that it is the same size as the image inside. Each of these images can be any dimension, and the desired result is that the bottom of every image is perfectly aligned. The kicker here is that this is responsive, so the images may scale up or down. Here's my thinking of how this might be accomplished:
Loop through every image and find the tallest one (outerHeight), then grab that same image's width (outerWidth). Subtract the outerWidth from the outerHeight to get the "master" difference. Loop again through each image to calculate the difference for each specific image and subtract that from the "master" difference, then apply that number to the top margin. Rinse and repeat until each image is aligned to the bottom of the tallest image.
Right? I think the logic is sound, I just lack the skills to put this together properly in Javascript. Sorry for the super long post, but any and all help/advice is appreciated!
function alignImages() {
// caching selectors
var imgs = document.getElementsByTagName('img'),
maxHeight = 0;
for (idx in imgs) {
var img = imgs[idx];
if (img.height > maxHeight) {
maxHeight = img.height;
}
}
for (idx in imgs) {
var img = imgs[idx];
img.style.marginTop = (maxHeight - img.height) + "px";
}
}
I’m a totally JavaScript rookie, and I can’t really figure out how to do it.
I want a horizontal slider or tab script with thumbnails and arrow indication which thumbnail current showing in the slider, like this:
*http://jqueryglobe.com/labs/slide_thumbs/*
But it needs to be horizontal vertical. Can someone maybe help me to solve that problem?
Thanks in advance
Edit:
Yes, I'm sorry. I mean vertical. My bad.
It is not that hard actually.
You just need to re-order the HTML so that the images appear on the right/left of the preview main image container.
Then, if you look at the simple javascript involved, just modify everything that says "left" to "top" and "width" to "height" like so (this code is taken from the page itself -> view source):
$(document).ready(function() {
// Save the jQuery objects for later use.
var outer = $("#preview_outer");
var arrow = $("#arrow");
var thumbs = $("#thumbs span");
var preview_pos;
var preview_els = $("#preview_inner div");
var image_width = preview_els.eq(0).height(); // Get height of imaages
// Hook up the click event
thumbs.click(function() {
// Get position of current image
preview_pos = preview_els.eq( thumbs.index( this) ).position();
// Animate them!
outer.stop().animate( {'scrollTop' : preview_pos.top}, 500 );
arrow.stop().animate( {'top' : $(this).position().top }, 500 );
});
// Reset positions on load
arrow.css( {'top' : thumbs.eq(0).position().top } ).show();
outer.animate( {'scrollTop' : 0}, 0 );
// Set initial width
$("#preview_inner").css('height', preview_els.length * image_height);
});