Incorrect jQuery element width calculation - javascript

Having a simple html code
<div id="header">
<div id="headerBox">
<div id="headerText">
</div>
</div>
</div>
with css styles
div#header {
display: block;
overflow: hidden;
margin: 0;
padding: 0;
width: 100%;
}
div#headerBox {
padding: 1em;
text-align: center;
white-space: nowrap;
border-bottom: 10px double gray;
}
div#headerText {
background: red;
display: inline-block;
}
and jQuery (2.x edge)
function resize(win) {
var size;
var w = $('#headerBox').width();
$('#headerText').html('');
$('#headerBox').css('font-size', 1 + 'px');
$('#headerText').html(
"width of <span style=\"font-size:2em;\">headerBox</span> element is " + w + "px");
while ($('#headerText').width() <= w) {
size = parseInt($('#headerBox').css('font-size').replace(/\D+$/, ''), 10);
$('#headerBox').css('font-size', (size + 1) + 'px');
}
$('#headerBox').css('font-size', size + 'px');
}
$(window).resize(function(e){
resize(this)
});
resize(window);
all together accessible via this fiddle,
I experience incorrect jQuery element width calculation. When you access the above fiddle, you see that headerText element is too wide. There should be same right padding as is on left side, text should be centered. Once you resize the Result window (in the fiddle), text is adjusted as supposed to.
Question is WHY there is incorrect calculation on the very first time?
It seems that var w = $('#headerBox').width(); is incorrect calculated. WHY?

Found the problem:
Due to padding: 1em; for headerBox, width of this element changes with change of font-size.
So in while loop I need to work with up-to-date information, not the one I stored at the beginning.
Therefore
var w = $('#headerBox').width();
...
while ($('#headerText').width() <= w) {
...
}
needs to be changed to
while ($('#headerText').width() <= $('#headerBox').width()) {
...
}

JQuery .width doesn't include the padding of #headerbox. Use .outerWidth to get correct width.
var w = $('#headerBox').outerWidth();

Related

Measure the content area of an element

How can you get the dimensions of the content area of a DOM element?
Strangely couldn't find a question/answer to this. Many questions about measuring DOM elements as a whole, but none about the content area itself.
Example:
div {
width: 100px;
height: 200px;
padding: 10px;
border: 5px;
margin: 15px;
box-sizing: border-box;
}
Now somethings get you various parts of the box model, but nothing seems to give you the content:
const elem = document.querySelector('div');
elem.offsetWidth; // content + padding + border
elem.clientWidth; // content + padding
window.getComputedStyle(elem); // Returns an object with width padding and border as strings like "15px".
window.getBoundingClientRect(); // Gives width and height of total box-model excluding margin if sizing is border-box.
You'll need to subtract the computed paddings from the client width and height:
const elem = document.getElementById('elem');
const computedStyles = window.getComputedStyle(elem)
const extraWidthOffset = +computedStyles.getPropertyValue("padding-left").slice(0, -2) + +computedStyles.getPropertyValue("padding-right").slice(0, -2)
const extraHeightOffset = +computedStyles.getPropertyValue("padding-top").slice(0, -2) + +computedStyles.getPropertyValue("padding-bottom").slice(0, -2)
const contentWidth = elem.clientWidth - extraWidthOffset
const contentHeight = elem.clientWidth - extraHeightOffset
console.log(contentWidth, contentHeight)
#elem {
width: 100px;
height: 200px;
padding: 10px;
border: 5px;
margin: 15px;
box-sizing: border-box;
}
<div id="elem">
<p>Content</p>
</div>

Exiting a for loop that creates divs when reached end of screen

I am trying to complete a little exercise that refreshes the page when the big button in the middle is clicked and the little dots change colour.
I have stopped the page from scrolling so the page is full of dots but I have noticed that the overflow property acts differently on different browsers. Then I thought of another issue, on mobile or tablets the dots will show differently again!
So I'm not sure if this is even possible but the desired result is for the loop to create dots until the screen is full and the button displaying in the middle of the screen.
Could someone please tell me if this idea is possible as I haven't been able to find any similar questions. Or if there is a better way to get my desired result. Also if you have the time could you please briefly explain why as I want to understand how it works and learn from it.
So...
This is the JavaScript
var htmlDot = "";
var red;
var green;
var blue;
var rgbColor;
function colourSelect() {
return Math.floor(Math.random() * 256 );
}
for(var i = 1; i<=100; i+=1) {
red = colourSelect();
green = colourSelect();
blue = colourSelect();
rgbColor = "rgb(" + red + "," + green + "," + blue + ")";
htmlDot += "<div style=\"background-color:"+ rgbColor + " \"></div>";
}
document.write(htmlDot);
This is the HTML
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="main.css">
</head>
<body>
<button id="refresh">Click Me!</button>
<script src="script.js"></script>
</body>
</html>
This is the CSS
body {
position: relative;
overflow: hidden;
}
#refresh {
font: 40px bold;
font-family: sans-serif;
width: 200px;
height: 200px;
display: inline-block;
border-radius: 50%;
margin: 5px;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
background-color: rgb();
}
div {
width: 50px;
height: 50px;
display: inline-block;
border-radius: 50%;
margin: 5px;
}
Thank you in advance
I think you're looking for something like this:
https://jsbin.com/racahapevi/edit?html,css,js,output
Key points:
Calculate numbers of dots that can fit horizontally
Calculate total numbers of dots
Define <html>, <body> width and height to 100% of the viewport
overflow: hidden on html, so there will not be scroll
Add onclick event the button.
Here some code:
var numDots = hdots * vdots;
while(numDots--){
red = colourSelect();
green = colourSelect();
blue = colourSelect();
rgbColor = "rgb(" + red + "," + green + "," + blue + ")";
htmlDot += "<div class='dot' style=\"background-color:"+ rgbColor + " \"></div>";
}
Instead of using 100 for the number of dots you have to figure out how many dots fit in your browser window given the dimensions of the browser window.
var w = window.innerWidth; // browser width
var h = window.innerHeight; // browser height
var size = 60; // 50px + 5px + 5px (width or height) + (left or top margin) + (right or bottom margin)
var hdots = Math.floor(w/size); // how many dots fit horizontally
var vdots = Math.floor(h/size); // how many dots fit vertically
var numDots = hdots * vdots;

