Javascript - object.offsetTop and .offsetLeft gives 0 - javascript

I'm trying to get the position of an element by using Javascript. I have used clientTop, offsetHeight, window.getComputedStyle(box1).top and a few things in between but all I get when I console log it is 0. The element is placed almost in the middle of the page so it should be all but 0 in the result.
HTML:
<body>
<h1>Box placement</h1>
<div id='box1' class='box center green size200'>
</div>
</body>
JS:
let box1 = document.querySelector('#box1');
let browserHeight = window.innerHeight;
let browserWidth = window.innerWidth;
let boxHeight = box1.clientTop;
let boxWidth = box1.offsetLeft;
function printInfo() { //Result
console.log(browserHeight); //1185
console.log(browserWidth); //1266
console.log(boxHeight); //0
console.log(boxWidth); //0
console.log(window.getComputedStyle(box1).top); //auto
console.log(box1.offsetLeft); //0
}
printInfo();
Any ideas to where I might have gone wrong? Here is a fiddle with the CSS as well: http://jsfiddle.net/1f23v9nj/1/

That behaviour is caused by the less.js library. If you don't really need its features, then don't include it -- problem solved.
If you do need it -- for reasons not apparent from the code in your question -- then wait for the less.pageLoadFinished promise to resolve, as follows:
less.pageLoadFinished.then(function () {
'use strict';
let box1 = document.querySelector('#box1');
// ... etc
});
See updated fiddle

Related

How to select individual elements with javascript here?

See here: https://siteweb.synergieetvitalite.com/monportfolio/
I would like the smartphone and laptop to come close togheter as the user moves his mouse. The code i am using :
HTML:
<div class="scene">
<div data-speed="51" class="layer layer-middle"></div>
<div data-speed="81" class="layer layer-top"></div>
</div>
JS:
<script> document.addEventListener('mousemove', parallax);
function parallax(e) {
e.preventDefault();
this.querySelectorAll('.layer-middle').forEach((layer) => {
let speed = layer.getAttribute('data-speed');
layer.style.transform = `translateX(${e.clientX * speed / 1000}px)`;
})
}
</script>
I tried to modify this so that .layer-top moves to the right, but then the layer-middle stopped moving alltogheter, probablement because of SelectorAll or forEach. I don't really know javascript so I wasn't able to simply make the function work for each element individually.
thanks for your help!
I think you can remove the foreach and select each element separately like below. So this way you will move the laptop to right and the phone to left or vice versa.
I've changed your code a little. Try it and let me know if its what which you are looking for.
<script> document.addEventListener('mousemove', parallax);
function parallax(e) {
e.preventDefault();
laptop = document.querySelector('.layer-middle');
let speed = laptop.getAttribute('data-speed');
laptop.style.transform = `translateX(${e.clientX * speed / 1000}px)`;
phone = document.querySelector('.layer-top');
phone.style.transform = `translateX(${-1*e.clientX * speed / 1000}px)`;
}
</script>

Change CSS of element within elements and classes

