Can't get left position with global stylesheet in JavaScript - javascript

I need to get the upper left position of an image in JavaScript. I define the location of an image in a global style sheet:
<style type="text/css">
img.movable { position:relative; top:0px; left:375px; }
</style>
When I define the image using the global style
<img id="image11" class="movable" src="testimage.jpg" onclick="jump()" />
The style.left attribute is empty:
<script type="text/javascript">
function jump() {
xpos = document.getElementById("image11").style.left;
alert( "style.left="+xpos );
xpos = document.getElementById("image11").offsetLeft;
alert( "offsetLeft="+xpos );
}
</script>
But when I define the image using an inline style:
<img id="image11" style="position:relative; top:0px; left:375px;" src="logo.jpg" onclick="jump()" />
style.left contains a value.
This behaviour is the same for IE8 and Firefox. Any ideas why that is?
Cheers,
Martin.

el.style is actually a map of all the css properties applied using the style attribute. To get styles defined in stylesheets or default browser styles, you need to use computed style. Quirksmode, as usual, is a first stop.

The DOM element that represents the IMG tag you specified has its own style property, and its values will override any given by globals. Unfortunately in this case, the property of the element you specified will indeed be empty, as the values do not cascade down to the JavaScript object level.
You will need to get the position from either the offsetLeft property or the CSS rule itself.

.style properties only relate to inline css. Styles specified in a stylesheet will thus not be present in the .style list. If you want to get the position of an element on the page (as opposed to viewport) something like this should work:
function getNodePosition(node) {
var top = left = 0;
while (node) {
if (node.tagName) {
top = top + node.offsetTop;
left = left + node.offsetLeft;
node = node.offsetParent;
} else {
node = node.parentNode;
}
}
return [top, left];
}
Adapted from Quirksmode. OffsetTop and OffsetLeft are wrt to the parent, so this iterates up the tree to get the total offsets, and hence page position. If you want to know the position wrt the viewport, you can adjust the values returned here by the scroll distance.

Get Left Element of a given HTMLElement
function getHTMLElementLeft(HTMLElement, left)
{
if (left == undefined)
{
var left = 0;
}
if (HTMLElement.nodeType == 1)
{
left += HTMLElement.offsetLeft;
if (HTMLElement.offsetParent)
{
left = getHTMLElementLeft(HTMLElement.offsetParent, left);
}
}
return left;
}

Related

Move an <img> when button pressed

Here is my code that I am currently using for the function, I have made imgs move in the past using key codes but what I used a function to move it for me, the code looks like it should work there is probably just a silly error:
<!DOCTYPE html>
<html>
<head>
<title>Return To Alnerwick</title>
<style>
body
{
background-image: url("https://s-media-cache-ak0.pinimg.com/736x/e8/d6/fc/e8d6fc15671a05eeaf592f85c6dbb2db.jpg");
background-size: 1500px 1000px;
background-repeat: no-repeat;
}
img
{
position:absolute;
TOP:650px;
LEFT:750px;
width:100px;
height:100px
}
</style>
<script>
function move() {
var element = document.getElementById("char");
element.style.left = parseInt(element.style.left) - 90 + 'px';
}
</script>
</head>
<body>
<img id="char"src="/New Piskel (5).gif">
<button onclick="move();">move</button>
</body>
</html>
It's because you are using a stylesheet. When using a stylesheet, you have get the computed styles:
function move() {
var element = document.getElementById("char");
var style = window.getComputedStyle(element);
console.log("Current value: " + style.left);
element.style.left = (parseInt(style.left) - 90) + 'px';
}
See a working fiddle: https://jsfiddle.net/vgb7tc03/1/
Also getComputedStyle reference: https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
In your move function, you are referencing element.style.left. This is the element's inline style property. That inline style property is not defined in your markup at all.
You are defining the LEFT property in your css (not inline). What you will need to do is either reference the LEFT css property from your function, or set the left property inline in your element instead of in CSS.
Your problem is that element.style.left won't return its position. There are a couple of solutions:
1) You know that your image is already 750px from the left so you can just go
var img_left=750;
at the beginning of your script tag and then go
img_left=img_left-90;
element.style.left = img_left + "px";
in your function.
2) if you want to get the position of the element, you would go
element.getBoundingClientRect().left;
instead of element.style.left so the whole line would be
element.style.left=(element.getBoundingClientRect().left-90)+"px";

