How to extend container when it has absolutely positioned elements in it? - javascript

Lets say I have
CSS:
.mainWrap { position: relative; overflow: hidden; }
.wrap-boxes { positon: relative; }
.box { position:absolute (position and height is generated by plugin isotope: http://isotope.metafizzy.co/custom-layout-modes/centered-masonry.html }
HTML:
<div class"mainWrap">
<div class="wrap-boxes">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
clearfix applied to wrap-boxes won't work as it has elements with absolute position in it.
therefore i'd need to use jQuery to calculate the height of the boxes in order to extend wrap-box. I don't know the height of these boxes as they have random height and I do not know the total number of boxes as they are constantly generated by the client. I'd need a general jQuery that solves that. If i don't extend the mainWrap the boxes will be cut off and i need to use overflow: hidden for other reasons.
Any help on this?

Something like this maybe?
$.fn.wrapHeight = function() {
return this.each(function() {
var height = 0;
$(this).children().each(function() {
height += $(this).height();
}).end().height(height);
});
};
$('.wrap-boxes').wrapHeight();

Absolutely-positioned elements are no longer part of the layout. You need to use JavaScript to measure the size and position of the child elements and set the size of the parent element accordingly.

In pure JavaScript you could use the following:
var wrapbox = document.getElementById('mainWrap').childNodes[1],
els = wrapbox.childNodes,
i,
height = 0;
for (i in els) {
if(els[i].nodeType == 1) {
height += parseInt(els[i].offsetHeight);
}
wrapbox.style.height = height + 'px';
}
http://jsfiddle.net/AJLe7/1/
Notice I changed the class="mainWrap" to id="mainWrap" to simplify the answer...

Related

Run Jquery only when an element is in the viewport

I'm trying to perform the Jquery function below when the element becomes visible in the viewport rather than on the page load. What would I need to change to allow that to happen? I'm using an external JS file to perform the Jquery, so keep that in mind.
Here's a piece of the HTML that is associated with the Jquery function -
<div class="skillbar clearfix " data-percent="70%">
<div class="skillbar-title" style="background: #FF704D;">
<span>Illustrator</span></div>
<div class="skillbar-bar" style="background: #FF704D;"></div>
<div class="skill-bar-percent">70%</div>
</div>
jQuery(document).ready(function(){
jQuery('.skillbar').each(function(){
jQuery(this).find('.skillbar-bar').animate({
width:jQuery(this).attr('data-percent')
},4000);
});
});
I once came across such problem and what I used is waypoints small library.
all you need is to include this library and do:
var waypoint = new Waypoint({
element: document.getElementById('waypoint'),
handler: function(direction) {
console.log('Element is in viewport');
}
})
Using CSS3 transitions instead of jQuery animations might be more performant and simpler. a cheap and nasty way of pushing it out of screen to demonstarate the effect.
There's a couple of things you'll need to do - firstly if you only want the animation to trigger when it's in the viewport then you'll need to check if anything is in the viewport on scroll. Then only update the bars width when it comes into view. If you want the effect to repeat every time it comes into viewport you'll need to set .skillbar-bar's width back to 0 if it's out of the viewport (just add an else statement to the viewport checking if)
I've added a 1000px margin-top and 400px margin-bottom in my example to .skillbar as a cheap and nasty way of demonstrating the effect
(function($){
$(document).ready(function(){
var $els = $('.skillbar'); // Note this must be moved to within event handler if dynamically adding elements - I've placed it for performance reasons
var $window = $(window);
$window.on('scroll', function(){
$els.each(function(){ // Iterate over all skillbars
var $this = $(this);
if($window.scrollTop() > $this.offset().top - $window.height()){ // Check if it's in viewport
$this.find('.skillbar-bar').css({'width' : $this.attr('data-percent')}); // Update the view with percentage
}
});
});
});
}(jQuery));
.skillbar{
margin-top: 1000px;
margin-bottom: 400px;
position: relative
}
.skillbar-bar{
transition: width 4s;
position: absolute;
height: 20px;
}
.skill-bar-percent{
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Scroll down 1000px :)
<div class="skillbar clearfix " data-percent="70%">
<div class="skillbar-title">
<span>Illustrator</span></div>
<div class="skillbar-bar" style="background: #FF704D; width: 20%"></div>
<div class="skill-bar-percent">70%</div>
</div>
This might work for you.
var el = $('.yourElement'),
offset = el.offset(),
scrollTop = $(window).scrollTop();
//Check for scroll position
if ((scrollTop > offset.top)) {
// Code..
}

Move overflowed elements to another div

I have a div with fixed height and another div below it with fixed height. I want elements (whole elements) that cannot fit within first div to move to another div. I don't want elements to be cut- just moved in whole and I want the order to be kept- so span2 will never be before (higher) than span1.
<div id="div1" style="height: 200px; width: 300px">
<span id="span1">Hello world<span>
<span id="span2">El 1</span>
</div>
<div id="div2" style="height:200px; width: 300px"></div>
Is this possible with just CSS? It doesn't really have to move from div1 to div2. I need just 2 containers of fixed height and moving elements between them. Can this be done with CSS columns? Or flex?
JS FIDDLE:
Try the FIDDLE.
Following code checks the DIV overflow status.
Javascript:
function IsDivOverFlow(div)
{
if (div.outerHeight() < div.prop('scrollHeight') || div.outerWidth() < div.prop('scrollWidth')) {
return true;
} else {
return false;
}
}
Using the function on button click
var Count = 0;
$('button').click(function()
{
var EditableContent = '<span contenteditable=true>'+(++Count)+' : TEST</span>';
var oldHTML = $('#div1').html();
$('#div1').append(EditableContent);
if(IsDivOverFlow($('#div1'))){
$('#div1').html(oldHTML);
$('#div2').append(EditableContent);
}
});
Hope it helps....
If you want to use css columns you can use something like this, but only using one div instead of two:
.your_class{
-webkit-column-count: 3; /* Chrome, Safari, Opera */
-moz-column-count: 3; /* Firefox */
column-count: 3;
}

How to get div's content height

My div has a styling position:absolute, and as a result, it doesn't expand if the content is higher than it's height.
Therefore, I thought that a solution would be if I find what the is the actual content's height, and assign the height to the div with the position:absolute styling.
Any idea how to do it? or maybe an idea how to make an absolute div to expand according to its content.
Thanks in advance!
Element.scrollHeight should do the job.
Here's an awful way to get the height of the container. We're basically cloning the whole div, setting the position so that it has height, checking that height, and then removing it:
$(function () {
var clone = null;
alert( clone = $('.test').clone().css('position', 'static').appendTo(".container").height());
clone.remove();
});
Here's the fiddle: http://jsfiddle.net/vPMDh/1/
It should expand even if being absolute.
check you don't have a height: xxpx
if so, change it to min-height
As you've said "it doesn't expand if the content is higher than it's height." I guess you have a fixed height set on it.. if you do need this for some reason try using min-height instead.
Have a look at this fiddle.
<div class="classname">
Some content....
<p style="clear:both">&nbsp</p>
</div>
use a clearfix hack. heres the link
and add clearfix to you div
example
in your style sheet
<style>
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
.clearfix {
display: inline-block;
}
html[xmlns] .clearfix {
display: block;
}
* html .clearfix {
height: 1%;
}
</style>
...
and in your div add clearfix the class
<div class="clearfix">
//some html tags
</div>
Thanks for contributing your question. If you use this:
$(document).ready(function(){
var x = $("#container").height();
alert(x);
//if not works then
var y = $("#container").outerHeight();
alert(y);
});
I think it is easy as clean code to find the height of any div if you do not apply the div's height too.
similar solution to #MattDiamant, but with vanilla JS and without creating a clone:
function getDivHeight(posAbsoluteDiv) {
const heightBackup = posAbsoluteDiv.style.height;
posAbsoluteDiv.style.height = 'auto';
const contentHeight = posAbsoluteDiv.getBoundingClientRect().height;
posAbsoluteDiv.style.height = heightBackup;
return contentHeight;
}

Equal Height Columns that Recalculate on Window Resize

The code I have below is supposed to find the height of the largest column (.border) and adjust the height of any other columns found within the .container div to equal it. Unfortunately, I haven't been able to get this code to work as intended so I'm hoping someone wiser than I could can help me out.
It's also worth mentioning that column height should be recalculated and columns resized respectively whenever the window has been resized.
<script type="text/javascript">
$(document).ready(function(){
//Bind the window onresize event
$(window).bind('resize', resizeWindow);
//Call resizeWindow() function immediately to intiially set elements
resizeWindow();
});
function resizeWindow(){
//Find all the container parent objects
$('.container').each(function(){
//Initialize the height variable
var maxHeight = 0;
//Cache the jQuery object for faster DOM access and performance
var $borders = $(this).find('.border');
//Find all the border child elements within this specific container
$borders.each(function(){
//Get current element's height
var thisHeight = $(this).height();
//Check if the current height is greater than the max height thus far
//If so, change max height to this height
if (thisHeight>maxHeight) maxHeight = thisHeight;
});
//Now that we have the maximum height of the elements,
//set that height for all the .border child elements inside the parent element
$borders.height(maxHeight);
});
}
</script>
<div class="container">
<a href="#" class="border">
<div class="column">
<div class="content">asdf</div>
</div>
</a>
<a href="#" class="border">
<div class="column">
<div class="content">asdf</div>
</div>
</a>
</div>
Use the jQuery equalHeights plugin:
http://www.cssnewbie.com/equalheights-jquery-plugin
$('.container .border').equalHeights(); // make all .border the same height
$(window).resize(function(){$('.container .border').equalHeights();});
See: http://jsfiddle.net/rZU35/
This is not exactly a solution to your JavaScript problem. This is a CSS solution, that doesn't need any JavaScript. Using those styles with your markup, both columns will always have the same height:
div.container {
display: table;
width: 100px;
}
div.container > a {
display: table-cell;
border: 1px solid red;
}
Demo
http://jsfiddle.net/wmbcr/
This will work upon resize too, if no fixed width is set.
I think you should provide an height to your DIV not the <a>.
Try this fiddle:
http://jsfiddle.net/ddFtX/1/

CSS: dynamic width div

I'm coding a slider and I have problems with the stylying of the container.
I have 3 div:
A div that sets the width and height of the slider
A container div with all the content divs (and the scroll for the slider)
Many divthat show different contents each
What I want to do is apply a negative margin on the second div to slide the content.
LIVE example: http://jsbin.com/efuyix/7/edit
JS:
function animate(element) {
var start = new Date();
var id = setInterval(function() {
var timePassed = new Date() - start;
var progress = timePassed / 600;
if (progress > 1) progress = 1;
element.style.marginLeft = -50 * Math.pow(progress, 5)+"px";
if (progress == 1) {
clearInterval(id);
}
}, 10);
}
CSS
.example_path {
overflow: hidden;
width: 50px;
height: 50px;
}
.example_block {
min-width: 100px;
height: 50px;
float:left;
}
.example_in_block {
width: 50px;
height: 50px;
float:left;
}
HTML
<div class="example_path">
<div class="example_block" onclick="animate(this)">
<div class="example_in_block" style="background-color:blue;"></div>
<div class="example_in_block" style="background-color:pink;"></div>
<div style="clear:both;"></div>
</div>
</div>
The problem:
The width of .example_block has to be exactly the same or more than (amount of content divs .example_block * 50 [width size of content div] ) to work.
For example, if I set the width size of the .example_block to 90, the pink div will be below the blue div and not beside it.
I want the container div to be dynamic so I don't have to set the specific width size.
How can I do this?
Simply remove the float:left in the .example_block.
See http://jsbin.com/efuyix/9/edit
Not with negative margins. You can probably set padding on one of the outer DIVs.
Also, min-width isn't going to be backwards compatible with older versions of IE.
Check this example: http://jsfiddle.net/5xBYN/6/
If the initial positioning is good, you can then use negative values on your container DIV (the third DIV) for top, left, right or bottom to achieve sliding.
Update:
Maybe this is closer to what you want. http://jsfiddle.net/5xBYN/7/
I'm still not sure what you are trying to do. Maybe edit the fiddle I posted and update your question with what I'm getting wrong if there is anything.

Categories

Resources