I am trying to set the height of an image to be 50% of the width, but the image scales with the page. The current CSS I am targeting looks like this:
.img-quiz p span img { width: 100%; }
Here's what I've tried in js, but isn't working:
var imgQuiz = document.getElementByClassName('img-quiz').getElementsByTagName('img');
var elementStyle = window.getComputedStyle(imgQuiz);
var pixHeight = elementStyle.getPropertyValue('height');
imgQuiz.style.height = pixHeight * .5;
Also, I'm new to javascript, do I need to wrap this in a function (i.e. window.onload = function())?
Check out this JS Fiddle for help...
https://jsfiddle.net/Lm60v949/6/
var image = document.getElementsByClassName('img-quiz')[0].getElementsByTagName('img')[0];
// console.log( image ); // test to make sure the image was captured
/*
var image = document.getElementById('imgQuiz'); // much cleaner way to select
*/
image.height = image.width / 2;
// console.log( image.height, image.width ); // check the results
.img-quiz p span img { width: 100%; }
<div class="img-quiz">
<p>
<span>
<img id="imgQuiz" src="https://image.shutterstock.com/z/stock-photo--week-old-cocker-spaniel-puppy-630877553.jpg">
</span>
</p>
</div>
A couple of hiccups here:
.getElementsByClassName and .getElementsByTagName both return a HTMLCollection -- to use these, you will have to select the index of the collection that matches your image ([0], [1], [2], ... )
If you can, an ID on the targeted image would be ideal. Just easier to write and read code.
var image = document.getElementsByClassName('img-quiz')[0].getElementsByTagName('img')[0];
If you want brownie points, you can do something like:
image.onload = function(){
image.height = image.width / 2;
};
(assuming you have the image already captured and saved to the variable "image")
This is a nice sanity check to make sure the image exists (and has a height & a width) before trying to manipulate it.
You may be overthinking the problem a bit -- once an image is loaded, you can just look up the width and set the height property of the image.
There's a couple of extras that you can do here:
Check to make sure that the image width is not 0 (zero) ... this is a nice double-check that the image has loaded
if( image.width > 0 ){ ... }
Round the number down to a whole number (there's nothing wrong with .5 size increments, just nice to work with whole numbers)
image.height = Math.floor( image.width/2 );
Summary of your question:
My understanding of your situation is, your trying to make an image have the height of 50% of the webpage but its not doing so, you have looked into different methods including JavaScript but struggling, also you asked about onload methods.
If so this is my proposed solution
Solution
In this example we are using pure JavaScript (no library or framework)
The html has pre-set the src for the image, if you want to dynamically set the src then use the following imgEl.src = "path/to/file.jpg";
The method or trigger used is a DOMContentLoaded, which ensures all the HTML elements of the page have loaded before it begins trying to read and manipulate the DOM Elements.
The function we trigger is called funStart (Short for function Start), I always encourage people to use abreviations that define the object type so that it is easier to read such as fun for function, str for string, bl for boolean, obj for object, int for integer so on.
inside funStart we are assigning an DOM element as imgEl which is an image obj and we are saying set the width to be innerWidth which is the document width
We are then saying set the height to be 50% of the document height (innerHeight), by dividing the value into 2.
function funStart(){
var imgEl = document.getElementById("targetImg");
imgEl.height = innerHeight / 2;
imgEl.width = innerWidth;
}
document.addEventListener("DOMContentLoaded", funStart, false);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<img id="targetImg" src="https://static.pexels.com/photos/257360/pexels-photo-257360.jpeg" alt="background image" title="background">
</body>
</html>
Here's a simple example (you can learn more in here):
var image = document.getElementsByClassName('img-quiz')[0];
image.height = image.width / 2;
<img src="https://dummyimage.com/100x100">
<img class="img-quiz" src="https://dummyimage.com/100x100">
The HTML file would be like this:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<img src="https://dummyimage.com/100x100">
<img class="img-quiz" src="https://dummyimage.com/100x100">
<script>
// you could also move the script tag to the head and add an event handler to the event load (window.onload = function() {...};
var image = document.getElementsByClassName('img-quiz')[0];
image.height = image.width / 2;
</script>
</body>
</html>

JavaScript filter hueRotate does not work

I am trying to change an image's (#bgImage) hue when hovering over a button (profIcon) in JavaScript. This type of button is created with JS, and there are 9 of them.
Here is the code that creates a DOM image element, sets it's source, position, size and transition. Finally it appends it to it's container. The image appears correctly, where it should be.
I am using quickID in place of document.getElementById, and it is working without error.
var bgImage = document.createElement("img");
bgImage.id = "bgImage";
bgImage.src = "./resources/images/backgrounds/profession/selector.jpg";
bgImage.style.position = "absolute";
bgImage.style.left = "0px";
bgImage.style.top = "0px";
bgImage.style.width = "100%";
bgImage.style.height = "100%";
bgImage.style.zIndex = 1;
bgImage.style.webkitTransition = "all 0.5s ease";
quickID("centerdiv").appendChild(bgImage);
Here is the code that runs when I hover over an image:
profIcon.onmouseover = function () {
var thisNr = this.id.substr(8); //last char of the profIcon ID; number between 0 and 8
var newHue = profTomb[thisNr][3]; //this contains the value and only that.
console.log(newHue); //always returns the correct value
quickID(this.id).style.webkitFilter = "grayscale(0%)"; //this part works, too
quickID("bgImage").style.webkitFilter = "hueRotate(" + newHue + "deg)";
}
My problem: for some reason, the filter does not apply. newHue is either a positive (75), or a negative (-23) value and it's inserted correctly, as it appears in the console log. I only use webkit vendor prefix as I use Google Chrome.
I waited up to 1 minute with my mouse cursor over the image, thinking my system needs time to process the transformation, but nothing happened.
Does anyone knows what is the problem?
The correct string to use is hue-rotate, not hueRotate. The following should work:
quickID("bgImage").style.webkitFilter = "hue-rotate(" + newHue + "deg)";

About image rotation once element with specific id is clicked

Logo and elements from ul once clicked rotates image. By default image is already rotated by certain degrees, then on each click image rotates to necessary value.
So far I was using the following:
$("#objRotates").css('opacity','.2');
var value = 0;
var prev_value = 0;
$( "li" ).click(function() {
var text=$(this).text();
if(text==="text1"){value=0;}
if(text==="text2"){value=33;}
if(text==="text3"){value=66;}
if(prev_value != value){
$("#objRotates").animate({opacity:'1'});
$("#objRotates").rotate({
animateTo:value,
easing: $.easing.easeInOutExpo,
center: ["25px", "150px"],
callback: function(){$("#objRotates").animate({opacity:'0.2'});}
});
}
prev_value = value;
});
Above code is the one that was used before, where images start position was 0 and its animation was triggered from link text.
Using jqueryRotate.js examples(here)
How do I change the code, so that images start position is certain degrees and animation starts if element with specific ID is clicked?
Give at least clue..Cause for now, looking at my old code, I am lost. Thanks in advance.
SIMPLIFIED FIDDLE
Ok, so I've created a couple of samples for you to check out. The first one is very basic and I've simplified the code a little to make it easier to understand. This one just uses completely static values and a static elementId for the event, which I'm pretty sure answers your question based on your response to my comment yesterday. http://jsfiddle.net/x9ja7/594/
$("#elementId").click(function () {
var startingAngle = 45;
var endingAngle = 90;
var elementToRotate = "img";
$(elementToRotate).rotate({
angle: startingAngle,
animateTo: endingAngle
});
});
But I wanted to give another example as well that would be dynamic and repeatable for multiple elements. With the code above, you would have to copy/paste the same code over and over again if you want to perform this animation by clicking different elements. Here's an alternative. In this example, you set all of your parameters in the data attributes in the clickable element, then the function is completely repeatable, you only have to write it once. Less code = everyone happy! Here's the example: http://jsfiddle.net/x9ja7/595/
//#region Default starting angles
$("#image1").rotate({ angle: 90 });
$("#image2").rotate({ angle: 20 });
//#endregion
$(".rotateAction").click(function () {
//#region Optional parameter - used in the optional callback function
var $self = $(this);
//#endregion
var startingAngle = Number($(this).attr("data-startingangle"));
var endingAngle = Number($(this).attr("data-endingangle"));
var elementToRotate = $(this).attr("data-elementtorotate");
//#region If the current angle is the ending angle, reverse the animation - this can be removed if you want, I thought it may be cool to show some of the things you can do with this.
var currentAngle = $(elementToRotate).getRotateAngle();
if ( currentAngle[0] === endingAngle) {
startingAngle = Number($(this).attr("data-endingangle"));
endingAngle = Number($(this).attr("data-startingangle"));
}
//#endregion
$(elementToRotate).rotate({
angle: startingAngle,
animateTo: endingAngle
//#region This is optional - uncommenting this code would make the animation single-use only
//, callback: function () { $self.off().removeClass("clickable"); }
//#endregion
});
});
Hope this helps. If you need any other assistance, please let me know.

Box2d.js impulses/forces and initial position

I was "playing" with kripken's box2d when I had a pair of issues. I chose this fork because it seems to be the fastest and the most used.
API defines position on bodyDef but you 'must' give it on body.
Forces, impulses, ... keep attached to the body giving a unexpected constant velocity.
Does anybody get these behaviours before? Does anybody have any hints?
This comes from a complex app but I have simplified for demo:
<html>
<head>
<script src="http://kripken.github.io/box2d.js/box2d.js"></script>
</head>
<body>
<script>
// gravity 0 for top view scene
var world = new Box2D.b2World( new Box2D.b2Vec2(0, 0), true);
var bodyDef = new Box2D.b2BodyDef();
bodyDef.set_type( Box2D.b2_dynamicBody );
bodyDef.set_position(40,40);
var body = world.CreateBody(bodyDef);
// ISSUE 1
// without these two lines real position is 0,0
body.GetPosition().set_x(40);
body.GetPosition().set_y(40);
var dynamicBox = new Box2D.b2PolygonShape();
dynamicBox.SetAsBox(5.0, 5.0);
var fixtureDef = new Box2D.b2FixtureDef();
fixtureDef.set_shape(dynamicBox);
fixtureDef.set_density(1);
fixtureDef.set_friction( 0.8);
fixtureDef.set_restitution( 0.5);
body.CreateFixture(fixtureDef);
//ISSUE 2
// Never ending movements
//body.ApplyLinearImpulse(new Box2D.b2Vec2(5,5),body.GetWorldCenter());
body.ApplyForce(new Box2D.b2Vec2(50,50),body.GetWorldCenter());
function update() {
world.Step(1/30, 10, 10);
world.ClearForces();
console.log(body.GetPosition().get_x()+","+body.GetPosition().get_x());
}
setInterval(update, 1000/60);
</script>
</body>
</html>
For issue 1, set_position should expect a b2Vec2 parameter. Try this:
bodyDef.set_position( new b2Vec2( 40, 40 ) );
I got more issues so finally I switched to box2dweb. Older but more tested and more stable.

Categories

Resources