Set all panels width to the width of the widest panel - html

I have jquery tabs and i would like to make all panels width be the same as the widest panel width.
Something like heightStyle:"auto" works for height.
widthStyle:"auto" would be what im looking for, but it doesn't exist.
Comparison of how it looks vs how i would like it to look:
<div id="tabs" class="tab" >
<ul>
<li><span>One</span></li>
<li><span>Two</span></li>
<li><span>Three</span></li>
</ul>
<div id="f1">aaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div id="f2">bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb</div>
<div id="f3">c<br>c<br>c<br>c<br>c<br>c<br></div>
</div>
<div style="clear:both">
</div>
<div id="tabs2" class="tab" >
<ul>
<li><span>One</span></li>
<li><span>Two</span></li>
<li><span>Three</span></li>
</ul>
<div id="f1">aaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div id="f2">bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb</div>
<div id="f3">c<br>c<br>c<br>c<br>c<br>c<br></div>
</div>
<script>
$("#tabs").tabs({
heightStyle: "auto",
}).css("float", "left");
$("#tabs2").tabs({
heightStyle: "auto",
}).css("float", "left").width(485);
</script>
http://jsfiddle.net/knj73r9o/2/
I'd like to do it without hardcoding the width but automatically using the contents width. Is something like that possible?

To address this, you will want to iterate each panel and determine the largest width value. Since the width is collapsed, you have to also activate each panel. Something like this will help:
Example: https://jsfiddle.net/Twisty/knj73r9o/24/
JavaScript
$(function() {
function findMaxWidth($tab) {
var mw = 0;
var oInd = $tab.tabs("option", "active");
$tab.find(".ui-tabs-panel").each(function(ind, el) {
$tab.tabs("option", "activate", ind);
console.log("Activate Tab " + ind);
if ($(el).width() > mw) {
mw = $(this).width();
console.log("Tab " + ind + " Width: " + mw + "px");
}
});
$tab.tabs("option", "active", oInd);
return mw;
}
$("#tabs").tabs({
heightStyle: "auto",
}).css("float", "left");
var widthStyle = findMaxWidth($("#tabs"));
$("#tabs div").each(function() {
$(this).css("width", widthStyle + "px");
});
$("#tabs2").tabs({
heightStyle: "auto",
}).css("float", "left").width(485);
});
Once you have the width, you can use .css() to set the width of each.
If you need to do this a lot, or on many items, consider using $.widget() to set your own widthStyle option or function.
Hope it helps.

You can use CSS and have the tabs expand to width of 100%. This would expand to the width of the parent container.
.tab{
width: 100%;
}

Related

Bootsrap Affix not working

