Can't calculate element's size - javascript

I'm trying to calculate width and height of elements, to set precise position in CSS with jQuery, but for some reason calculation for some IDs doesn't work (alert shows 0 or nothing) while working for other IDs and classes. Here's the jQuery code:
$(document).ready(function () {
$("#img1").each(function () {
var maxtop = $('.pattern').outerHeight() - $('#mimg1').outerHeight() - 20,
maxleft = $('.pattern').outerWidth() - $('#mimg1').outerWidth() - 20,
randomtop = getRandomInt(20, maxtop),
randomleft = getRandomInt(20, maxleft),
randomzindex = getRandomInt(1, 30);
$(this).css({
"top": randomtop,
"left": randomleft,
"z-index": randomzindex
});
});
$("#img13").each(function () {
var maxtop = $('.pattern').outerHeight() - $('#mimg13').outerHeight() - 20,
maxleft = $('.pattern').outerWidth() - $('#mimg13').outerWidth() - 20,
randomtop = getRandomInt(20, maxtop),
randomleft = getRandomInt(20, maxleft),
randomzindex = getRandomInt(1, 30);
alert ($('#mimg13').outerHeight());
$(this).css({
"top": randomtop,
"left": randomleft,
"z-index": randomzindex
});
});
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
});
CSS:
html {width:100vw; height:100vh;}
body {margin:0; width:100vw; height:100vh; overflow:hidden;}
.pattern {width:100%; height:100%; margin:0; padding:0;}
.drag {overflow: visible; padding-bottom: 0px; cursor: move; position: absolute;}
.mood-img {position:absolute; display:none; margin:0; padding:0;}
HTML:
<body class="pattern-2">
<div class="pattern"></div>
<div id="img1" class="drag mood-img">
<img class="shadow moodimg1" src="mood/brick-mood-1.png">
<span class="mood-name shadow">
<nobr>A. Brickwork I</nobr>
</span>
</div>
<div id="img13" class="drag mood-img">
<img id="moodimg13" class="shadow moodimg" src="mood/brick-graphic-4.png">
<span class="mood-name shadow">
<nobr>6. Untitled</nobr><br>
<small>digital</small>
</span>
</div>
</body>
I have tried lot of different options but none of them worked and the problem is always (as it seems) is that JS doesn't calculate elements' sizes, so positions are also calculated wrong.
And also may be there's some more simple way to make all these calculation, cause I have 13 elements with different IDs (from img1 to img13 and from mimg1 to mimg13. May be I could use JS to get IDs by itself, with no need for me to write all IDs into JS?
IDEA
I have a page with a few div elements, one of them is visible, others are set to display:none. When particular span element is clicked, JS sets certain hidden div visible, changing its CSS to display:block. The div I have this problem with at first was an invisible container for several other divs with images and text elements and I wanted to position these contained elements against the container div (which had width and height set to 0 and margin top and left set to 50%) with margin-top and margin-left. Then I set the container to have 100% width and height and tried to position container's content with top and left. Then I removed the container and set its former inner elements to have position:absolute and tried to still position it with top and left properties calculated and set with jQuery. Actually those elements are images with some pop-up text, which should be randomly placed all over the page (overflow:hidden), and have z-index set randomly as well. I've spent three days trying to find the solution, but got no result — either it's not working at all (elements are placed all on top of one another in the same position (top left corner) either calculations are done wrong and some (or all) divs are positioned out of the page which creates scroll or hiding images when overflow is hidden. Hope I'm explaining it fine, so anyone could be able to understand what have I wanted to do.

You're calculating dimensions on page load - $(document).ready(... but unfortunately it doesn't mean the images are ready at this point. It's a common issue.
Since you already have your images wrapped with .each function, simply replace it with the load event handler
$("#img1").on('load', function () {
...
});

http://jsbin.com/iLIWOfa/2/edit
If the CSS of a parent element of a image is display: none, the image is not loaded and there is no width or height.
Just set opacity: 0 instead.

Related

How to dynamically get the length of a div using JQuery and JavaScript?

