adjust heights of div's - based on resolutions and items count - javascript

I've a requirement where I have 3 panels(Chats, Groups, Channels) in the left side panel and I need to adjust their heights based on the resolutions and also the items in that panels.
I will make api calls and get the items for that panels and bind them through angular bindings.
Please check the JSFiddle I've prepared for a clear understanding.In this, I've also wrote some additional media queries and adjusted the max-heights for the resolutions.
Now, My actual requirement is :
1) If there are no items at all in all the 3 panels, then all panels should collapse which is already working.
2) If all the 3 panels has items more than its size, then scroll should appear as the output screen which is already working.
3) If only one panel has items, then it should automatically expand its size like shown in the image in the
and same should apply to other panels as well.
4) Finally, if only few items are available in the 2 panels and more items are present in the 3rd panel, then it should show in the following way.
Actually, I thought of writing some jquery after the api calls based on the items count but that's kind of getting hard because I need to check the resolutions as well and also the items count in all the panels.
Is there any css way of achieving this?
at least, is there any article or something where I can follow and do this?
is jquery, the only way of doing this?

You could standardise it at 33.33333vh height then modify it using jQuery after the fact. It could get a little complex depending on how many exceptions you want to cater for but this unit will take care of the resolution differences and is supported by modern browsers.
In your jQuery you could work out the number of items in each panel as a percentage of the total and give each panel an appropriate height in vh - the label.
$(function() {
var totalNumItems = $('.panel div').length;
$('.panel').each(function() {
setPanelHeight($(this));
});
function setPanelHeight(panel) {
var numItems = panel.find('div').length,
heightPercentage = (numItems / totalNumItems) * 100;
/* calc -1.5em takes the label height into account */
panel.css('height', 'calc(' + heightPercentage + 'vh - 1.5em)');
panel.niceScroll();
}
});
If there were no items in a panel, it would calculate its vh as 0 and as such collapse it.
Edit: jsfiddle: https://jsfiddle.net/mattBBP/8vvcub3c/
This doesn't quite work because the area it's being displayed is not 100% of the viewport but this could be modified/offset / would not be a problem out of the fiddle.

Related

Unordered list containing list items with dynamic widths - horizontal menu

I need help trying to space my horizontal menu the width of its parent <div>.
The problem is that the list items in the <ul> are dynamic, so there are a number of combinations varying depending on whether or not you are logged, whether or not you have joined the page, and whether or not you are an Admin.
I have set the <ul> to be 100% of the parent <div>. This works fine. Currently my <li>s are all just left aligned, you can see this on http://www.daddyleagues.com/OzeSportsCFM (it's the section with home coaches stats etc)
The problem is that I am only editing this by using CSS overrides and JS (adding classes etc) through a CMS. I can't adjust the widths as the list is determined.
So I am wondering if there is any magical way to make the <li>s calculate their own %
I'm thinking I may just have to create some JavaScript function which adds the widths in % depending on what items appear. This is a last resort, hoping someone has some easier way.
You can use css3 flexbox.
ul{
display:flex;
justify-content: space-around;
}
Read more about flexbox # css-tricks
Flexbox browser support #caniuse
get your list parent element (ul), lets call it "menu" for the sake of an answer.
var menu = document.getElementById('menu'),
width = 100 / menu.length;
Array.prototype.slice.call(menu.children).forEach(function(li) {
li.setAttribute('style', 'width:' + width + '%;');
});

Responsive "masonry-like" columns without using masonry (trying to avoid position:absolute;)

