jQuery: JavaScript does not do what I tell it to - javascript

I know that the title is very subtle but I have absolutely no idea how I should title this issue nor what the hell is happening with this function.
function update_background(source, isSystem){
if (!isSystem) {
source.replace(/\/tn_/, '');
jQuery('div#drag_container img[alt="background"]').attr('src', source); //*1
jQuery('div#drag_container img[alt="background"]').attr('style', '');
var height = jQuery('div#drag_container img[alt="background"]').height();
var width = jQuery('div#drag_container img[alt="background"]').width();
var ratio = Storyboard['format'];
//Don't touch the paddings, they are correct!
if (height * ratio > width) {
var padding = (Storyboard['display'] - (width * (Storyboard['height'] / height))) / 2;
jQuery('div#drag_container img[alt="background"]').css({
'height': Storyboard['height'],
'padding-left': padding
});
} else {
var padding = (Storyboard['height'] - (height * (Storyboard['display'] / width))) / 2;
jQuery('div#drag_container img[alt="background"]').css({
'width': Storyboard['display'],
'padding-top': padding,
'padding-bottom': padding
});
}
} else {
jQuery('div#drag_container img[alt="background"]').attr('src', source).attr('style', '');
jQuery('div#drag_container img[alt="background"]').css({
'width': Storyboard['display'],
'height': Storyboard['height']
});
}
}
What this function is supposed to do, is take a picture, get the size of it, compare it to the the size of the container it will be shown in, resize it so that it is as big as possible without sticking out of the container and then finally, apply padding where needed to center the image. It does not matter if the picture is landscape or portrait, the function knows exactly what to do. The picture is cached so that we don't get wrong values (I already had a bug like that). In case it is a System Background, we don't care for correct size and padding. Worked flawless for 3 months.
Lately, it is behaving rather odd. At the line with the comment *1, it does not only reset the src attribute of the img-tag, but it also sets a height and a padding, as if it already were in the padding calculations. They are removed again on the next line (which wasn't actually inserted for that purpose but was inserted to get the original dimensions of a picture) and it still works.
Unless, of course, you let the function run at regular speed, where it does not reset the style. I am quite irritated by this Bug as I have no idea where to start searching.
The function is only called once. It only runs once through the function. It is not included in an event and this function is called in 2 totally different places.
Any ideas?
Edit 1
I have found out that the Bug does not occur in every Browser.
Mac OS X Snow Leopard
Firefox: behavior as described
Opera: does it all wrong, but is not supported by our company
Safari: Still works flawless
Windows XP
Chrome: Works same as Safari
Firefox: Behavior as described
IE8: Same Behavior
IE7: Actually Works!
Linux
Firefox: Behavior as described
Konqueror: does not even work with my JavaScript

You might be having problems getting the size of the image because it isn't guaranteed that it has been loaded by the time you're checking its dimensions.
var $img = jQuery('div#drag_container img[alt="background"]');
$img.bind('load', function(){
// do all of your stuff with the width and the height of the image in here...
var width = $(this).width();
var height = $(this).height();
});
$img.attr('src', source); /* kicks off the loading of the image, the bound function
* above will get called when it's done.
*/

Related

Getting the correct client height of an external SVG when it loads in Chrome

I'm wanting to tie the height of a button to the height of an external SVG after it's been resized by a browser.
Jsfiddle is here.
Here's the script:
function svgLoad() {
"use strict";
this.wrapper = document.getElementById('wrapper');
this.navID = document.querySelector('#slideMenu');
this.menuButton = document.querySelector('#menuButton');
this.logo = document.getElementById('logo');
this.logoWrap = document.getElementById('logoWrap');
this.navBar = document.getElementById('navBarWrap');
console.log(this.logo);
console.log(this.logo.clientHeight);
console.log(this.navBar.clientHeight);
this.loaded = function() {
this.logoHeight = Math.round(this.logo.clientHeight);
this.rect = this.logo.getBoundingClientRect();
console.log(this.rect.height);
console.log(this.logoHeight);
console.log(this.navBar.clientHeight);
// Sets height of menu button to match height of logo.
this.menuButton.style.height = this.logoHeight + 'px';
console.log(this.menuButton.style.height);
this.wrapper.style.marginTop = this.navBar.clientHeight + 'px';
}.bind(this);
this.logo.onload = this.loaded;
}
new svgLoad();
If I use window.onload everything displays fine, but I'd prefer the script to run once the SVG is ready. If I try running when the SVG object is loaded, I get different results across browsers.
Everything works fine in FF and Edge/IE using onload/addEventListener on the SVG.
In Chrome it it won't work at all, it consistently reports the SVG's size as 160px. It's showing the SVG as an anonymous function in the console, and within that the client height is calculated correctly; It just won't apply it to the script (possibly worth noting it reports the same height in the fiddle even though it doesn't load the SVG at all in Chrome).
Edit - having looked into this a bit more, Chrome seems to be changing the SVG's offsetTop property to make up the difference between the height it should dsisplay at and 160px.
I've playing with this and found an answer.
FF and IE/Edge will resize the SVG properly without either width or height specified on the object. Chrome requires that a height is specified before it sends the correct client height to the script.
For my purposes using rem/em was the best solution.

$(window).resize() and $(document).ready() calculate different values

I am trying to make text adaptive using jQuery. Here is the fiddle:
http://jsfiddle.net/bq2ca7ch/
You can see a div with some text in it. The div doesn't have a specified height, and it's height is calculated from text height and 10% paddings on top and bottom.
I want font-size to be responsive. Let's say, div's original size was 124px, and font-size was 50px, so I want to keep this ratio. That means I need to know, what percent 50 is from 124. It is about 40.32 (50/124*100). That means that I need to set font-size to value, equal to container height/100 * 40.32. Here is the code I used:
function foo(){
var container = $(".box");
var containerHeight = $(".box").innerHeight().toFixed();
var neededSize = (containerHeight/100*40.32).toFixed();
container.css("font-size", neededSize + "px");
}
$(window).resize(foo);
$(document).ready(foo);
That seems to be working, but only when I resize the page. When I reload it, there is some different value. Why does the same function gives different values on resize and onload?
What i observed that Size changes because :
1. When you just reload .the function runs only once.
2.But when you resize , the function runs twice and changes the font size because the again calculations are done based on new height.
Main thing is on resize it is calculating wrong innerheight
See this:
function foo(jQuery ){
var container = $(".box");
var containerHeight = $(".box").innerHeight(true).toFixed(2);
var neededSize = (containerHeight/100*40.32).toFixed(2);
alert(containerHeight );
container.css("font-size", neededSize + "px");
}
$(window).resize(foo);
$(document).ready(foo);
Resize method is not reliable.
Code in a resize handler should never rely on the number of times the handler is called. Depending on implementation, resize events can be sent continuously as the resizing is in progress (the typical behavior in Internet Explorer and WebKit-based browsers such as Safari and Chrome), or only once at the end of the resize operation (the typical behavior in some other browsers such as Opera).
I tried with this , it worked for me both are giving the same result for me . try this container.css("font-size":neededSize + "px");

Javascript positioning not working in Chrome or Safari

I have a script going in Javascript, the purpose of which is to make an image stay centered in the window when the window is smaller than the image. It just moves the image to the left by half the difference between the image width and the window width so that the center of the image is always the center of the screen. When the window is not smaller than the image, this left offset is set to zero. And it works perfectly, if I'm in IE or Firefox. On the webkit browsers, it doesn't ever go to zero, creating an effect akin to float:right when the window is wider than the image. Here's the code:
setTimeout(slideImageWidth, 1);
function slideImageWidth() {
var slideWidth = window.getComputedStyle(document.getElementById("slide-image")).width,
windowWidth = window.innerWidth,
slide = document.getElementById("slide-image"),
slideWidth = window.getComputedStyle(slide).width;
if (windowWidth < (slideWidth.replace("px", "") + 1) && slide.style.display !== "none") {
slide.style.left = ((((-slideWidth.replace("px", "") + windowWidth)) / 2) + "px");
}
else {
slide.style.left = 0;
setTimeout(slideImageWidth, 1);
};
I tried putting slide.style.left = 0 before the if and just letting the loop take care of it in the next millisecond, but that didn't work either. I've also tried both placements with:
slide.style.left = "0px";
slide.style.left = 0 + "px";
slide.style.left = "0" + "px";
slide.style.left = 0px;
none of which worked in Chrome or Safari, but all but the last of which worked in Firefox and IE.
When I use alert(slide.style.left) when the window is wider than the image, a positive value is returned in Chrome and Safari, unlike the 0 from Firefox and IE, which tells me that the 0 value is never being written to slide.style.left. Yet, I know that I can modify slide.style.left because it still positions itself based on the equation.
Why does this code not work with the webkit browsers, and how can I fix it?
First, the things which I think are accidental typos:
1) Your code references something called "slide1Width", which is defined nowhere.
2) Your code references something called "slide1", which is defined nowhere.
3) You don't have the right number of close brackets, and the last bracket inexplicably has a semicolon after it.
Second, the most obvious error that isn't causing your specific problem:
(slideWidth.replace("px", "") + 1)
This expression is not what you want. If slideWidth is "440px", the replace() call gives you "440", and ("440" + 1) is the string "4441". I don't think that's what you mean to do here.
Third, and finally, what I believe is the cause of the actual bug you're asking about: timing. If you open up the dev tools and manually run slideImageWidth() on a wide window after it has loaded and failed to center itself, the image will in fact jump to the center, even on Chrome. Why doesn't it do it on page load? Here:
window.getComputedStyle(slide).width
That expression returns "0px" right when the page is first loaded. If you wait until the image is done loading, you'll be able to get an actual width for it, in which case you can do the calculations you want. (Or, presumably, you could set the width yourself via styling.) It seems that IE is getting the image loaded and flowed before running the script, whereas Chrome is not.
Is there a reason you want to use setTimeout instead of a resize event? What about something like this:
window.onresize = function(event) {
setSlidePosition();
};
function setSlidePosition() {
var slideLeft = (document.getElementById("slide-image").style.left.indexOf('px') != -1 ) ? document.getElementById("slide-image").style.left : '0px';
var numLeft = slideLeft.replace('px','');
console.log(numLeft);
var element = document.getElementById("slide-image")
if(element.width > window.innerWidth) {
var newLeft = (element.width - window.innerWidth) / 2 * -1 + "px";
document.getElementById("slide-image").style.left = newLeft;
} else {
document.getElementById("slide-image").style.left = "0px";
}
};
setSlidePosition();
http://jsfiddle.net/4qomq7tb/45/
Seems to behave the same in chrome and FF at least. This doesn't specifically answer the question relating relating to your code, though :/

Window width on Chrome and Firefox error

I have the following code:
function c() {
var h = ($(window).height() - $('#maincontainer').outerHeight()) / 2;
var w = ($(window).width() - $('#maincontainer').outerWidth()) / 2;
$('#maincontainer').css('position', 'absolute');
$('#maincontainer').css('top', h);
$('#maincontainer').css('left', w);
}
$(window).resize(c);
$(window).load(c);
The resize event works properly on every browser I tried but the load always returns a width value of 8px, putting the maincontainer div on the left border of the screen.
This executes properly putting a div on the middle on the window only on IE8, failing on Chrome 22 and Firefox 16.
EDIT:
The solution that seemed to work:
$(window).ready(c);
$(window).load(c);
$(window).resize(c);
Also, the body should have width: 100%.
Instead of:
$(window).resize(c);
$(window).load(c);
do:
$(function(){
c();
$(window).resize(c);
});
What's happening is you're asking for the size of the document before anything has loaded, so you get (almost) nothing. This does it as soon as the document is 'ready' and therefore gives you a more useful value.
You may also need to make your body 100% width and height and use that size instead of the window.

Handling JQuery/CSS errors in IE

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);

Categories

Resources