Move exceeding list items to next column in bootstrap - javascript

I am having a row with two columns as shown in the snippet below.
Here in Column 1 there are 7 list items under ul tag.
But i am in the need to show Only 5 list items in column 1 and the rest of the items should move to the next column.. (i.e to Column 2).
How can i achieve the result to move the list items automatically to next column based on the count (here its 5), if the list items exceeding above count (5)..
And the result expected to be only in html and css and there should not be any library like jquery or any other third party.
Current Snippet:
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col-xs-4 mr-4">
<ul class="list-group">
<li class="list-group-item">List Item 1</li>
<li class="list-group-item">List Item 2</li>
<li class="list-group-item">List Item 3</li>
<li class="list-group-item">List Item 4</li>
<li class="list-group-item">List Item 5</li>
<li class="list-group-item">List Item 6</li>
<li class="list-group-item">List Item 7</li>
</ul>
</div>
<div class="col-xs-4 mr-4">
Column-2
</div>
</div>
</div>
Expected Result:
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col-xs-4 mr-4">
<ul class="list-group">
<li class="list-group-item">List Item 1</li>
<li class="list-group-item">List Item 2</li>
<li class="list-group-item">List Item 3</li>
<li class="list-group-item">List Item 4</li>
<li class="list-group-item">List Item 5</li>
</ul>
</div>
<div class="col-xs-4 mr-4">
<ul class="list-group">
<li class="list-group-item">List Item 6</li>
<li class="list-group-item">List Item 7</li>
</ul>
</div>
</div>
</div>

