jQuery: css margin based on the amount of elements in container? - javascript

I'm trying to create a simple collage creator using jquery.
what I need to do is to have a margin of 1% between each element (collage).
But at the same time I need the collages to have 0 margin from their container.
I hope that makes sense.
I've created this FIDDLE so you know what I mean.
when you run the code, just click on the button 4 times and you should see the collages being created inside the container perfectly fine BUT there is a margin between their container and its children elements which is not wanted.
Is there any way to sort this issue out?
This is my code:
$('#colBtn').live('click', function(){
$('.lable').show();
$('#reset').show();
$('#fileField').show();
$('#sbs').show();
var width = $('#width').val();
var height = $('#height').val();
$('#main').append('<div class="droppable" style="width:'+width+';height:'+height+';overflow: hidden; position:relative;float:left; margin:1%;"></div>');
$('#layout').text($('#main').html());
return false;
});

What you're looking for is a negative margin.
put another div in your #main div and give it a negative margin.
margin: 0 -1%
This will make it as if it had no margin since you have
overflow: hidden
set to your main container.
Something like this: Fiddle
Hope this gets you closer to your goal ;)

By the above given figure. The main issue seems like figuring out which is the first item and which is the last item of a row. having dynamic number of items in a row.
I just figure out the first item and last item you can use it to adjust margin.
function fix(){
var $item = $('.droppable');
var parentWidth = $item.parent().width();
var itemWidth = $item.outerWidth(true);
var itemInLine = Math.floor(parentWidth/itemWidth);
var totalItems = $item.length;
var rows = totalItems / itemInLine;
var lastItem = 0;
var firstItem = 1;
for(var i = 1; i< rows + 1; i++){
lastItem = i * itemInLine;
$('.droppable:nth-child('+ lastItem +')').css({'margin-top':'0px','margin-right':'0px'});
firstItem = (i * itemInLine) - itemInLine + 1;
$('.droppable:nth-child('+ firstItem +')').css({'margin-top':'0px'});
}
}

Related

Calculate height left for paragraph / subtract elements in JavaScript

I want to crop text and found ways to do that.
The problem is they work on height and i don't know the height because the heading above can have 1, 2, 3... lines.
So i need to get the height of the outer element and subtract the heading height.
var list = document.body.getElementsByClassName("cropText");
for (var i = 0; i < list.length; i++) {
cropTextToFit(list[i]);
}
function cropTextToFit (o) {
var containerHeight = o.clientHeight;
var head = document.getElementsByTagName("H2");
var headHeight = head.clientHeight;
console.log(containerHeight);
console.log(headHeight);
}
cropText is the article tag where the heading and the paragraph are in.
headHeight shows "undefined" and "containerHeight" is wrong...
Firstly you need to find the <H2> tag within the cropText element (o in your function), document.getElementsByTagName("H2") will return an array of all the <H2> s in the document
Presuming there is only one h2 inside the cropText element you need something like
var head = o.querySelector('h2');
Also, to work out the total h2 height you will need offsetHeight + the height of the top and bottom margins
getElementsByTagName returns more objects and param clientHeight not avaliable. Use head[i]

Getting Coordinates of an element on page scroll

