PDA

View Full Version : javascript not recognizing my CSS settings



gib65
03-15-2012, 10:24 PM
I have a div whose CSS I'm setting as follows:



div.services_menu
{
display: none;
position: absolute;
top: 215px;
left: 240px;
overflow: hidden;
}


I also have a initPage function that gets called on pageload:



function initPage()
{
var menu = document.getElementById("services_menu");
var menuItems = menu.getElementsByTagName("div");

alert("top = " + menu.style.top);
}


The above CSS applies to menu. The alert box tells me:

top =

So menu.style.top is not set to anything even though I explicitely set it in my CSS. Why is this?

Note: I've verified that menu.style.top is still blank even well after the page loads, just to be sure that it's not an issue with CSS being read/processed after the initPage script is read/processed.

ajfmrf
03-16-2012, 12:18 AM
please post a link to the problem page.This will help people that want to help you.

keyboard
03-16-2012, 01:01 AM
Can't see anything wrong with that code.
If you can't post a link, please post the full code of the page so we can see if something else is interfering.

jscheuer1
03-16-2012, 05:05 AM
There's a lot wrong with the code.


document.getElementById('whatever').style.top

Is always an empty value unless the element's top style property was previously set inline, either hard coded or via javascript. To get other style settings such as those from the stylesheet(s), you need the computed style (most browsers) or the current style (IE less than 9 and IE 9 or greater when in quirks mode).

And, your style selector:



div.services_menu

is setting the style for any div element(s) with with a class of services_menu, not an id of services_menu. So even if you could get the style from the stylesheet in the way you are doing, it's not set for an element with that id. It set for any elements with that class.

For something straightforward like top, it's fairly easy to get it once you have the right element:


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
function initPage()
{
var menu = document.getElementById("services_menu");
var menuItems = menu.getElementsByTagName("div");

alert("top = " +
(window.getComputedStyle?
document.defaultView.getComputedStyle(menu, null).getPropertyValue('top') :
menu.currentStyle['top'])
);
}
onload = initPage;
</script>
<style type="text/css">
div#services_menu
{
display: none;
position: absolute;
top: 215px;
left: 240px;
overflow: hidden;
}
</style>
</head>
<body>
<div id="services_menu"></div>
</body>
</html>

But for other style properties there can be considerations that complicate the situation. For more info, see:

http://www.dynamicdrive.com/forums/blog.php?b=41



Some other later thoughts . . .

I was just looking back over this and it occurred to me that there's another way of looking at this issue. You could 'ask' for the element's offsetTop. Once again you have to have the correct element in that defining the element's class and then querying about it via id still won't work with this or any method. That said, you can do:


<script type="text/javascript">
function initPage()
{
var menu = document.getElementById("services_menu");
var menuItems = menu.getElementsByTagName("div");

alert("top = " + menu.offsetTop);
}
onload = initPage;
</script>

But what this tells you isn't the style, rather where the browser has positioned the element visa vis it's offsetParent in some browsers or the body in others. If the element is absolutely positioned though and it's immediate parent is the body, it's a good cross browser way to get the distance from the top. And if it's not positioned absolutely and a direct descendant of the body, things can be done to determine a) it's distance from the top of the page, or b) from the top of its offsetParent. But the code for these has to be written to take account of the differences in browsers. And the offsetTop for any element that's display: none; as is this one is 0. You can overcome that by using visibility: hidden; instead.

Further, if one is using jQuery things get much easier. The computed/current style is (for id="services_menu"):


$('#services_menu').css('top')

And to get the offset from the top of the page (this and the others below still require the element not to be display: none;):


$('#services_menu').offset().top

from the top of its offsetParent:


$('#services_menu').position().top

For any of these, if one wants them for the class="services_menu", the following may be used to retrieve the element:


$('.services_menu')

Here however, if there are more than one as there can be with class, only the first one's style/position is returned.

gib65
03-16-2012, 06:41 PM
There's a lot wrong with the code.


document.getElementById('whatever').style.top

Is always an empty value unless the element's top style property was previously set inline, either hard coded or via javascript. To get other style settings such as those from the stylesheet(s), you need the computed style (most browsers) or the current style (IE less than 9 and IE 9 or greater when in quirks mode).

That's wonderful!

However, this only seems to work in Opera and IE (they recognize currentStyle). In Firefox, Chrome, and Safari, neither currentStyle nor computedStyle are recognized.



And, your style selector:



is setting the style for any div element(s) with with a class of services_menu, not an id of services_menu. So even if you could get the style from the stylesheet in the way you are doing, it's not set for an element with that id. It set for any elements with that class.

"services_menu" is the name of both the class and the id of the div.

jscheuer1
03-16-2012, 09:48 PM
Works here in Firefox (alerts top = 215px):


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
function initPage()
{
var menu = document.getElementById("services_menu");
var menuItems = menu.getElementsByTagName("div");

alert("top = " +
(window.getComputedStyle?
document.defaultView.getComputedStyle(menu, null).getPropertyValue('top') :
menu.currentStyle['top'])
);
}
onload = initPage;
</script>
<style type="text/css">
div.services_menu
{
display: none;
position: absolute;
top: 215px;
left: 240px;
overflow: hidden;
}
</style>
</head>
<body>
<div class="services_menu" id="services_menu"></div>
</body>
</html>

Do you perhaps have more than one div with an id of services_menu? That could throw it off.

Are you writing this menu, or is it one you got somewhere else that you're trying to tweak?

And I have to ask, why do you need this information? There are tons of menu scripts that work just fine without needing to know the computed or current style of anything. If you've just set it in the stylesheet, you must know what it is. If it's the sort of thing that can vary depending upon the particular use the menu is being put to on a particular page, have it be set in the menu's configuration.

If you want more help, please include a link to the page on your site that contains the problematic code so we can check it out.

gib65
03-20-2012, 02:16 PM
Thanks again John,

I think the problem was that I wasn't referencing getComputedStyle or currentStyle like you were here:



document.defaultView.getComputedStyle(menu, null).getPropertyValue('top') :
menu.currentStyle['top'])


I didn't call the function document.defaultView.getComputedStyle(*,*), and I didn't index currentStyle in the style of an array like you did.

I haven't tested this though.

jscheuer1
03-20-2012, 03:46 PM
I have read (or think that I have) somewhere that the defaultView.getComputedStyle() function can be skipped sometimes. I tried it here with this and it didn't work without it. I also tried it without the null argument, and that worked, but I don't see any reason to skip it. And you're right, currentStyle requires array brackets, or as it's technically know in this situation - object notation. If it were an array, instead of ['top'], we would have a number like [3]. But it's not an array, it's a collection or object. In other languages this is known as an associative array though, so you're not far off.

vwphillips
03-26-2012, 02:39 PM
it is the display: none;
interfering with

document.defaultView.getComputedStyle(obj,null).getPropertyValue('top');

jscheuer1
03-26-2012, 04:30 PM
it is the display: none;
interfering with

document.defaultView.getComputedStyle(obj,null).getPropertyValue('top');

I don't think so. If you check my working example from my previous post:

http://www.dynamicdrive.com/forums/showpost.php?p=271482&postcount=6

You will see that it has display: none;

If we were looking for the offsetTop property of the element though, you would be correct, display none would interfere with getting that.