I'm building my personal e-commerce website with vertical rhythm in mind. It's just a challenge for myself. But images are so problematic for me. I need to set their height using javascript (script below?), for some images it's executed properly but not some others. The not executed properly images will have 0 height.
I've tried using window.onload but still don't work. I also looking for proper vanilla JS plugin but none of them available to use.
function adjustImg(element) {
var images = document.getElementsByTagName(element),
lineHeight = parseInt(window.getComputedStyle(document.body).getPropertyValue('line-height')),
newLineHeight = lineHeight / 2;
for(i = 0; i < images.length; i++) {
var aspectRatio = images[i].offsetWidth / images[i].offsetHeight,
originalHeight = images[i].offsetWidth / aspectRatio,
div = Math.round(originalHeight / newLineHeight),
newHeight = newLineHeight * div;
images[i].style.height = newHeight + 'px';
}
}
I expected all images to have corrected height properly. But like I said some of them don't show up because of the 0 height. My hypothesis is because the image is not completely loaded, but the javascript has been executed. Therefore the javascript could not obtain the offsetWidth and offsetHeight
I've no idea how to fix this issue, any helps are much appreciated. Sorry for my english.
Perhaps try img.onload. This event fires when an image is loaded.
Related
I was wondering if there is an easy way to change the CSS classes in JavaScript.
I have gone through all other similar questions here and I couldn't find an straight-forward and simple solution.
what I'm trying to do is to set the width and height of a <div> to match an image that I have on my site (upon loading). I already know the picture dimensions and I can set my CSS to that - but I want my script to figure this out on its own.
After hours of r&d (I'm a beginner), this is what I came up with:
var myImg = new Image();
myImg.src = "img/default.jpg";
myImg.onload = function(){
var imgWidth = this.width;
var imgHeight = this.height;
document.getElementById("myBg").setAttribute('style', "height :"+ imgHeight + "px");
document.getElementById("myBg").setAttribute('style', "width :"+ imgWidth + "px");
};
However, this only sets the width of the element with id "myBg". If I reverse the order of the height and width, then it only sets the height to the image's height.
It seems like first it sets the height of the element to the image height but right after it moves to the next statement to set the width, the height value goes back to what it what defined originally in css.
I did further research online and seems like changing the css (inserting new attributes, removing, etc.) using JavaScript is not an easy task. It is done through
document.styleSheets[i].cssRules[i] or document.styleSheets[i].addRule
type of commands, but all the tutorials online and here on stackoverflow were confusing and complicated.
I was wondering if anyone familiar with document.styleSheets can explain this to me simply?
Imagine I have this class in my separate css file:
.container
{
height: 600px;
width: 500px;
}
I want the height and width to change to the dimension of the picture upon loading. How do I do this?
I don't want to define a new "style" element in my html file, I want to change the css file.
I'm not supposed to know the image dimension before it loads to the page.
no jquery please, I want to do this using only standard JavaScript.
Thank you.
The reason only one or the other works is because in your second line of code, you destroy the whole style attribute, and recreate it. Note that setAttribute() overwrites the whole attribute.
A better solution would be to use the element.style property, not the attribute;
var bg = document.getElementById("myBg");
bg.style.width = imgWidth + "px";
bg.style.height = imgHeight + "px";
You can grab all elements with class container and apply it to each of them like this:
var elements = document.querySelectorAll('.container');
for(var i=0; i<elements.length; i++){
elements[i].style.width = imgWidth + "px";
elements[i].style.height = imgHeight + "px";
}
Note querySelectorAll isn't supported by IE7 or lower, if you need those then there are shims for getElementsByClassName() here on SO.
If your rules start incrementing you could extract your css to a new class and switch classes:
CSS:
.container-1{
/* A set of rules */
}
.container-2{
/* A set of rules */
}
JavaScript:
element.className = element.className.replace(/container-1/, 'container-2')
var object = document.createElement('container');
object.style.width= "500px";
object.style.height= "600px";
You can also add values to this if you hold the dimensions in variables
var height = 600;
var width = 500;
You can increment when needed
height += 5;
Here is something you might find useful. It may offer you some insight on how you can solve a problem with many different approaches, seeing as though you are new to js.
I need to use some data, calculated by JS (for example: window size) as css property of some HTML element. To avoid flickering of the window because of layout changes, I can't afford to use document.onready. I actually need to trigger JS function at the time the DOM element is added to the DOM tree.
I've tried with DOMNodeInserted event, but it seems that it triggered only for elements that are added post-loading the HTML code, with JavaScript.
What I need is to change tag that is presented in the original HTML source of the page. So for now I just inline JavaScript just after the HTML code of the tag that has to be changed, but is there a way to do this without inlining JS after every such tag. Something like DOMNodeInserted, but triggered while the original HTML is being rendered. Or how else I can accomplish this - having a JS dependent layout that does not move after it's loaded (it's properly generated before showing it to the user) and still have HTML code in the page (e.g. do not generate the page entirely from JavaScript)?
UPDATE
here is the javascript that is used to resize image. It respects both width and height, while widht:100% or height:100% works unless the window width/height is not smaller then image itself.
function resizeImg() {
var imgwidth = bgImg.width();
var imgheight = bgImg.height();
var winwidth = $(window).width();
var winheight = $(window).height();
var imgratio = imgwidth / imgheight;
imgwidth = winwidth;
imgheight = winwidth / imgratio;
if (imgheight < winheight) {
imgheight = winheight;
imgwidth = imgheight * imgratio;
}
$('.cover-image').css({
width: winwidth+'px',
height: winheight+'px'
});
}
You can use a script to compose a stylesheet and add it to a new style element on the head before the body renders.
Or you can use media queries in a style sheet and apply the styles you prefer for different window or device dimensions.
I'm currently building a site and using the Shadowbox JS plugin to display images.
Because we serve up images via a JSP (rather than linking directly to image files), Shadowbox seems unable to dynamically determine their width and height and so just opens the images in an overlay of ~the screen size.
It's possible to manually pass in widths and heights to the shadowbox plugin using 'rel', so I've got around the problem for FF/Chrome/Safari using the following code:
$('#pic1img').attr("src")).load(function() {
picWidth = this.width;
picHeight = this.height;
});
$(window).load(
function() {
var w = $("#pic1img").width();
var h = $("#pic1img").height();
if( picWidth < w ){ picWidth = w; }
if( picHeight < h ){ picHeight = h; }
$('#pic1').attr('rel', 'shadowbox[pics];height=' + picHeight + ';width=' + picWidth);
}
);
But I can't find any way to do the same in IE.
The code actually worked once I began loading the thumbnails at full size and then setting their width and height after load.
The issue was that I was setting a surrounding div to
display: none
until the images were loaded and IE can't work out the sizes of hidden images.
Resolved this by setting
visibility: hidden
instead.
I'm trying to counteract an adjustment to the height of an element which is above the scroll offset by calculating the difference in height and then updating the current scroll position to account for it.
The problem is that there's no way that I can prevent a very quick flickering artefact. Whether I adjust the element's height and then the scroll position, or vice versa, I can't seem to prevent a quick visual jump.
Does anyone know how this could be overcome? I want these to operations to happen at the same time with no rendering in-between but I'm not sure if it's possible.
// Setup
...
var myElement = ...
var oldHeight = ...
var scrollOffset = window.scrollY;
var newHeight = 100;
var diff = newHeight - oldHeight;
// Determine if we need to counteract new size
var adjustScroll = (absoluteOffset(myElement) < scrollOffset);
// Adjust size
myElement.style.height = newHeight+'px';
// Adjust scroll to counteract the new height
if (adjustScroll) window.scrollTo(0, scrollOffset+diff);
I'm working with WebKit, specifically on iOS.
for webkit you can use CSS transitions/animations to smooth this but it's still sound like you are going the wrong way to begin with. I am sure that whatever is it you are trying to do can be solved purely with CSS (maybe with some very minimal Javaqscript). Post an example of you HTML + CSS + JS.
You could use scrollIntoView with timers to simulate multiple threads.
Or you could do it inside a document fragment beforehand.
Sorry to be reviving an old post here, but i came across this looking for a solution to a similar problem to do with browser resizing.
Stackoverflow user James Kyle created this little jsfiddle using jQuery that attempts to maintain scroll position as best as possible when a page is resized
var html = $('html'),
H = html.outerHeight(true),
S = $(window).scrollTop(),
P = S/H;
$(window).scroll(function() {
S = $(window).scrollTop();
P = S/H;
});
$(window).resize(function() {
H = html.outerHeight(true);
$(window).scrollTop(P*H);
});
http://jsfiddle.net/JamesKyle/RmNap/
you could try using this same code and trigger a 'resize' event on the html when the image has loaded by using a jQuery library like imagesLoaded
I've got some code to maximize a video panel on page load / resize. I'm using JQuery 1.4.4 and everything is working great in Chrome, Firefox and Safari. Following some examples from some other posts, I adjust the video panel size based on the rendered size and styling of the other elements on the screen.
function maximizeVideo(){
var play_height = $(window).height()-42;
var play_width = $PLAY.width() - $NAV.width();
play_width -= parseInt($NAV.css("paddingLeft"), 10) + parseInt($NAV.css("paddingRight"), 10);
play_width -= parseInt($NAV.css("marginLeft"), 10) + parseInt($NAV.css("marginRight"), 10);
play_width -= parseInt($NAV.css("borderLeftWidth"), 10) + parseInt($NAV.css("borderRightWidth"), 10);
$NAV.css('height',play_height-16+"px");
$VIDEO_PANEL.resize(play_width, play_height);
}
In IE the css accessor sometimes returns NaN. Is there a better way to account for the rendered width of the other element?
If not, what's the best way to trap these errors?
Thanks!
For your situation, I think you should be looking at the outerWidth function instead of width. Using outerWidth(true), we can obtain the width of the element including its borders, padding and margin. Therefore you can replace this line:
var play_width = $PLAY.width() - $NAV.width();
with this:
var play_width = $PLAY.width() - $NAV.outerWidth(true);
And thus eliminating the next three lines of calculations altogether.
Additionally, the height and width functions are not just getters, but also setters, so this line:
$NAV.css('height',play_height-16+"px");
can be rewritten as
$NAV.height(play_height - 16);