I am having this problem where i have a set of 6 UL's having a common class x.Each of them consist of a specific section of the page.Now i have 6 menus that are related to each of the section.What i have to do is highlight the menu when its related section is in users view.
For this i thought that may be jQuery position(); or offset(); could have helped but they give the top and left of the element.I also tried using jQuery viewport plugin but apparently view port is big it can show more than one UL at a time hence i cant apply element specific logic here.I am not familliar to this but does anything changes of an element on scrolling?If yes then how to access it?
Please share your views.
Regards
Himanshu Sharma.
Is very easy to do it using jQuery and a dummy fixed HTML block that helps you find the current position of the viewport.
$(window).on("scroll load",function(){
var once = true;
$(".title").each(function(ele, index){
if($(this).offset().top > $("#viewport_helper").offset().top && once){
var index = $(this).index(".title");
$(".current").removeClass('current')
$("#menu li").eq(index).addClass('current')
once = false;
}
});
})
Check out a working example: http://jsfiddle.net/6c8Az/1/
You could also do something similar with the jQuery plugin, together with the :first selector:
$(window).on("scroll load",function(){
$(".title:in-viewport:first").each(function(){
var index = $(this).index(".title");
$(".current").removeClass('current')
$("#menu li").eq(index).addClass('current')
});
})
You can get the viewport's width and height via $(document).width() and $(document).height()
You can get how many pixels user scrolls via $(document).scrollTop() and $(document).scrollLeft
Combining 1 and 2, you can calculate where the viewport rectangle is
You can get the rectangle of an element using $(element).offset(), $(element).width() and $(element).height()
So the only thing left to you is to determine whether the viewport's rectangle contains (or interacts) the elements's rectangle
So the whole code may look like:
/**
* Check wether outer contains inner
* You can change this logic to matches what you need
*/
function rectContains(outer, inner) {
return outer.top <= inner.top &&
outer.bottom >= inner.bottom &&
outer.left <= inner.left &&
outer.right >= inner.right;
}
/**
* Use this function to find the menu related to <ul> element
*/
function findRelatedMenu(element) {
return $('#menu-' + element.attr('id'));
}
function whenScroll() {
var doc = $(document);
var elem = $(element);
var viewportRect = {
top: doc.scrollTop(),
left: doc.scrollLeft(),
width: doc.width(),
height: doc.height()
};
viewportRect.bottom = viewportRect.top + viewportRect.height;
viewportRect.right = viewportRect.left + viewportRect.width;
var elements = $('ul.your-class');
for (var i = 0; i < elements.length; i++) {
var elem = $(elements[i]);
var elementRect = {
top: elem.offset().top,
left: elem.offset().left,
width: elem.width(),
height: elem.height()
};
elementRect.bottom = elementRect.top + elementRect.height;
elementRect.right = elementRect.left + elementRect.width;
if (rectContains(viewportRect, elementRect)) {
findRelatedMenu(elem).addClass('highlight');
}
}
}
$(window).on('scroll', whenScroll);
Let's see if i understood well. You have a page long enough to scroll, and there is an element that when it appears in the viewport, you wanna do something with it. So the only event that's is triggered for sure on the time the element gets in the viewport is the 'scroll'. So if the element is on the page and the scroll is on the viewport, what you need to do is bind an action to the scroll event to check if the element is in the view each time the event is trigger. Pretty much like this:
$(window).scroll(function() {
check_element_position();
});
Now, in order for you to know if the element is in the viewport, you need 3 things. The offset top of that element, the size of the viewport and the scroll top of the window. Should pretty much look like this:
function check_element_position() {
var win = $(window);
var window_height = win.height();
var element = $(your_element);
var elem_offset_top = element.offset().top;
var elem_height = element.height();
var win_scroll = win.scrollTop();
var pseudo_offset = (elem_offset_top - win_scroll);
if (pseudo_offset < window_height && pseudo_offset >= 0) {
// element in view
}
else {
// elem not in view
}
}
Here, (elem_offset_top - win_scroll) represent the element position if there was no scroll. Like this, you just have to check if the element offset top is higher then the window viewport to see if it's in view or not.
Finally, you could be more precise on you calculations by adding the element height (variable already in there) because the code i just did will fire the event even if the element is visible by only 1 pixels.
Note: I just did that in five minutes so you might have to fix some of this, but this gives you a pretty darn good idea of what's going on ;)
Feel free to comment and ask questions

function equalHeight , set a minimum Height to apply?

I have tried everything, but without javascript I cannot achieve the bad layout my designer gave to me!!
As you can see I have the div #backgr-box that has to be absolute positioned with z-index to be properly behind the #contenuto (which holds the page content!!)
Now to solve the extensibilty trouble of #backgr-box I have the below code that works if the content of #contenuto is longer than the sidebar #barra-laterale , but it is not ok in opposite case, see page: http://demo.liquidfactory.it/secondopolo/per-informarti
So how can I tell javascript to apply that calculation only over a minimum height of div sidebar #barra-laterale ??
Need help.. please!
function equalHeight(group) {
tallest = 0;
group.each(function() {
thisHeight = $(this).height();
if(thisHeight > tallest) {
tallest = thisHeight = $("#contenuto").height() - 380;
}
});
group.height(tallest);
}
$(document).ready(function() {
equalHeight($(".column"));
});
The problem is likely with this line:
tallest = thisHeight = $("#contenuto").height() - 380;
Currently it is setting both the variables tallest and thisHeight to the height of the content region minus 380 pixels. Change it to:
tallest = thisHeight;
And it will resize all the columns to the height of the tallest one.
Edit: It looks like your right-hand column actually consists of multiple columns with a class of .barra-laterale in this case you may want to take another tack altogether:
// calculate the total height of the content are and sidebar
var contentHeight = $("#contenuto").height();
var sidebarHeight = 0;
$(".barra-laterale").each(function() { sidebarHeight += $(this).height(); })
if (sidebarHeight > contentHeight) {
$("#contenuto").height(sidebarHeight);
} else {
// extend the last sidebar column to cover the difference between the
// height of the content and the sum of the sidebar heights
var lastSideBarHeight = $(".barra-laterale").last().height();
var heightDifference = contentHeight - sidebarHeight;
$(".barra-laterale").last().height(lastSideBarHeight + heightDifference)
}