It's not possible to move elements from one DOM container to another with CSS.
One can change the layout behaviour in a single container though and CSS-Grid can do that without requiring a fixed height.....using the explicit and implict grid.
ul.list-group {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(5, 1fr);
grid-column-gap:1em;
grid-auto-flow: column;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.2/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div class="row">
<div class="col-xs-4 mr-4">
<ul class="list-group">
<li class="list-group-item">List Item 1</li>
<li class="list-group-item">List Item 2</li>
<li class="list-group-item">List Item 3</li>
<li class="list-group-item">List Item 4</li>
<li class="list-group-item">List Item 5</li>
<li class="list-group-item">List Item 6</li>
<li class="list-group-item">List Item 7</li>
<li class="list-group-item">List Item 8</li>
<li class="list-group-item">List Item 9</li>
<li class="list-group-item">List Item 10</li>
</ul>
</div>
</div>
</div>

You can achieve that using flexbox, but both the flex container (.list-group in this case) and flex items (.list-group-item) need to have explicit height in order to wrap properly.
And a little side-note: don't use col-xs with Bootstrap 4, use col instead.
.list-group {
height: 200px;
}
.list-group-item {
height: 40px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col-4 mr-4">
<ul class="list-group d-flex flex-column flex-wrap">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
</ul>
</div>
</div>
</div>

Related

Changing parent width by number of its child elements?

In the following example, I have a header with logo-container on the left, menu in the middle and a button on the right. In the example, the menu has 5 top-level items, and 2 sub-menus.
<div class="container">
<div class="logo_container">
<img src="logo.png" />
</div>
<div id="top-navigation">
<div id="top-menu-nav">
<ul id="top-menu">
<li class="top-item">Top Item 1</li>
<li class="top-item">Top Item 2
<ul>
<li class="sub-item">Sub-Item 1</li>
<li class="sub-item">Sub-Item 2</li>
<li class="sub-item">Sub-Item 3</li>
<li class="sub-item">Sub-Item 4</li>
</ul>
</li>
<li class="top-item">Top Item 3
<ul>
<li class="sub-item">Sub-Item 5</li>
<li class="sub-item">Sub-Item 6</li>
<li class="sub-item">Sub-Item 7</li>
<li class="sub-item">Sub-Item 8</li>
</ul>
</li>
<li class="top-item">Top Item 4</li>
<li class="top-item">Top Item 5</li>
</ul>
</div>
<ul id="menu-button">
<li class="menu-button-cta">Button</li>
</ul>
</div>
</div>
As top-level items might be added or removed, I'd like to change the width of the parent element in accordance with the number of top-level items in menu.
For instance:
<ul id="top-menu"> has 5 <li class="top-item"> = .container {width: 100%;}
<ul id="top-menu"> has 4 <li class="top-item"> = .container {width: 90%;}
<ul id="top-menu"> has 3 <li class="top-item"> = .container {width: 80%;}
Is there a way to do it in CSS or jQuery?
You can do this in jquery using .children().length, eg:
$("ul.top-menu").each(function() {
$(this).addClass(".container-" + $(this).children(".top-item").length);
});
then css:
.container-5 { width: 100%; }
.container-4 { width: 90%; }
.container-5 { width: 80%; }
Here is my solution with jQuery. First, calculating length of children, then applying style accordingly.
var lengthOfChildren = $("#top-menu").children().length;
switch (lengthOfChildren) {
case 3:
$(".container").css("width", "80%");
break;
case 4:
$(".container").css("width", "90%");
break;
default:
$(".container").css("width", "100%");
}

MMenu remove div

I'm using jQuery.mmenu https://mmenu.frebsite.nl. My menu looks like this (Desktop menu):
<nav id="navigation">
<ul class="navigation list-inline d-flex justify-content-center">
<li>
Menu 1
<div class="list-inline d-flex justify-content-center">
<div class="container">
<div class="row">
<div class="col navigation-column pt-1 pb-4">
<h3>Kategoria</h3>
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
</ul>
</div>
</div>
</div>
</div>
</li>
<li>Menu 2</li>
</ul>
</nav>
How can I get (mobile menu) plugin jQuery.mmenu:
<nav id="navigation">
<ul class="navigation list-inline d-flex justify-content-center">
<li>
Menu 1
<h3>Kategoria</h3>
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
</ul>
</li>
<li>Menu 2</li>
</ul>
</nav>
Please help. I've been trying 2 days but I can not improve it.

Show/Hide Tab Arrows to Navigate Additional Tabs on Overflow

Right now, I have a tab structure that looks like the following:
As you can see, when the tabs reach the end of the line they wrap to the next line. I know how to hide the additional tabs; however, I want to introduce an arrow system to navigate to the additional tabs when the tabs overflow. Something that looks like below depending on the screen resolution:
I only want to have the arrows appear if there are additional tabs that are being hidden, this leads me to my question: How do I detect when the tabs wrap and insert the arrows?
I need this to work with responsive layouts.
Here is the code I am using to create the tabs (note: it includes hard-coded list items for the arrows):
<ul id="tabs" class="tab-links">
<li class="">Tables & Views</li>
<li class="">ERD</li>
<li class=""><i class="fa fa-caret-left"></i></li>
<li class="active"><a class="query-tab" href="#query1">Query 1</a></li>
<li class="">Query 2</li>
<li class="">Query 3</li>
<li class="">Query 4</li>
<li class="">Query 5</li>
<li class="">Query 6</li>
<li class="">Query 7</li>
<li class="">Query 8</li>
<li class="">Query 9</li>
<li class=""><i class="fa fa-caret-right"></i></li>
<!-- Hidden Tabs -->
<li class="">Query 10</li>
<li class="">Query 11</li>
<li class="">Query 12</li>
</ul>
The answer requested:
window.addEventListener('load', initTabs);
function initTabs() {
var listContainer = document.getElementById('tabs');
var buttonWidthCounter = 0;
var totalContainerWidth = listContainer.offsetWidth;
for (var i = 0; i < listContainer.children.length; i++) {
if (buttonWidthCounter + listContainer.children[i].offsetWidth > totalContainerWidth) {
//button overflow...add tab buttons
console.log('there is overflow...add tab arrow buttons...');
}
buttonWidthCounter += listContainer.children[i].offsetWidth;
}
}
li {
display: inline-block;
}
<ul id="tabs" class="tab-links">
<li class="">Tables & Views</li>
<li class="">ERD</li>
<li class=""><i class="fa fa-caret-left"></i></li>
<li class="active"><a class="query-tab" href="#query1">Query 1</a></li>
<li class="">Query 2</li>
<li class="">Query 3</li>
<li class="">Query 4</li>
<li class="">Query 5</li>
<li class="">Query 6</li>
<li class="">Query 7</li>
<li class="">Query 8</li>
<li class="">Query 9</li>
<li class=""><i class="fa fa-caret-right"></i></li>
<!-- Hidden Tabs -->
<li class="">Query 10</li>
<li class="">Query 11</li>
<li class="">Query 12</li>
</ul>
The answer I suggest:
Scrollbars are much easier to implement and are arguably better.
li{
display:inline-block;
}
ul{
white-space:nowrap;
}
html,body{
margin:0;
padding:0;
}
#container{
width:100vw;
overflow:scroll;
}
<div id="container">
<ul id="tabs" class="tab-links">
<li class="">Tables & Views</li>
<li class="">ERD</li>
<li class=""><i class="fa fa-caret-left"></i></li>
<li class="active"><a class="query-tab" href="#query1">Query 1</a></li>
<li class="">Query 2</li>
<li class="">Query 3</li>
<li class="">Query 4</li>
<li class="">Query 5</li>
<li class="">Query 6</li>
<li class="">Query 7</li>
<li class="">Query 8</li>
<li class="">Query 9</li>
<li class=""><i class="fa fa-caret-right"></i></li>
<!-- Hidden Tabs -->
<li class="">Query 10</li>
<li class="">Query 11</li>
<li class="">Query 12</li>
</ul>
</div>

Slide down in each list

I need ul.list-group-subshould display none on first glance and when I click on "Click" (.dd), only one "list-group-sub" should display block from current li while "list-group-sub" should display none from other li and vice versa, only one is one "list-group-sub" open at a time
Fiddle Demo :
https://fiddle.jshell.net/alpeshlahad/zv3vpzew/3/
$(".list-group-item .dd").click(function() {
$("ul.list-group-sub").slideToggle();
});
ul.list-group-sub {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list-group member-list trainers-data ot-box">
<li class="list-group-item">
List 1
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
<li class="list-group-item">
List 2
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
</ul>
The issue is because your ul.list-group-sub selector is calling slideToggle() on all elements. You instead need to traverse the DOM to find the one related to the clicked .dd element. To do that you can use closest() to get the parent li, then find() to get the element you need.
To only display one menu at at time you also need to call slideUp() on them whilst toggling the target one. Try this:
$(".list-group-item .dd").click(function(e) {
e.preventDefault();
var $target = $(this).closest('li').find("ul.list-group-sub").slideToggle();
$('ul.list-group-sub').not($target).slideUp();
});
ul.list-group-sub { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list-group member-list trainers-data ot-box">
<li class="list-group-item">
List 1
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
<li class="list-group-item">
List 2
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
</ul>
Also note that I removed the use of javascript; in the href attribute of your a elements. You can instead call preventDefault() on the event to stop the default behaviour. This method has the benefit of de-coupling the JS logic from the HTML.
$("ul.list-group-sub").slideToggle() targets all sub-items. Use this:
$(this).closest('.list-group-item').find('.list-group-sub').slideToggle();
to target the corresponding list sub-items.
See demo below and updated fiddle here:
$(".list-group-item .dd").click(function() {
$(this).closest('.list-group-item').find('.list-group-sub').slideToggle();
});
ul.list-group-sub {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list-group member-list trainers-data ot-box">
<li class="list-group-item">
List 1
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
<li class="list-group-item">
List 2
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
</ul>

jQuery UI Sortable Multiple element target

I have 2 list element
<div id="list-one">
<ul class="ul-one">
<li data-order="1">item 1</li>
<li data-order="2">item 2</li>
<li data-order="3">item 3</li>
</ul>
</div>
<br />
<div id="list-two">
<ul class="ul-two">
<li data-order="1">item 4</li>
<li data-order="2">item 5</li>
<li data-order="3">item 6</li>
</ul>
</div>
Can ul-two list element order follow ul-one order when I sort ul-one using jQuery Sortable ?
I want get the result like
<div id="list-one">
<ul class="ul-one">
<li data-order="2">item 2</li>
<li data-order="1">item 1</li>
<li data-order="3">item 3</li>
</ul>
</div>
<br />
<div id="list-two">
<ul class="ul-two">
<li data-order="2">item 5</li>
<li data-order="1">item 4</li>
<li data-order="3">item 6</li>
</ul>
</div>
just drag ul-one element
Thanks for the answer
Sorry for misunderstand the question.
This is a working solution. I added id tag to easy call
http://jsfiddle.net/39ZvN/1141/
Try this
<div id="list-one">
<ul class="sort ul-one">
<li data-order="1">item 1</li>
<li data-order="2">item 2</li>
<li data-order="3">item 3</li>
</ul>
</div>
<br />
<div id="list-two">
<ul class="sort ul-two">
<li data-order="1">item 4</li>
<li data-order="2">item 5</li>
<li data-order="3">item 6</li>
</ul>
</div>
$( '.sort li' ).each(function() {
var position = $(this).data('order');
$(this).siblings().eq(position+1).after(this);
});

Categories