I have a layout of boxes that are all floated left and when you click on their headings, they slide open revealing content. The issue is that the way floats work, when you click to expand one of them, it messes with the row underneath.
http://jsfiddle.net/FCCye/ <-- click on one of the headings to see the issue.
I've solved this by separating them into columns like so:
http://jsfiddle.net/caW4M/
That works fine, however, the layout needs to be responsive, so when the window is 480 or lower, it needs to be 1 column. Between 480 and 768 it needs to be 2 columns. Anything above 768, 3 columns. (obviously, the jsfiddles don't show the breakpoints I have set up.)
This is the code I've come up with to solve this, however it is not working at all. I was wondering if someone could tell me what I'm doing wrong.
// Create all three portfolio columns
var one = $('<div/>').addClass('column').addClass('one');
var two = $('<div/>').addClass('column').addClass('two');
var three = $('<div/>').addClass('column').addClass('three');
// Store all portfolio elements into variables once they're in columns
var colElems = $('.column .project');
// Now append the columns
var winWidth = $(window).width();
if ( winWidth > 480 && winWidth <= 768 ) {
// Remove everything from columns and delete existing columns
$(colElems).appendTo('#portfolio .content');
$('#portfolio .content').remove(one,two,three);
// Store portfolio elements into variables for safe-keeping
var c1Elems = $('.project:nth-child(2n+1)');
var c2Elems = $('.project:nth-child(2n+2)');
// Perform appends into portfolio columns
c1Elems.appendTo(one);
c2Elems.appendTo(two);
// Append portfolio elements to columns
$('#portfolio .content').append(one,two);
}else{
// Remove everything from columns and delete existing columns
$(colElems).appendTo('#portfolio .content');
$('#portfolio .content').remove(one,two,three);
// Store portfolio elements into variables for safe-keeping
var c1Elems = $('.project:nth-child(3n+1)');
var c2Elems = $('.project:nth-child(3n+2)');
var c3Elems = $('.project:nth-child(3n+3)');
// Perform appends into portfolio columns
c1Elems.appendTo(one);
c2Elems.appendTo(two);
c3Elems.appendTo(three);
$('#portfolio .content').append(one,two,three);
}
So, what I'm trying to do is append the normal 3 columns when it's not between 480 and 768 (because on mobile size, the columns would stack on top of each other anyway) and when between 480 and 768, only append two columns. So my thought is that at the different sizes, I would have to pull all of the boxes out of the columns, delete the columns, and reappend the columns in different numbers based on the window width. This has proved to be a failed attempt, so if anyone can explain to me what I'm doing wrong I would be very appreciative!
Thanks!
Not an answer to your question, but if you will follow the advice then your question will no longer be of interest. ;-)
First of all why don't you use CSS3 Media Queries for your different layouts? That is what they are for.
Secondly it is "bad practice" to use pixel values (or any other kind of absolute units) for defining breakpoints, even if a lot of authors actually do! It is best to only use relative units like 'em'.
The new Flexbox module could also be an option for you, depending on the supported Browser versions (especially IE 8).
And why don't you let the expanded box not simply overlap the other content by using 'position: absolute'?
Well, doing things with Javascript which should be done with pure CSS isn't a good idea. What happens, when JS is deactivated? And also from a performance point of view, on resizing the viewport ... - all bad.
So my advice would be to completely rethink your approach.

How to determine how many CSS3 columns are actually being displayed (vs. the specified column-count)?

I have a list of tags that are in a box that I've specified as having multiple columns:
#tags {
-webkit-columns: 140px 5;
}
Result:
The content of this list is dynamically generated.
When I resize the browser window, the number of columns collapses. e.g.:
Using jQuery / JS / CSS / etc., how can I determine how many columns are being displayed at any given time?
Unless you specified all column width-related properties browsers will try to fit whole number of columns in content area (between left and right padding of element). So (contentWidth + columnGap)/(columnWidth + columnGap) rounded down will give you result.
Note that right padding may be set so high that whole column will be able to fit there - you may need to adjust computations.
You can also directly get size of column if you have an element with 100% width inside columns text.
You can get the value like this:
$('#tags').css('-webkit-column-count');
Try alerting this:
alert($('#tags').css('-webkit-column-count'));
Similar to Alexei's answer, I figured out a solution to get the column count:
var $tags = $("#tags"),
column_width = $tags.children(':first').width(),
container_width = $tags.width(),
column_count = Math.floor(container_width / column_width); // in my case, sum of column gaps is less than the width of a column, so I can round down.

vertical carousel cutting off images

I am currently aiming to implement a vertical carousel, to allow users to navigate through a gallery of thumbanils, the carousel is meant to show 3 items per click however it only shows 2 and a bit.
The link to see it in action is http://mensclothingroom.factoryagency.co.uk/product/lambswool-round-neck-sweater/
Have I implemented it incorrectly I personally think that the plugin is working out the parent containers height incorrectly.
Looking at your js file (/themes/mcr/resources/javascript/jquery.carousel.min.js) at this moment your wrapper height is calculated by
s.itemHeight * s.steps.count + "px"
but $itemHeight = $item.outerHeight(); and this don't take into account the margin-bottom (6px) you inserted for your <li> elements: in fact you wrapper is now 252px height tall (that is 84px * 3) instead of 266px so you should change that expression into
$itemHeight = $item.outerHeight(true);
this will make the wrapper tall enough (84 + 6)px * 3 = 270px to contain entirely three thumbnails but , of course, adjust and tune the height calculation to fit your need.
see http://api.jquery.com/outerHeight/ for more information