Find DOM elements at top and bottom of scrolling div with jQuery

I have a scrolling div containing list items. I have this boilerplate scroll event defined
$("#scrollingDiv").scroll(function(e) {
});
Inside of this scroll event function, how can I figure out which elements are at the top and bottom of the currently visible area?
You could try computing the positions of the list items with respect to the scrolling <div> and then scan the positions to see which ones match up with the scrollTop of the <div>.
Something like this perhaps:
var base = $('#scrollingDiv').offset().top;
var offs = [ ];
$('li').each(function() {
var $this = $(this);
offs.push({
offset: $this.offset().top - base,
height: $this.height()
});
});
$("#scrollingDiv").scroll(function() {
var y = this.scrollTop;
for(var i = 0; i < offs.length; ++i) {
if(y < offs[i].offset
|| y > offs[i].offset + offs[i].height)
continue;
// Entry i is at the top so do things to it.
return;
}
});
Live version (open your console please): http://jsfiddle.net/ambiguous/yHH7C/
You'd probably want to play with the fuzziness of the if to get something that works sensibly (1px visible hardly makes an element the top one) but the basic idea should be clear enough. Mixing in the height of #scrollingDiv will let you see which <li> is at the bottom.
If you have a lot of list items, then a linear search might not be what you want but you should be able to solve that without too much effort.

Script that makes all floating divs the same height

Hey there, I have 20 divs floated left with different height. I use this script to resize them. It worked perfect when my website was designed using pixels.
When i have changed my website to % design (percentage design), the script stopped working that reliable, sometimes it does not resize.
can you take a look, see if there are any adjustments needed for liquid layouts?
maybe it's the way i call the script?
Ty very much
Here it is:
var currentTallest = 0;
var currentRowStart = 0;
var rowDivs = new Array();
function setConformingHeight(el, newHeight) {
// set the height to something new, but remember the original height in case things change
el.data("originalHeight", (el.data("originalHeight") == undefined) ? (el.height()) : (el.data("originalHeight")));
el.height(newHeight);
}
function getOriginalHeight(el) {
// if the height has changed, send the originalHeight
return (el.data("originalHeight") == undefined) ? (el.height()) : (el.data("originalHeight"));
}
function columnConform() {
// find the tallest DIV in the row, and set the heights of all of the DIVs to match it.
$('div.column').each(function(index) {
if(currentRowStart != $(this).position().top) {
// we just came to a new row. Set all the heights on the completed row
for(currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) setConformingHeight(rowDivs[currentDiv], currentTallest);
// set the variables for the new row
rowDivs.length = 0; // empty the array
currentRowStart = $(this).position().top;
currentTallest = getOriginalHeight($(this));
rowDivs.push($(this));
} else {
// another div on the current row. Add it to the list and check if it's taller
rowDivs.push($(this));
currentTallest = (currentTallest < getOriginalHeight($(this))) ? (getOriginalHeight($(this))) : (currentTallest);
}
// do the last row
for(currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) setConformingHeight(rowDivs[currentDiv], currentTallest);
});
}
$(window).resize(function() {
columnConform();
});
$(document).ready(function() {
columnConform();
});
Well if you change it to fluid layout (% design) then you are going to have to add a window resize listener, basically when the resize event is done or while it's running you need to recall the script so it can recalculate with new dimensions, you did not need to doo that with pixels because it was a fixed size and once assigned will not change no matter how many times you resize the actual screen.
If you use styles like this:
<style>
.parent{
background:#F00;height:300px
}
.parent div{
float:left;height:100%;width:33.33%;
}
</style>
<div class="parent">
<div style="background:#FED"></div>
<div style="background:#EDF"></div>
<div style="background:#DFE"></div>
</div>
You just have to set the height of the parent div, and the width of the children div

Categories

Resources