I have added the library for Bootstrap and data-spy attribute where I want to make the div fix when I scroll the page down. But it doesn't work, I have almost tried everything, but not able to figure out the problem.
Is is something like the data-spy attribute doesn't work on class = "row" ?
Here's my code for HTML.
<div class="row">
<h4> HEADING </h4>
<h5>
<div class="row" data-spy="affix" data-offset-top="10">
dsds
Date : <input type="date" name="graph_date" id="graph_date">
</div>
<div class="row">
<div class="graph-hourly">
<div class="loader" id="chart_loader">
<p>Loading...</p>
</div>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_hourly"></div>
</div>
</div>
</div>
and some css :
.affix {
top : 0;
width: 80%;
}
after searching for some solutions, I've added this also,
.affix-top {
width: 100%;
}
.affix-bottom {
position: absolute;
width: 100%;
}
but this solution also dosen't worked for me.
Not sure what the problem is in your case. I copied and pasted your code into a jsfiddle with the bootstrap library and the affix class did work. Though, it worked badly because it affixed the row right when you started scrolling.
Looks like Bootstrap doesn't have a way to set the offset to the current position of the element so I added the following javascript to make it work.
$('#affix-this').affix({
offset: {
top: $('#affix-this').offset().top
}
})
(#affix-this should be changed to the id of the row you want to affix.)
Note the $('#affix-this').offset().top. This makes sure the element gets affixed right when you reach the element's current position.
Second, I removed the html attributes that you had for the affixing.
<div class="row">
<h4> HEADING </h4>
<div class="row" id="affix-this">
dsds Date :
<input type="date" name="graph_date" id="graph_date">
</div>
<div class="row">
<div class="graph-hourly">
<div class="loader" id="chart_loader">
<p>Loading...</p>
</div>
<div id="chart_hourly"></div>
</div>
</div>
Notice the affix-this id was added to the row that you want to affix.
Here is a working JSFiddle with these changes so you can see it in action: https://jsfiddle.net/heraldo/6s4u26m3/4/
First of all delete top:0; from affix class because it will make a issue for you.
now you have two methods pick a one :
1
adding data-spy="affix" which is works fine for me
2
same result ass data-spy but you will need some styling after you complete your page
by adding a position Property for input tag
as ex. :
CSS:
sticky{
position:fixed;
}
and HTML :
<input type="date" name="graph_date" class="sticky" id="graph_date">
Update 1
this Jquery code can detect a scroll event so when user scroll down it will make the div tag sticky or "affix"
$(function() {
$(window).scroll(function() {
var aTop = "100";
if ($(this).scrollTop() >= aTop) {
$('#affix-this').css( "position", "fixed" );
$('#affix-this').css( "top", "0" );
$('#affix-this').css( "width", "100%" );
}
});
});
change the aTop variable with the height you want (in pixel) so when the user scroll down 100px the div become sticky
a JSfiddle example
Update 1.1
a bit smarter Jquery code do the same but get the height automatically from a another element this can be good if you format your page to something similar to this
$(function() {
$(window).scroll(function() {
var aTop = $('id').height();
if ($(this).scrollTop() >= aTop) {
$('#affix-this').css( "position", "fixed" );
$('#affix-this').css( "top", "0" );
$('#affix-this').css( "width", "100%" );
}
});
});
Make sure the element to which you're adding data-spy="affix has been created in the DOM before your Bootstrap scripts load. I ran into an issue where I was adding data-spy="affix" in my HTML, but it was wrapped up in a section that wasn't rendering, thanks to data-ng-if. My HTML was created after my Bootstrap had loaded, so the <div> I wanted to stick to the top of the screen never stayed in a fixed position. If you can, use data-ng-show, or something that merely hides HTML, rather than prevents it from being created on page load.

CSS transition of height for injected content into a DIV

I'm having a following template:
<div class='content'>
{{content}}
</div>
And following style:
.content {
margin-top: 30px;
background-color: skyblue;
width: 300px;
transition: all linear 0.5s;
}
Please note that {{content}} will grow or shrink (technically to extend a card to show more information or hide it). I've already set the css transition and it does work when manually setting a different height to the element. However when more content is injected into content no transition is made, just a plain old resizing. Any help of getting the transision right?
See following plunkr
Thanks,
Amit.
I believe that's quite normal, transitions apply only to changes to the CSS, not for computed changes.
One option might be to have a nested div, set overflow: hidden on the outer one, then get the computed height of the inner one and set it on the outer one to get the transition.
CSS:
#outer {
margin-top: 30px;
background-color: skyblue;
width: 300px;
transition: all linear 0.5s;
overflow: hidden;
}
HTML:
<button id="more" onclick="increase();">More</button>
<button id="more" onclick="decrease();">Less</button>
<div id="outer">
<div id="inner">
lorem ipsum
</div>
</div>
JS:
function increase()
{
var o = document.getElementById('inner');
var t = o.innerHTML;
for (var i=0 ; i<20;i++)
t += " lorem ipsum";
o.innerHTML = t;
adjustHeight();
}
function decrease()
{
var o = document.getElementById('inner');
o.innerHTML = "lorem ipsum";
adjustHeight();
}
function adjustHeight()
{
var i = document.getElementById('inner');
var o = document.getElementById('outer');
o.style.height = window.getComputedStyle(i).height;
}
Working fiddle: http://jsfiddle.net/Lnts7w1f/
With the help of #jcaron answer I managed to sort this in a react component. So when the 'activeSubsection' button is clicked the useEffect hook is run.
const [topicsHeight, setTopicsHeight] = React.useState("0px")
const topicsDiv = React.useRef();
React.useEffect(() => {
setTopicsHeight(topicsDiv?.current?.offsetHeight + "px")
}, [activeSubsection])
{!hideTopics &&
<div style={{ overflow: "hidden", height: topicsHeight, transition: "0.2s" }}>
<Topics ref={topicsDiv} className="largeScreen">
{!!subsectionTopics && subsectionTopics.sort((a, b) => a.node.slug.localeCompare(b.node.slug)).map((topic, index) =>
<Link key={index} href={'/'+slug+'/'+topic.node.slug} scroll={false}>
<Topic
active={activeTopic == topic.node.slug} transition={true} bold={activeTopic == topic.node.slug}
>
{topic.node.title}
</Topic>
</Link>
)}
</Topics>
</div>
}
Ovbiously that's not the full component but hopefully enough to give you an idea.
Well... There's a trick you can do for that... I don't know if it will fit your needs.
The css transition effect is applied on css properties that have a previous value, and then change. Though you are indeed changing the content's height of the div, the actual css property height is not explicitly changing. That's why you don't get the animation.
A workaround is to find the inner height of the div and then set it to the element, causing it to animate. I've created a function for that, and added a span to control the inner size of the div.
Just call the function on every change:
<div class='content'>
<span id="height-control">
{{ctrl.content}}
</span>
</div>
JS function:
var spn = document.getElementById("height-control");
var UpdateHeight = function () {
var h = spn.offsetHeight;
spn.parentNode.style.height = h + "px";
};
http://plnkr.co/edit/p6QRAR5j4C8d0d0XRJRp?p=preview