I am developing a web application using AngularJS. I find myself in a situation where I have a bar (with the css I created a line) that must dynamically lengthen and shorten.
I know that JQuery scripts are sufficient to do this. For example, if my css is like this:
.my_line{
display:block;
width:2px;
background: #FFAD0D;
height: 200px; /*This is the part that needs to dynamically change*/
}
I could in the controller resize the line (of my_line class) simply with:
$(".my_line").css("height", someExpression*100 + 'px');
The thing is, I would like to dynamically resize the line based on the size of another div element (Or, in general, any HTML element of my choice).
I don't know how to get (at run-time) the size of a certain page element in terms of height.
Only in this way I would be able to create a line that dynamically lengthens or shortens as the size of a div (or some other element) changes!
How do you do this? So I will avoid writing hard-coded the measures but I want make sure that they vary as the dimensions of other elements on the page vary
I hope this is helping:
$(".my_line").css("height", $("#referenceElement").height()*5 + 'px');
.my_line{
display:inline-block;
width:2px;
background: #FFAD0D;
}
#referenceElement {
display:inline-block;
background: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="my_line"></div>
<div id="referenceElement">Hi, I'm 5 time smaller than the orange line!</div>
Here I am using the setInterval to track the div's height (you can do width as well) and storing it in a previousHeight variable and comparing it every interval
Then according to the comparison, it will determine if the height of the div has changed. If it has then it will change the height of the other div according to the height of the first div
You can create multiple variables and track multiple elements in the same setInterval
$(document).ready(function(){
var previousHeight = parseInt($("#my-div").css("height"));
setInterval(function(){ checkHeight(); }, 100);
function checkHeight() {
// Check height of elements here
var currentHeight = parseInt($("#my-div").css("height"));
if(currentHeight != previousHeight) {
previousHeight = currentHeight;
$("#dynamic-div").css("height", parseInt(currentHeight) + "px");
}
}
$("#button").click(function() {
$("#my-div").css("height", parseInt(previousHeight) + 5 + "px");
})
})
#my-div{
background: #000000;
height: 20px;
width: 20px;
}
#dynamic-div{
background: teal;
height: 20px;
width: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="my-div">
</div>
<button id="button">Increase div height</button>
<div id="dynamic-div">
</div>

Having an image fill a container after transform(90deg)