How to dinamically update the child div width after insert other elements in the parent div

I have a main div (with fixed height and scroll-x and scroll-y):
<div style="position:relative;border:solid 2px #000;overflow-y:scroll;overflow-x:scroll; height:200px; width:100%;" id="pippo">
</div>
and a bunch of child div created dynamically in js and inserted in the parent div with absolute position:
<div style='z-index:3;position:absolute; top: 50px; left: "+pos+"px;border:solid 1px;'>m</div>
This divs can be created everywhere, also beyond the parent div height and width (I don't care because I get the scrollbars).
My problem is:
there are other child divs (created in js) that represent a background like a chart. The divs have a border and a width of 100%. An example of one of them:
<div style='z-index:2;border-bottom:solid 1px #ccc; color:#ccc;position:absolute;width:100%;bottom:"+yyy+"px;'>0</div>
When javascript create dynamically the divs, the background don't update his width to the new one (if the divs go beyond the parent measures).
So, if you scroll on the right, you don't see the background.
How can I do to give the right width (100%) to the background when the parent width is dynamically changed?
http://jsfiddle.net/4x2KP/157/
Thanks everybody!
I've do an work around to it, if you can add specific class to the axis divs.
You can listen to the scroll event on the #pippo and adjust the offset of the axis, as its fixed horizontally inside the #pippo. But you may have to separate the digit part and axis-line part to make the digit part movable by the scrollbar.
var t = 250;
var $axis;
var offsets;
$(document).ready(function(){
crea_bg();
setTimeout(function(){ pippo(); }, t);
});
var pos = 0;
function pippo(){
pos = pos + 30;
$("#pippo").append("<div style='z-index:3;position:absolute; top: 50px; left: "+pos+"px;border:solid 1px;'>m</div>");
setTimeout(function(){ pippo(); }, t);
}
function crea_bg(){
var yyy = 0;
$("#pippo").append("<div class='axis' style='z-index:2;border-bottom:solid 1px #ccc; color:#ccc;position:absolute;width:100%;bottom:"+yyy+"px;'>0</div>");
for (i = 25; i <= 300; i=i+25) {
$("#pippo").append("<div class='axis' style='z-index:2;border-bottom:solid 1px #ccc; color:#ccc;position:absolute;width:100%;bottom:"+(yyy+(-i))+"px;'>"+(-i)+"</div>");
$("#pippo").append("<div class='axis' style='z-index:2;border-bottom:solid 1px #ccc; color:#ccc;position:absolute;width:100%;bottom:"+(yyy+(i))+"px;'>"+i+"</div>");
}
$axis = $('.axis').css('left', 0);
}
$('#pippo').scroll(function() {
//var currentLeft = parseFloat($axis.css('left'));
//console.log($axis.css('left'), currentLeft, $axis.position().left);
//$axis.css('left', currentLeft - $axis.position().left);
$axis.css('left', '-=' + $axis.position().left);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<div style="position:relative;border:solid 2px #000;overflow-y:scroll;overflow-x:scroll; height:200px; width:100%;" id="pippo">
</div>
I'm not sure if this is what you are asking for, but this code creates those background lines at the same time that the letters are written.
You can adjust it easily changing the "width" var.
var t = 250;
$(document).ready(function(){
crea_bg();
setTimeout(function(){ pippo(); }, t);
});
var pos = 0;
function pippo(){
pos = pos + 30;
crea_bg();
$("#pippo").append("<div style='z-index:3;position:absolute; top: 50px;"
+" left: "+pos+"px;border:solid 1px;'>m</div>");
setTimeout(function(){ pippo(); }, t);
}
function crea_bg(){
var yyy = 0;
var width = pos + 30;
$("#pippo").append("<div style='z-index:2;border-bottom:solid 1px #ccc;"
+"color:#ccc;position:absolute;width:"+width+"px;bottom:"+yyy+"px;'>0</div>");
for (i = 25; i <= 300; i=i+25) {
$("#pippo").append("<div style='z-index:2;border-bottom:solid 1px #ccc;"
+" color:#ccc;position:absolute;width:"+width+"px;bottom:"+(yyy+(-i))+"px;'>"+(-i)+"</div>");
$("#pippo").append("<div style='z-index:2;border-bottom:solid 1px #ccc;"
+ "color:#ccc;position:absolute;width:"+width+"px;bottom:"+(yyy+(i))+"px;'>"+i+"</div>");
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<div style="position:relative;border:solid 2px #000;overflow-y:scroll;overflow-x:scroll; height:200px; width:100%;" id="pippo">
</div>
Avoiding the typical document flow
If you must avoid the typical document flow, you'll need to insert another container between <div id="pippo"> and its child elements, then manually update the new container's width/height as needed.
Staying within the typical document flow
If you don't need to work around the normal document flow and are just searching for any possible way to make a parent expand, use a combination of display: inline-block and white-space: nowrap:
$(document).ready(function() {
setInterval(function() {
$('#pippo').append('<div class="childDiv">m</div>')
}, 250);
});
#pippo {
border: solid 2px #000;
height: 200px;
width: 100%;
overflow-y: scroll;
overflow-x: scroll;
white-space: nowrap;
}
.childDiv {
display: inline-block;
border: solid 1px #000;
margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<div id="pippo"></div>

Dynamically creating triangle with max-width/fit inside div

I have a web page that accepts three inputs.
I am dynamically creating a triangle from these three inputs (by setting border-widths).
I want the triangle to fit inside the div on the page. For example, if the inputs were 500, 500, 300 I want to reduce these to fit inside the div on the page while retaining the aspect ratio of the inputs.
HTML:
<div id="triangle"></div>
CSS:
#triangle {
max-width: 200px;
width: 0;
height: 0;
margin: 0 auto;
}
jQuery:
$("#triangle").css({
"border-left": length1 + "px solid transparent",
"border-right": length2 + "px solid transparent",
"border-bottom": length3 + "px solid #2383ea"
});
Here is one way of doing it.
Start with the following HTML, two nested block elements:
<div id="triangle"><div class="inner"></div></div>
and some basic CSS:
body {
margin: 0;
}
#triangle {
border: 1px dotted gray;
max-width: 400px;
margin: 0 auto;
}
#triangle .inner {
width: 0;
height: 0;
}
and now use the following jQuery/JavaScript:
var length1 = 1500;
var length2 = 1500;
var length3 = 1500;
var maxWidth = parseInt($("#triangle").css("max-width"));
var baseWidth = Math.min($("#triangle").width(),maxWidth);
var scale = baseWidth/(length1+length2);
$("#triangle .inner").css({
"border-left": length1*scale + "px solid red",
"border-right": length2*scale + "px solid green",
"border-bottom": length3*scale+ "px solid #2383ea"
});
You can see a demo at: http://jsfiddle.net/audetwebdesign/WVcvj/
Programming Notes
You will enter the length1, length2 and length3 from a form or something.
By default, #triangle will take on the width of the parent container, so use that width if it is smaller than the maximum width (you can get the value using the .css function). The parseInt() function will strip out the px label that comes with the value.
The base of the triangle has a width of length1+length2, so calculate the ratio of the available width to the specified width.
You then normalize the three border widths and you are done!

HTML5 and Javascript - a function appears to be working only once

guys, I am playing arround with HTML5 and javascript. The current thing which I am making is the following: there is a purple block on the screen and when you click a button it is moved 100 pixels to the right. This works so far, however, the function works only on the first time it is ran. I can't find my bug. I am posting the entire source code (javascript, html and css)
<!doctype html>
<head>
<style>
#stage{
position: relative;
width : 800px;
height : 600px;
background: #c0c0c0;
border: 1px dashed black;
}
.coil{
width: 64px;
height: 64px;
background: #800080;
position: absolute;
top: 200px;
left: 50px;
}
</style>
</head>
<body>
<div id="stage">
<div class="coil"></div>
<button id="button1">move!</button>
</body>
<script>
var coil = document.querySelector(".coil");
var button = document.querySelector("#button1");
button.addEventListener("click", clickHandler2, false);
//why is it working correctly just once
function clickHandler2()
{
coil.style.left += 100 + "px";
}
</script>
As nycynik mentioned, you are being a bit careless with the string additions.
Try this:
function clickHandler2()
{
var before = parseInt(coil.style.left);
before = isNaN(before) ? 0 : before;
coil.style.left = before + 100 + "px";
}
When you do your add like that, its not actually adding to the value, its only making a new string; add a console.log on the button and you will see.
console.log(coil.style.left += 100 + "px");
the output is "100px100px"
one alternative solution:
var coilPos = 100;
//why is it working correctly just once
function clickHandler2()
{
coilPos += 100;
coil.style.left = coilPos + "px";
console.log(coil.style.left += 100 + "px");
}
You must use a closure. A variable in the closure context must keep the left value. Then when applying the value to the property you use
var actualLeft += 100;
coil.style.left= actualLeft +"px";

Categories

Resources