combine conditions if browser window is X height and element is scrolled to X point within

I've started with the below which works perfect, but I only need this to run and execute when my nav element .mainNav is scrolled to within a certain point within browser height.
#media screen and (max-height: 660px) {
.mainNav {
margin-top:-130px !important;
}
}
So detecting vertical browser height WITH scroll position within then chain .css with jQuery to. (margin-top:-100px)
Basically how to combine above parameter with below parameter. Below detects scroll position...
var $document = $(document),
$element = $('#some-element'),
className = 'hasScrolled';
$document.scroll(function() {
if ($document.scrollTop() >= 50) {
// user scrolled 50 pixels or more;
// do stuff
$element.addClass(className);
} else {
$element.removeClass(className);
}
});
You could do this by using the clientBoundingRect of the element. For example (untested, just theory);
var mainNav = document.getElementsByClassName('.mainNav')[0];
window.onscroll(function(e){
if(mainNav.clientBoundingRect().top <= 100 && window.height <= 660){
mainNav.style.marginTop = "-130px";
// or you could add a class here, as per the suggestion above, such as
// mainNav.setAttribute('class', 'mainNav locked');
}else{
mainNav.style.marginTop = "0";
// and remove it here
// mainNav.setAttribute('class', 'mainNav');
}
})
There is no visbility pseudo-selector in CSS, so you're looking at implementing this using JS handing of the visibilitychange event on your element, and then toggling the right (sequence of) class(es) through the element.classList interface, probably with transition rules in the CSS itself for the properties you want to be dynamic.

Is Javascript an Effective Method of Creating Fluid Layouts?

I'd like opinions on whether or not Javascript is a still a viable and relatively effective method of producing fluid website layouts. I know that it is possible to create fluid layouts with Javascript, but relative to other methods (e.g. CSS3/HTML5) how does it stand up in terms of performance and complexity? The function below represents what I mean. In the function, javascript is being used to find the dimensions of various elements and place other elements accordingly. To see it working, follow this link.
function onPageResize() {
//center the header
var headerWidth = document.getElementById('header').offsetWidth; //find the width of the div 'header'
var insideHeaderWidth = (document.getElementsByClassName('header')[0].offsetWidth + document.getElementsByClassName('header')[1].offsetWidth + document.getElementById('logoHeader').offsetWidth); //find the combined width of all elements located within the parent element 'header'
document.getElementsByClassName('header')[0].style.marginLeft = ((headerWidth - insideHeaderWidth) / 2) + "px"; //set the margin-left of the first element inside of the 'header' div
/////////////////////////////////////////////////////////////////
//justify alignment of textboxes
var subtitleWidth = document.getElementsByClassName('subtitle'); //assign the properties of all elements in the class 'subtitle' to a new array 'subtitleWidth'
var inputForm = document.getElementsByClassName('inputForm'); //assign the properties of all elements in the class 'inputForm' to a new array 'inputForm'
for (i = 0; i < inputForm.length; i++) { //for every element in the array 'inputForm' set the margin-left to dynamically place the input forms relative to eachother
inputForm[i].style.marginLeft = (subtitleWidth[4].offsetWidth - subtitleWidth[i].offsetWidth) + "px";
}
/////////////////////////////////////////////////////////////////
//place footer on absolute bottom of page
if (window.innerHeight >= 910) { //when the page is larger than '910px' execute the following
var totalHeight = 0; //initialize a new variable 'totalHeight' which will eventually be used to calulate the total height of all elements in the window
var bodyBlockHeight = document.getElementsByClassName('bodyBlock'); //assign the properties of all elements in the class 'bodyBlock' to a new array 'bodyBlockHeight'
for (i = 0; i < bodyBlockHeight.length; i++) { //for every instance of bodyBlockHeight in the array, add the height of that element into the 'totalHeight'
totalHeight += bodyBlockHeight[i].offsetHeight;
}
totalHeight += document.getElementById('header').offsetHeight; //finally, to add the height of the only element that has yet to be quantified, include the height of the element 'header' into the 'totalHeight'
/*Set the margin-top of the element 'footer' to the result of subtracting the combined heights of all elements in the window from the height of the window.
This will cause the footer to always be at the absolute bottom of the page, despite whether or not content actually exists there. */
document.getElementById('footer').style.marginTop = (window.innerHeight - totalHeight) - document.getElementById('footer').offsetHeight + "px";
} else {
//if the page height is larger than 910px (approx the height of all elements combined), then simply place the footer 20px below the last element in the body
document.getElementById('footer').style.marginTop = "20px"
}
/////////////////////////////////////////////////////////////////
}
Again, the result of the above function can be viewed at this link.
Thank you to any and all who offer their opinions!
You should be using CSS rather than JavaScript because that is what CSS is designed to do. If you want a fluid layout play around with using percentage widths, floats and media queries.