I would like to have an image rotate and fill the container after it's been loaded. The issue I'm having is the height is automatically set when loaded and then not resetting after rotation. Here is a JSFiddle of the issue:
$('.load').on("click", function () {
var image = $('.image');
image.attr("src", "https://s-media-cache-ak0.pinimg.com/736x/f5/a0/62/f5a0626a80fe6026c0ac65cdc2d8ede2.jpg");
image.addClass('rotate-image');
});
.image {
max-width: 100%;
max-height: 100%;
}
.rotate-image {
transform: rotate(90deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="img-container" style="background:black; height:100px; width: 200px; text-align:center">
<img class="image" src="" />
</div>
<br />
<button class="load">Load</button>
This requires the max-width and max-height styles to be removed, though.
To fit the image, it has to be made larger so that it width (height, when rotated) becomes as big as the container's height. However, it's rotated only visually and the browser doesn't care about that because transform doesn't change the flow of the website. For it, there is an "unrotated" picture whose height is now bigger than its container. Visually rotating the image doesn't change anything. For that purpose, the image needs to be pulled up with a number of pixels equal to how much its bigger than the parent. Those pixels are divided by two because the image overflows at the bottom only.
Play with the fiddle to see what I mean.
$('.load').on("click", function() {
var image = $('.image');
image.attr("src", "https://s-media-cache-ak0.pinimg.com/736x/f5/a0/62/f5a0626a80fe6026c0ac65cdc2d8ede2.jpg");
image.addClass('rotate-image');
var parentHeight = image.parent().height();
image.css("width", parentHeight + "px");
image.css("position", "relative");
image.css("bottom", ((image.height() - parentHeight) / 2) + "px");
});
.rotate-image {
transform: rotate(90deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="img-container" style="background:black; height:100px; width: 200px; text-align:center">
<img class="image" src="" />
</div>
<br />
<button class="load">Load</button>
Edit: Beware, if you load the image from an external source by setting its src and immediately rotate it, image.height() might return 0 and the image might be displaced. Then, if you click again, its height is now correct and it gets placed right.
I'm not absolutely sure, but I think that's because when you load the image, the browser needs to download it first, meaning that you don't yet know what its dimensions are.
To see that in action, paste some image URLs from Google in the fiddle I provided.
You need to do this by javascript or jquery. Your goal is:
.Rotated_Img ...
width = 100 % of parent height
height = 100 % of parent width
And i do not think css has any think for this, until the parent width and height have related to view port vw and vh.
jquery:
$('.Rotated_Img').each(function(){
$(this).css('width', $(this).parent().height() + 'px');
$(this).css('height', $(this).parent().width() + 'px');
});

Automatic scrolling to keep child element in the center

I have a parent div called lyricpadding, and inside I have a lot of <h4>'s with a unique ID. Anyways, what I need to do us, by using preferably Jquery or Javascript or CSS, is to keep the <h4> marked with the class of highlighted in the middle of the parent container, but I don't want it to stretch over the whole thing, I just want the text to be centered by an automatic scroll until it gets to the bottom. So the div with the class highlighted will always be visible, preferably in the center.
Here is a jQuery example. It uses position absolute and then adjusts according to the scroll position and window size. See this fiddle.
HTML:
<div class='lyricpadding'>
<h4 class='highlighted'>Highlighted</h4>
<h4>Other</h4>
<h4>Other</h4>
<h4>Other</h4>
<h4>Other</h4>
</div>
CSS:
.lyricpadding
{
height:1000px;
width:100%;
background-color:lightblue;
}
.highlighted
{
display:inline-block;
position:absolute;
}
jQuery:
function positionMiddle()
{
var $highlighted = $('.highlighted');
$highlighted.css({
left: ($(window).width() - $highlighted.outerWidth())/2,
top: $(window).scrollTop() + ($(window).height() - $highlighted.outerHeight())/2
});
}
$(window).resize(function(){
positionMiddle();
});
$(window).scroll(function(){
positionMiddle();
});
// To initially run the function:
positionMiddle();

How to flow text from DIV to DIV?

I have two DIVs with absolute position on two sides of a HTML page such as (EXAMPLE)
<div class="left">
</div>
<div class="right">
</div>
with CSS
.left{
position:absolute;
left:10px;
top:10px;
width:100px;
height:100px;
background:red;
}
.right{
position:absolute;
right:10px;
top:10px;
width:100px;
height:100px;
background:blue;
}
Is there a way to add text to the left DIV and flow excess text to the right one? I am not stuck to this two DIV, and I'm just looking for a solution to flow excess text to another position.
NOTE: I hope to find a pure CSS solution, though, it seems to be improbable; then, I am looking for a pure javascript solution (not using JS libraries).
CSS Regions (still a 'draft', but) is aiming to fix this problem:
The CSS regions module allows content to flow across multiple areas
called regions. The regions are not necessarily contiguous in the
document order. The CSS regions module provides an advanced content
flow mechanism, which can be combined with positioning schemes as
defined by other CSS modules such as the Multi-Column Module [CSS3COL]
or the Grid Layout Module [CSS3-GRID-LAYOUT] to position the regions
where content flows.
More info and tutorials at https://www.adobe.com/devnet/archive/html5/articles/css3-regions.html
Here is one for fixed-width approach. The gap between two columns will equal to width of main div.
Fiddle
<div class="container">
<div class="sides">The big text here.<div>
<div class="main"></div>
</div>
For variable width you need JS or jQuery.
Update:
I have used jQuery for this purpose as I have found pure JS difficult to find solution of this.
function setGap() {
var width = $(".main").width();
$(".sides").css({
"-moz-column-gap": width + "px",
"-webkit-column-gap": width + "px",
"column-gap": width + "px"
});
}
$(window).resize(setGap);
setGap();
Fiddle
Update 1:
function setGap() {
var width = document.getElementsByClassName("main")[0].offsetWidth;
var elem = document.getElementsByClassName("sides")[0];
var style = elem.getAttribute("style");
if (typeof style != "null") {
style =
"-moz-column-gap:" + width + "px; -webkit-column-gap:" + width + "px; column-gap:" + width + "px";
elem.setAttribute("style", style);
}
else {
style +=
"-moz-column-gap:" + width + "px; -webkit-column-gap:" + width + "px; column-gap:" + width + "px";
elem.setAttribute("style", style);
}
}
window.onresize = setGap;
setGap();
Fiddle
so far (2012) It's not possible using CSS, CSS3 (with 2 separate elements)
but using JS You can clone the content and use scrollTop on the right element :
LIVE DEMO
var d = document,
$left = d.getElementById('left'),
$right = d.getElementById('right'),
leftH = $left.offsetHeight;
$right.innerHTML = $left.innerHTML +'<p style="height:'+ leftH +'px;" />';
$right.scrollTop = leftH;
As you can see I'm appending also an empty paragraph, to fix the right element need to scrollTop some amount of px
Note: add overflow:hidden; to your ID elements #left and #right

Resize based on page/screen height

My page is divided into left and right divs, the right div has a border left partitioning the two. if the height of the right box is bigger then left, it works fine. However if the left box height is more, then the border is only halfway.
How can i resize the height of the right box based on the height of entire screen so that the border runs all the way to the end.
You can provide height to your right div like, place a id ( like rightDiv ) there if not (in jQuery).
$('#rightDiv').height($(window).height());
if you want to height of your entire document use:
$('#rightDiv').height($(document).height());
$(window).height() will retrun available browser window height.
$(document).height() will retrun document height.
or you can make a comparison:
var doc = $(document);
var win = $(window);
var maxHeight = doc.height() > win.height() ? doc.height() : win.height() ;
$('#rightDiv').height(maxHeight);
You have min-height, for animate height you can try:
$('#rightDiv').animate( { height : maxHeight}, <duration>);
<duration> is optional, you can provide here 'slow', 'fast', miliseconds
Another solution would be this pure CSS one: http://jsfiddle.net/zgMv5/
You put around the left and the right div another <div> and use it as CSS table row. Then the 2 containing <div> will be the same height.
<div id="outer">
<div id="left">This is some text.</div>
<div id="right">This is some text.</div>
</div>
The corresponding CSS would look like this:
div#outer {
display:table-row; }
div#outer > div {
display:table-cell; }
div#left {
border-right:1px solid red; }
I am not sure about the compatibility with old browsers...

Categories