Table Row SHOW / HIDE *Without* Column Width Resizing, w/ TableLayout: auto

I have table with multiple rows, showing items for sale. When the user clicks on a row, a Javascript inserts / shows a new row right beneath it with details about the item. The issue is when the description is long, it forces the column widths to readjust / resize. This shifts the columns positions and is really annoying, especially for the user. Right now, I have my table.style.tableLayout: auto. I actually prefer it this way, because the columns are adjusted to the content.
My question is: how do I dynamically "lock" the widths of the columns in my table so that when I insert / show the new row, the columns do not readjust / resize?
I've tried:
dynamically setting the table to temporarily "tableLayout: fixed"
inserting / showing my new row
changing the table back to "tableLayout: auto"
Actions 1 & 2 works in in FireFox, but not in Safari and IE (6 & 7). However, doing all three seems to prevent the columns from shifting too much.
The frustration is unbearable ... loosing lots of sleep ... please help!
Thanks.
For those looking for the code (this is done in jQuery). This also assumes the first row has the proper widths for each cell. Pretty easy changes if needed.
$('table.class_of_table_to_fix tr:first td').each(function() {
$(this).css({'width': $(this).width()+"px"});
});
I would set a percent width on each column simply as a guide. Set it just once on the TH of each column. The browser will still adjust the columns to content if necessary, but the columns will stay in place more consistently.
Next, I would never put css "white-space:nowrap" anywhere on that table. A long description should not break the table layout, it should wrap around properly on multiple lines, and be readable if you set the widths on each column to suit the type of data. Similarly I would keep the use of (non breakable spaces) to dates, times and numbers and allow the text to wrap.
Other than that, I do this at my job on a dialy basis, and there's a time when you need to stop ulling hairs asking the browser to do something it's not designed to do. Content should flow and adapt. Locking column widths to pixels is 99.99999% of the time a bad idea.
PS: If you really, reeally, REALLY need to lock columns, the only solution I'm aware of that works with CSS2 and accross all browsers is to use images. You could insert a 1px high transparent gif image in each column, and counting in the padding of the cells (TD), set a pixel width on each image (IMG), instead of on the columns (TH/TD). You could hide those in the TH for example. You can leave the images at 1 pixel wide and set percent widths on TDs, and when you open a new row, you would get each column width minus TD Padding, and set that to the corresponding IMG. I haven't tried! I just know that in many projects I've worked on, I've used small gif images to lock a minimum vertical spacing between columns, for example.
I had a similar problem when I was implementing a table with groups that could be toggled. I wanted the initial ratio between the columns to stay the same without fixing the widths of the columns. By default the browser would change the widths depending on the visibility of the table's rows, which was undesirable.
I went ahead and followed #faB's suggestion of applying percentages, but doing so using a small script that would calculate the percentages of the th elements and apply them after the initial render. This made my columns stay the same width, even with all rows hidden.
Here's the script, which uses jQuery:
(function($){
var lock_widths = function() {
var total_width = $('table').innerWidth();
var headers = $('table th');
var leftover = 100;
$.each(headers, function(ix, el) {
var header = $(el), width;
// on the last call use the leftover percentage
if (ix == headers.length - 1) {
width = leftover;
} else {
leftover -= width = header.outerWidth() / total_width * 100;
}
header.css({'width': width + '%'});
});
};
$(document).ready(lock_widths);
})(jQuery);
Tested in IE7+, Firefox and Chrome. This works for my special case because I have header columns as a reference, but it could be rewritten to measure some other columns.
You can display the details of the row beneath the clicked one in DIV and set its
style="overflow:auto";
so that details will wrap and scrollbar will be available to display entire text.
I don´t know if you´re familiar with jquery, but that´s what I would use - in combination with a separate class for the column that´s causing resizing in the new row - to:
Calculate / get the with of the column
Set the with of the afore mentioned class
Add the row
I haven´t tried it, but that should do it.
By the way, there are probably other ways to do it, I´m just more familiar with jquery (for point 1. and 2.).

Categories