how can I determine that an element height is fixed

I need to know whether an HTML element will expand as the content is added to it. The height of the element can be preset in a number of ways - with the inline style height or max-height, by setting relative height when the parent element has its height set, via a css class, etc.
All I need to know whether the height of the element will increase as I add children. I hoped to use the JQuery css method, but it computes the actual value and does not tell me whether it will change as new children are added.
There are several ways to set a height of the element. Here is a test function you can use in order to determine if specified element has fixed height:
HTML
<span id="notAffected"></span>
<div id="hasCSSHeight"/>
<div id="hasInlineHeight" style="height:50px"/>
<div id="hasAttribureHeight" height="10px" />
<div id="hasNoHeight"/>
CSS
#notAffected,
#hasCSSHeight {
height: 100px;
}
JavaScript
function hasHeight(el) {
var i,
l,
rules = window.getMatchedCSSRules(el),
display = window.getComputedStyle(el).getPropertyValue('display');
// Inline displayed elements are not affected by height definition
if(display === 'inline') {
return false;
}
// CSS
if(rules) {
for(i=0,l=rules.length;i<l;i++) {
if(rules[i].style.getPropertyValue('height')) {
return true;
}
}
}
// Inline style
if(el.style.height) {
return true;
}
// Attribute
if(el.getAttribute('height')) {
return true;
}
return false;
}
Example see here http://jsbin.com/usojec/3/edit

Can a DIV's CSS attribute be changed dynamically by javascript just by knowing it's class?

I have this div:
<div class="galleria-info" style="">
<div class="galleria-info-text">
<div class="galleria-info-title" style="">#test</div>
</div>
</div>
And I have this CSS for it:
.galleria-info {
width: 100%;
top: 290px;
left: 330px;
z-index: 10;
position: absolute;
}
What I would like to do is somehow thru javascript change the left attribute of the galleria.info div dynamically so that based on the length of the text for #test i can position the div far enough left to make room for it on screen.
I write different information where the word #test is at in the HTML dynamically and it doesn't have an ID only class.
Any clues or help will be mega-appreciated!
document.getElementsByClassName('galleria-info')[0].style.left = '300px'; // or whatever you want
You have two questions; I have two answers.
Getting by Classname
getElementById() gets the element by its id, getElementsByTagName()[] gets the element by tag name, and to get it by class name, use:
document.querySelectorAll("galleria-info")
Setting the Position
Sorry I used getElementById and getElementsByTagName instead of querySelectorAll.
right Attribute
Wouldn't a right attribute be more appropriate? You could get the width of the body (or container) and subtract however much you want from that instead.
var body_width = document.getElementsByTagName('body')[0].style.width;
var body_width = parseFloat(body_width);
document.getElementById('galleria-info').style.right = (body_width - 600) + "px";
Fixed-Width Font
But, if you are using a fixed-width font, then you can get the length of the string, multiply by the width of each character, and then set style.left to that minus the max distance it can reach (i.e. 300px.)
var str_length = document.getElementById('galleria-info').innerHTML.length;
var str_length = str_length * 10; // Or whatever the fixed width is
document.getElementById('galleria-info-text').style.left = (300 - str_length) + "px";
Wrapper
This doesn't use JavaScript, which, in my opinion, is a good thing because users can disable JavaScript. You can have a wrapper div around the original div that has the following CSS:
#galleria-info-wrapper {
width:300px;
text-align:right;
}
#galleria-info {
text-align:left;
}

Categories

Resources