Making a calendar component scrollable on x and y axis

I'm creating a calendar component with my own HTML/CSS.
It can have multiple categories across it's header horizontally (x-axis) and it will have up to 24 time slots down it's side vertically (y-axis).
The category headers must always be visible when scrolling vertically and the time slots must always be visible when scrolling horizontially.
How can I achieve this via css?
See screenshot for what I want (Image more tracks across header that results in content overflow).
Maybe take this as my sinple html structure:
<div class="calendar">
<div class="calendarColumnHeaders"></div>
<div class="calendarGrid">
<div class="timeSlotsColumn"></div>
<div class="tracksContainer"></div>
</div>
</div>
Thanks
Give <div class="tracksContainer"></div> an extra class called stick
add this Css:
.stick {
position:fixed;
top:0px;
}
And unfortunately, you do need some Jquery
jQuery – Calculates the position of the sticker div and makes its position fixed if the page has scrolled that far.
$(document).ready(function() {
var s = $(".tracksContainer");
var pos = s.position();
$(window).scroll(function() {
var windowpos = $(window).scrollTop();
s.html("Distance from top:" + pos.top + "<br />Scroll position: " + windowpos);
if (windowpos >= pos.top) {
s.addClass("stick");
} else {
s.removeClass("stick");
}
});
});
overflow-x: scroll; //horizontal
overflow-y: scroll; //vertical

Hide particular div onload and then show div after click

I have two divs div1 and div2. I want div2 to be automatically hidden but when i click on preview div then div2 to be made visible and div1 to hide. This is the code i tried but no luck :(
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("div2").hide();
$("#preview").click(function() {
$("#div1").hide();
$("#div2").show();
});
});
</script>
<div id="div1">
This is preview Div1. This is preview Div1.
</div>
<div id="div2">
This is preview Div2 to show after div 1 hides.
</div>
<div id="preview" style="color:#999999; font-size:14px">
PREVIEW
</div>
Make sure to watch your selectors. You appear to have forgotten the # for div2. Additionally, you can toggle the visibility of many elements at once with .toggle():
// Short-form of `document.ready`
$(function(){
$("#div2").hide();
$("#preview").on("click", function(){
$("#div1, #div2").toggle();
});
});
Demo: http://jsfiddle.net/dJg8N/
This is an easier way to do it. Hope this helps...
<script type="text/javascript">
$(document).ready(function () {
$("#preview").toggle(function() {
$("#div1").hide();
$("#div2").show();
}, function() {
$("#div1").show();
$("#div2").hide();
});
});
<div id="div1">
This is preview Div1. This is preview Div1.
</div>
<div id="div2" style="display:none;">
This is preview Div2 to show after div 1 hides.
</div>
<div id="preview" style="color:#999999; font-size:14px">
PREVIEW
</div>
If you want the div to be hidden on load, make the style display:none
Use toggle rather than click function.
Links:
JQuery Tutorials
http://docs.jquery.com/Main_Page
http://www.w3schools.com/jquery/default.asp (W3Schools)
http://thenewboston.org/list.php?cat=32 (Video Tutorials)
http://andreehansson.se/the-basics-of-jquery/ (Basic Tutorial)
JQuery References
http://api.jquery.com/
http://oscarotero.com/jquery/
You are missing # hash character before id selectors, this should work:
$(document).ready(function() {
$("#div2").hide();
$("#preview").click(function() {
$("#div1").hide();
$("#div2").show();
});
});
Learn More about jQuery ID Selectors
The second time you're referring to div2, you're not using the # id selector.
There's no element named div2.
$(document).ready(function() {
$('#div2').hide(0);
$('#preview').on('click', function() {
$('#div1').hide(300, function() { // first hide div1
// then show div2
$('#div2').show(300);
});
});
});
You missed # before div2
Working Sample
At first if you want to hide div element with id = "abc" on load and then toggle between hide and show using a button with id = "btn" then,
$(document).ready(function() {
$("#abc").hide();
$("#btn").click(function() {
$("#abc").toggle();
});
});

