I'm in such a situation where i need to wait till the image gets loaded once the image gets loaded i need to gets its computed height so that i can set the yellow color selector accordingly.
Question: based on computed height of image i'm setting yellow color selector. it works with setTimeout() randomly but i don't want such approach.
let images = ['https://via.placeholder.com/150','https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com','https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com'];
let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>`
document.getElementById('content').innerHTML = `<div class="box">${image}</div>`;
//actual code
let height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height');
let imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width');
console.log('height',height,'width',imageWidth);
wrapImage = `<div style="width:calc(${imageWidth} + 10px);height:calc(${height} + 10px);position:absolute;left:0;top:0;border:1px solid yellow;"></div>`;
document.querySelector('.box').insertAdjacentHTML('beforeend',wrapImage);
.box{
width:100%;
height:auto;
border:1px solid red;
position:relative;
}
<div id="content">
</div>
with setTimeout it works but i don't want such approach,i want callback
or some event
once element is ready
let images = ['https://via.placeholder.com/150','https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com','https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com'];
let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>`
document.getElementById('content').innerHTML = `<div class="box">${image}</div>`;
//actual code
setTimeout(() => {
let height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height');
let imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width');
console.log('height',height,'width',imageWidth);
wrapImage = `<div class="select" style="width:calc(${imageWidth} + 10px);height:${height};position:absolute;left:0;top:0;border:1px solid yellow;"></div>`;
document.querySelector('.box').insertAdjacentHTML('beforeend',wrapImage);
document.querySelector('.select').height = document.querySelector('.select').height + 10;
console.log('after computed height and added 10px',window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height'));
},700);
.box{
width:100%;
height:auto;
border:1px solid red;
position:relative;
}
<div id="content">
</div>
Please help me thanks in advance !!!
The Window. getComputedStyle() method returns an object containing the values of all CSS properties of an element, after applying active stylesheets and resolving any basic computation those values may contain.
In JavaScript, you can use the clientHeight property, which returns an element's height, including its vertical padding. Basically, it returns the actual space used by the displayed content. For example, the following code returns 120, which is equal to the original height plus the vertical padding.
To set or copy JavaScript computed style from one element to another, we can loop through each style and call the setProperty method to set the styles on the target element. to add a div and a section element. We define the copyNode function that takes the sourceNode and targetNode .
The values returned by getComputedStyle are resolved values. These are usually the same as CSS 2.1’s computed values, but for some older properties like width, height, or padding, they are instead the same as used values.
Definition and Usage The getComputedStyle () method gets all the actual (computed) CSS property and values of the specified element. The computed style is the style actually used in displaying the element, after "stylings" from multiple sources have been applied.
getComputedStyle is a rather specialized API that should only be necessary in special situations. For more on the issue of getComputedStyle and shorthand properties, see this question.
For instance, it is probably actually doing the equivalent of rgb (255, 165, 0) none repeat scroll 0% 0% / auto padding-box border-box. getComputedStyle will not return the value of shorthand properties, except in Chrome as you've discovered.
The image hasn't finished loading when you retrieved the height and width. To solve this, you'll need to wait for the images to load first, then get their height and width.
Listen for the window load
event, which will fire when all resources (including images) have loaded completely:
let images = ['https://via.placeholder.com/150', 'https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com', 'https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com'];
let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>`
document.getElementById('content').innerHTML = `<div class="box">${image}</div>`;
//actual code
window.addEventListener('load', function() {
let height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height');
let imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width');
console.log('height', height, 'width', imageWidth);
wrapImage = `<div class="select" style="width:calc(${imageWidth} + 10px);height:${height};position:absolute;left:0;top:0;border:1px solid yellow;"></div>`;
document.querySelector('.box').insertAdjacentHTML('beforeend', wrapImage);
document.querySelector('.select').height = document.querySelector('.select').height + 10;
console.log('after computed height and added 10px', window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height'));
});
.box {
width: 100%;
height: auto;
border: 1px solid red;
position: relative;
}
<div id="content">
</div>
If you want more flexibility then you can use Resize Observer. With this when you change src
attribute of image tag you'll able to change selection size.
const imageObserver = new ResizeObserver(function(entries) {
for (let entry of entries) {
var img = entry.target;
let height = img.height + 10;
let width = img.width + 10;
console.log('Added 10px. height:', height, ' width:', width);
wrapImage = `<div class="select" style="width:${width}px;height:${height}px;position:absolute;left:0;top:0;border:1px solid #f7d205;"></div>`;
document.querySelector('.box').insertAdjacentHTML('beforeend', wrapImage);
}
});
function init() {
document.getElementById('content').innerHTML = `<div id="box" class="box"></div>`;
var box = document.getElementById('box');
var img = document.createElement("img");
img.src = "https://via.placeholder.com/" + Math.floor(Math.random() * 50 + 80).toString() + "/0a0a0a/ffffff";
box.appendChild(img);
imageObserver.observe(img);
}
<!DOCTYPE html>
<html lang="en">
<style>
#box {
width: 100%;
border: 1px dotted red;
position: relative;
}
</style>
<body onload="init()">
<div id="content"></div>
</body>
</html>
Note: Using same ResizeObserver you can observe multiple images:
var images = document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
imageObserver.observe(images[i]);
}
Edit: As requested, demonstrating observing img resize from parent div element. Here the image is wrapped in div #box. On resize img dispatches a custom event and parent handles it.
function handleChildResize(event) {
console.log('parent: got it! handling it.. ')
var img = event.data;
let height = img.offsetHeight + 10;
let width = img.offsetWidth + 10;
console.log('Added 10px. height:', height, ' width:', width);
wrapImage = `<div class="select" style="width:${width}px;height:${height}px;position:absolute;left:0;top:0;border:2px solid #f7d205;"></div>`;
if (document.querySelector('.box > .select')) {
document.querySelector('.box > .select').remove();
}
document.querySelector('.box').insertAdjacentHTML('beforeend', wrapImage);
event.stopPropagation();
}
const imgObserver = new ResizeObserver(function(entries) {
for (let entry of entries) {
var img = entry.target;
var event = new Event('childResized');
event.data = img;
console.log("img: i am resized. Raising an event.");
img.dispatchEvent(event);
}
});
function init() {
var box = document.getElementById('box');
box.addEventListener('load', (event) => {
console.log('The page has fully loaded');
});
var img = document.createElement("img");
img.src = "https://via.placeholder.com/" + Math.floor(Math.random() * 50 + 80).toString() + "/0a0a0a/ffffff";
box.appendChild(img);
imgObserver.observe(img);
box.addEventListener('childResized', handleChildResize, true);
}
<!DOCTYPE html>
<html>
<head>
<style>
#box {
width: 100%;
padding: 10px;
border: 1px solid red;
position: relative;
}
</style>
</head>
<body onload="init()">
<div id="content">
<div id="box" class="box"></div>
</div>
</body>
</html>
You could consider adding the 'load' event listener as a callback for image loading. Please check the example:
const image = document.getElementById('image');
const handler = () => {
alert(image.height);
};
image.addEventListener('load', handler);
<img src="https://image.shutterstock.com/z/stock-vector-sample-stamp-grunge-texture-vector-illustration-1389188336.jpg" id="image" />
I see that you want to compute the final value of the get computed style
you see. The thing is that the getComputedStyle
doesn't get updated.
So just make a function to do it!
let images = ['https://via.placeholder.com/150','https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com','https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com'];'
let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>`
document.getElementById('content').innerHTML = `<div class="box">${image}</div>`;
//actual code
setTimeout(() => {
let height;
let imageWidth;
function calculateHeightAndWidth() {
height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height');
imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width');
}
calculateHeightAndWidth()
console.log('height',height,'width',imageWidth);
wrapImage = `<div class="select" style="width:calc(${imageWidth} + 10px);height:${height};position:absolute;left:0;top:0;border:1px solid yellow;"></div>`;
document.querySelector('.box').insertAdjacentHTML('beforeend',wrapImage);
document.querySelector('.select').height = document.querySelector('.select').height + 10;
calculateHeightAndWidth()
console.log('after computed height and added 10px',window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height'));
},700);
.box{
width:100%;
height:auto;
border:1px solid red;
position:relative;
}
<div id="content">
</div>
I see that you are creating your imgNode on a fly using ternary which means you do not have it pre-created in your HTML. So for that, you can use the solution as below by creating an Image constructor.
const images = [
"https://via.placeholder.com/150",
"https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com",
"https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com"
];
const img = new Image();
img.addEventListener("load", (ev) => {
console.log(ev);
document.getElementById(
"content"
).innerHTML = `<div class="box">${ev.target}</div>`;
const height = window
.getComputedStyle(document.querySelector(".box"), null)
.getPropertyValue("height");
const imageWidth = window
.getComputedStyle(document.querySelector(".box img"), null)
.getPropertyValue("width");
console.log("height", height, "width", imageWidth);
const wrapImage = `<div style="width:calc(${imageWidth} + 10px);height:calc(${height} + 10px);position:absolute;left:0;top:0;border:1px solid yellow;"></div>`;
document.querySelector(".box").insertAdjacentHTML("beforeend", wrapImage);
});
img.src = `${images[Math.floor(Math.random() * images.length)]}`;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With