Expanding Vertical Space Issue with Floated Elements

I have a layout that requires a list of items to be organized into two vertical columns. The items are in a single list of <div>s, with the markup also being re-purposed for mobile, so I don't want to modify the structure.
The problem I have here is that each item has an expanding content area which the user can toggle, and when this content is expanded the vertical space for that column needs to expand downward with the other column staying fixed.
Right now I have a basic solution with floated items, but when I expand the content areas the vertical space expands in both columns instead of just the one.
Here's a link to an example of the functionality as I have it now, and below is a screenshot of what the desired behavior should be.
Is it possible to style this to support the required behavior? Or am I going to have to modify the structure of items in order to get this to work? Thanks in advance for your help!
Your premise is flawed. Document structure flows left-to-right, top-to-bottom. You will need to make some change to the structure... Easiest would be adding two containers for a left column and a right column. Otherwise, you're in for some tricky absolute positioning markup, and a little funky jquery, which I can only suggest with the addition of some unique IDs for each of the panels.
I would, personally, add ids such as panel1 through panel4 per your example, then use this javascript (or similar) as a jumping off point:
for(var i=1; i<=4; i++) {
$('#panel'+i).css('left', function(index) {
if(i%2 == 0) return "120px";
else return "0px";
});
}
$('.more').click(function(e) {
e.preventDefault();
$(this).parent().children('p').toggle();
var id = $(this).parent().attr("id");
switch( id ) {
case 'panel1':
console.log("panel1 found");
$('#panel3').css('top', function(index) {
var buffer = $('#'+id).height() + 20 + "px";
return buffer;
});
break;
case 'panel2':
$('#panel4').css('top', function(index) {
var buffer = $('#'+id).height() + 20 + "px";
return buffer;
});
break;
default: break;
}
});
With the default values in the css for those panels:
#panel1 { top:0px; }
#panel2 { top:0px; }
#panel3 { top:56px; }
#panel4 { top:56px; }
The less you tweak the html, the more work you'll create in javascript.
edit:
Proposed alternate Javascript to remove need to alter HTML, assuming two elements per row. Since we know the row to be the problem...
var ct = 1
$('#container > div').each(function(index, domEle) {
$(domEle).attr('id', 'panel'+ct);
$('#panel'+ct).css({
'position': 'absolute',
'left' : function(index, value) {
if(ct%2 == 0) return "120px";
else return "0px";
},
'top' : function(index, value) {
return (56 * Math.floor(ct/3)) + "px";
}
});
ct++;
});
$('.more').click(function(e) {
e.preventDefault();
$(this).parent().children('p').toggle();
var id = $(this).parent().attr("id");
switch( id ) {
case 'panel1':
$('#panel3').css('top', function(index) {
var buffer = $('#'+id).height() + 20 + "px";
return buffer;
});
break;
case 'panel2':
$('#panel4').css('top', function(index) {
var buffer = $('#'+id).height() + 20 + "px";
return buffer;
});
break;
default: break;
}
});
Now no changes need be made to the HTML, though you'll want to redo the click function to handle repositioning of elements after a click. I would make life easy and hide all .more items before expanding a new box, since it would mean having to calculate the heights of all elements above, but how much work you want to make is your business.
Here's a PURE CSS SOLUTION for four panels (I don't know if you intended to have more, and I do not have six [2 wide 3 high] working yet--and suspect it is not possible). It works in FF and IE8/9. See the fiddle: http://jsfiddle.net/bEgwB/203/
However, IE8 experiences a redraw bug that keeps panel 3 from moving so it needs extra javascript help (added in fiddle above), and IE7 needs some margin adjustments to get panel 4 positioned correctly (but does not have the redraw issue even without the extra javascript help). UPDATE (11-18-11): here's the fiddle for IE7 margin adjustment: http://jsfiddle.net/bEgwB/286/
EDIT: a previous version of my CSS had display calls that were unnecessary.
HTML
<div id="container">
<div class="panel one">
Panel 1<br />
<a class="more" href="#">more</a>
<p>More Info 1 with some additional content</p>
</div>
<div class="panel two">
Panel 2<br />
<a class="more" href="#">more</a>
<p>More Info 2 with some additional content</p>
</div>
<div class="panel three">
Panel 3<br />
<a class="more" href="#">more</a>
<p>More Info 3 with some additional content</p>
</div>
<div class="panel four">
Panel 4<br />
<a class="more" href="#">more</a>
<p>More Info 4 with some additional content</p>
</div>
</div>
CSS
a {color:yellow;}
#container {width:0 ; padding: 0 130px;}
.panel {
background-color:green;
padding:5px;
color:#fff;
width:100px;
}
.panel p {display:none;}
.panel.one {
float: left;
margin:10px 0 10px -120px;
}
.panel.two {
float: right;
margin: 10px -120px 20px 0;
}
.panel.three {
float: left;
clear: left;
margin:10px 10px 10px -120px;
}
.panel.four {
clear: right;
margin: 10px;
}
JAVASCRIPT
$('.more').click(function(e) {
e.preventDefault();
$(this).parent().children('p').toggle();
/* the following fix IE8 */
$(this).parent().parent().hide();
$(this).parent().parent().show();
});
You need to add two more div's - left and right column and split your items between these two divs. This is the way how to make them independent, here is jsfiddle for this.
HTML
<div id="container">
<div class="left">
<div class="panel">
Panel 1<br />
<a class="more" href="#">more</a>
<p>More Info 1 with some additional content</p>
</div>
<div class="panel alt">
Panel 2<br />
<a class="more" href="#">more</a>
<p>More Info 2 with some additional content</p>
</div>
</div>
<div class="right">
<div class="panel">
Panel 3<br />
<a class="more" href="#">more</a>
<p>More Info 3 with some additional content</p>
</div>
<div class="panel alt">
Panel 4<br />
<a class="more" href="#">more</a>
<p>More Info 4 with some additional content</p>
</div>
</div>
</div>
CSS
a {color:yellow;}
#container {width:300px; position:relative;}
.panel {background-color:green;padding:5px;color:#fff;width:100px;margin:10px;}
.panel p {display:none;}
.left {
width: 50%;
float: left;
}
.right {
width: 50%;
float: right;
}
May be you can do it column-count property like this:
a {color:yellow;}
#container {
width:300px;
-moz-column-count: 2;
-moz-column-gap: 50%;
-webkit-column-count: 2;
-webkit-column-gap: 50%;
column-count: 2;
column-gap: 50%;
}
.panel p {display:none;}
.panel {background-color:green;padding:5px;color:#fff;width:100px;margin:10px;}
.alt{
margin-bottom:90px;
}
Check this fiddle http://jsfiddle.net/bEgwB/87/
UPDATED
Check this:
http://jsfiddle.net/bEgwB/276/
There is a styling solution. To tie the two columns together they need an extra level of binding you can do that by adding a style attribute to "container", "display:table" and to the panels with "display:table-cell".
That will keep the heights in synch. Both "container" and the "panel" class must have a declared width or they really mess up the layout. IE is weak on support of these attributes, so that could be a problem with the solution.
If I correctly inderstand, that do you you want is something like this
http://jsfiddle.net/bEgwB/275/
You need to use both css properties display:inline-block and float:left to implement effect like on your jpg. If my markup right and this looks as expected, I may help you with javascript, if it not ok now
Good luck.