I want to manually scroll a UL list with two button.
First time 4 items will show and when user click on up or down button list will scroll 1 item a time.
$(document).ready(function() {
$(".down").on("click", function() {
$(".scroll").scrollTop(
$(".listitem:nth-child(4)").offset().top -
$(".listitem:nth-child(3)").offset().top
);
});
});
.scroll {
height: 100px;
width: 200px;
overflow-y: hidden;
overflow-x: hidden;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<div class="container"><div class="row">
<div class="col-md-12">
<ul class="scroll">
<li class="listitem">List Item 1</li>
<li class="listitem">List Item 2</li>
<li class="listitem">List Item 3</li>
<li class="listitem">List Item 4</li>
<li class="listitem">List Item 5</li>
<li class="listitem">List Item 6</li>
<li class="listitem">List Item 7</li>
<li class="listitem">List Item 8</li>
</ul>
<button class="btn up">Up</button>
<button class="btn down">Down</button>
</div></div>
Now i am stuck i don't how i can dynamically pass the next and previous li to make it work . i want to do it exactly like that as i show in down button list scroll to next item.
You can use scrollIntoView() method to scrolls the element into the visible area. Note that :not(:nth-last-child(3)) would be the n - 1 visible list.
$(document).ready(function() {
$(".down").on("click", function() {
var $active = $(".listitem.active");
var $target = $active.next();
if ($target.get(0) && $target.is(':not(:nth-last-child(3))')) {
$active.removeClass('active');
$target.addClass('active').get(0).scrollIntoView({
behavior: 'instant',
block: 'start',
inline: 'nearest',
});
}
});
$(".up").on("click", function() {
var $active = $(".listitem.active");
var $target = $active.prev();
if ($target.get(0)) {
$active.removeClass('active');
$target.addClass('active').get(0).scrollIntoView({
behavior: 'instant',
block: 'start',
inline: 'nearest',
});
}
});
});
.scroll {
height: 100px;
width: 200px;
overflow-y: hidden;
overflow-x: hidden;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<div class="container">
<div class="row">
<div class="col-md-12">
<ul class="scroll">
<li class="listitem active">List Item 1</li>
<li class="listitem">List Item 2</li>
<li class="listitem">List Item 3</li>
<li class="listitem">List Item 4</li>
<li class="listitem">List Item 5</li>
<li class="listitem">List Item 6</li>
<li class="listitem">List Item 7</li>
<li class="listitem">List Item 8</li>
</ul>
<button class="btn up">Up</button>
<button class="btn down">Down</button>
</div>
</div>
</div>
Related
I'm having trouble with removing a class on-click on the Tab 2 list-item. These are links with underlines that show content.
The code so far fairly close, just need a little hand on seeing what I've missed.
<script type='text/javascript' src='/js/jquery/jquery.js?ver=1.12.4'></script>
HTML
<div class="mk-tabs">
<ul>
<li class="mk-tabs-tab">Tab 1</li>
<li class="mk-tabs-tab is-active">Tab 2</li>
</ul>
<div class="mk-tabs-panes">
<div class="mk-tabs-pane">Tab Content 1</div>
<div class="mk-tabs-pane is-active">Tab Content 2</div>
</div>
</div>
jQuery
<script type="text/javascript">
jQuery(document).ready(function($){
$('.mk-tabs ul li a').click( function(){
if ( $('.mk-tabs ul li').hasClass('is-active') ) {
$('.mk-tabs ul li').removeClass('is-active');
}
else {
$('.mk-tabs ul li').removeClass('is-active');
}
});
});
</script>
Two varying behaviors ...
jQuery(function($){
$('.mk-tabs').on('click', 'a', function(e){
e.preventDefault();
var container = $(this).closest('.mk-tabs');
var currentTab = $(this).closest('.mk-tabs-tab');
var currentIndex = currentTab.index();
$(".mk-tabs-tab", container).not(currentTab).removeClass('is-active');
currentTab.toggleClass('is-active');
var panes = $('.mk-tabs-pane', container);
panes.hide();
if (currentTab.hasClass('is-active')) {
panes.eq(currentIndex).show();
}
});
});
jQuery(function($){
$('.mk-tabs2').on('click', 'a', function(e){
e.preventDefault();
var container = $(this).closest('.mk-tabs2');
var currentTab = $(this).closest('.mk-tabs-tab');
var currentIndex = currentTab.index();
currentTab.toggleClass('is-active');
$('.mk-tabs-pane', container).eq(currentIndex).show();
var panes = $('.mk-tabs-pane', container);
if (currentTab.hasClass('is-active')) {
panes.eq(currentIndex).show();
} else {
panes.eq(currentIndex).hide();
}
});
});
ul {
display: flex;
list-style: none;
}
.mk-tabs-tab {
padding: 5px 10px;
}
.mk-tabs-tab.is-active{
background-color: red
}
.mk-tabs-pane {
display: none;
}
.mk-tabs-pane.is-active {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mk-tabs">
<ul>
<li class="mk-tabs-tab">Tab 1</li>
<li class="mk-tabs-tab is-active">Tab 2</li>
<li class="mk-tabs-tab">Tab 3</li>
<li class="mk-tabs-tab">Tab 4</li>
</ul>
<div class="mk-tabs-panes">
<div class="mk-tabs-pane">Tab Content 1</div>
<div class="mk-tabs-pane is-active">Tab Content 2</div>
<div class="mk-tabs-pane">Tab Content 3</div>
<div class="mk-tabs-pane">Tab Content 4</div>
</div>
</div>
<div class="mk-tabs2">
<ul>
<li class="mk-tabs-tab">Tab 1</li>
<li class="mk-tabs-tab is-active">Tab 2</li>
<li class="mk-tabs-tab">Tab 3</li>
<li class="mk-tabs-tab">Tab 4</li>
</ul>
<div class="mk-tabs-panes">
<div class="mk-tabs-pane">Tab Content 1</div>
<div class="mk-tabs-pane is-active">Tab Content 2</div>
<div class="mk-tabs-pane">Tab Content 3</div>
<div class="mk-tabs-pane">Tab Content 4</div>
</div>
</div>
#farinspace I'm trying this. I think the bug is "closest" on the pane code.
HTML
<div class="mk-tabs">
<ul>
<li class="mk-tabs-tab">Tab 1</li>
<li class="mk-tabs-tab is-active">Tab 2</li>
</ul>
<div class="mk-tabs-panes">
<div class="mk-tabs-pane">Tab Content 1</div>
<div class="mk-tabs-pane is-active">Tab Content 2</div>
</div>
</div>
jQuery
jQuery(function($){
$('.mk-tabs').on('click', 'a', function(e){
e.preventDefault();
var currentTab = $(this).closest('.mk-tabs-tab');
currentTab.toggleClass('is-active');
//if (currentTab.hasClass('is-active')) console.log('on');
//else console.log('off');
if ( currentTab.hasClass('is-active') ) {
$('.mk-tabs .mk-tabs-panes .mk-tabs-pane').toggleClass('is-active');
}
});
});
</script>
jQuery(document).ready(function($){
$('.mk-tabs ul li a').click( function(){
if($($(this).parent()).hasClass("is-active")){
$($(this).parent()).removeClass("is-active")
}
else
{
$(".mk-tabs-tab").each(function(){
$(this).removeClass("is-active")
})
if(!$($(this).parent()).hasClass("is-active"))
$($(this).parent()).addClass("is-active")
}
});
});
.mk-tabs{
display:flex
}
.is-active{
background-color:red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mk-tabs">
<ul>
<li class="mk-tabs-tab">Tab 1</li>
<li class="mk-tabs-tab is-active">Tab 2</li>
<li class="mk-tabs-tab">Tab 3</li>
<li class="mk-tabs-tab">Tab 4</li>
</ul>
</div>
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%");
}
I am having trouble correctly toggling classes in my tab list using javascript.
At first click the menu is open and on second click on the same will close, but after close will not open again if I click on the same menu.
Check my example to see exactly what I mean:
var prev = '';
var tabsList = document.querySelectorAll('.main-col');
for (i = 0; i < tabsList.length; ++i) {
tabsList[i].addEventListener("click", function(){
var elements = document.getElementsByClassName('main-col');
for (j = 0; j < elements.length; ++j) {
elements[j].classList.remove("open");
}
var index = this.dataset.foo;
document.querySelectorAll('[data-foo="' + index + '"]')[0].classList.toggle("open");
if ( prev == this) {
this.classList.remove("open");
}
prev = this;
});
}
h3 {
cursor: pointer;
}
.main-col .menu {
max-height: 0;
overflow: hidden;
transition: max-height .5s cubic-bezier(0, 1, 0, 1);
}
.main-col.open .menu {
background: #333;
max-height: 500px;
transition: max-height .5s ease-in-out;
}
<div id="f-col1" class="main-col" data-foo="1">
<h3 class="title-col1">Column 1 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-1">
<ul id="column-1-container" class="menu">
<li id="menu-item-1" class="menu-item">LINK 1</li>
<li id="menu-item-1" class="menu-item">LINK 1</li>
<li id="menu-item-1" class="menu-item">LINK 1</li>
</ul>
</div>
</div>
<div id="f-col2" class="main-col" data-foo="2">
<h3 class="title-col2">Column 2 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-2">
<ul id="column-2-container" class="menu">
<li id="menu-item-2" class="menu-item">LINK 2</li>
<li id="menu-item-2" class="menu-item">LINK 2</li>
<li id="menu-item-2" class="menu-item">LINK 2</li>
</ul>
</div>
</div>
<div id="f-col3" class="main-col" data-foo="3">
<h3 class="title-col3">Column 3 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-3">
<ul id="column-3-container" class="menu">
<li id="menu-item-3" class="menu-item">LINK 3</li>
<li id="menu-item-3" class="menu-item">LINK 3</li>
<li id="menu-item-3" class="menu-item">LINK 3</li>
</ul>
</div>
</div>
PS: Please don't give me alternatives with jQuery to this little problem. :)
You could achieve this by the following:
// Iterate each tab (main-col) that the toggle behaviour is applied to
document.querySelectorAll('.main-col').forEach(function(tabItem) {
// Add click event listener to current tab to process toggle logic
tabItem.addEventListener("click", function() {
// Use the toggle method to toggle open class on and off
tabItem.classList.toggle('open');
// Select any currently open tabs, and remove the open class from tabs
// that are not the tab we're currently toggling
document.querySelectorAll('.main-col.open').forEach(function(openTabItem) {
if(openTabItem !== tabItem) {
openTabItem.classList.remove('open');
}
});
})
})
h3 {
cursor: pointer;
}
.main-col .menu {
max-height: 0;
overflow: hidden;
transition: max-height .5s cubic-bezier(0, 1, 0, 1);
}
.main-col.open .menu {
background: #333;
max-height: 500px;
transition: max-height .5s ease-in-out;
}
<div id="f-col1" class="main-col" data-foo="1">
<h3 class="title-col1">Column 1 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-1">
<ul id="column-1-container" class="menu">
<li id="menu-item-1" class="menu-item">LINK 1</li>
<li id="menu-item-1" class="menu-item">LINK 1</li>
<li id="menu-item-1" class="menu-item">LINK 1</li>
</ul>
</div>
</div>
<div id="f-col2" class="main-col" data-foo="2">
<h3 class="title-col2">Column 2 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-2">
<ul id="column-2-container" class="menu">
<li id="menu-item-2" class="menu-item">LINK 2</li>
<li id="menu-item-2" class="menu-item">LINK 2</li>
<li id="menu-item-2" class="menu-item">LINK 2</li>
</ul>
</div>
</div>
<div id="f-col3" class="main-col" data-foo="3">
<h3 class="title-col3">Column 3 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-3">
<ul id="column-3-container" class="menu">
<li id="menu-item-3" class="menu-item">LINK 3</li>
<li id="menu-item-3" class="menu-item">LINK 3</li>
<li id="menu-item-3" class="menu-item">LINK 3</li>
</ul>
</div>
</div>
IE11 solution, with no polyfill (forEach)...
let FcolsParent = document.getElementById("Parent_of_f-cols");
FcolsParent.onclick = function(e) {
if (!e.target.matches('h3')) return;
e.stopPropagation();
let
isOpen = e.target.parentNode.classList.contains('open'),
Open_Tabs = FcolsParent.querySelectorAll('.main-col.open')
;
for( let i=0, iMax=Open_Tabs.length; i<iMax; i++ ) {
Open_Tabs[i].classList.remove('open');
}
if (!isOpen) e.target.parentNode.classList.add('open');
}
h3 {
cursor: pointer;
}
.main-col .menu {
max-height: 0;
overflow: hidden;
transition: max-height 1.5s cubic-bezier(0, 1, 0, 1);
/* transition: max-height 1.5s ease-in-out; */
}
.main-col.open .menu {
background: #333;
max-height: 500px;
transition: max-height 1.5s ease-in-out;
}
<div id="Parent_of_f-cols">
<div id="f-col1" class="main-col" data-foo="1">
<h3 class="title-col1">Column 1 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-1">
<ul id="column-1-container" class="menu">
<li id="menu-item-1" class="menu-item">LINK 1</li>
<li id="menu-item-1" class="menu-item">LINK 1</li>
<li id="menu-item-1" class="menu-item">LINK 1</li>
</ul>
</div>
</div>
<div id="f-col2" class="main-col" data-foo="2">
<h3 class="title-col2">Column 2 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-2">
<ul id="column-2-container" class="menu">
<li id="menu-item-2" class="menu-item">LINK 2</li>
<li id="menu-item-2" class="menu-item">LINK 2</li>
<li id="menu-item-2" class="menu-item">LINK 2</li>
</ul>
</div>
</div>
<div id="f-col3" class="main-col" data-foo="3">
<h3 class="title-col3">Column 3 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-3">
<ul id="column-3-container" class="menu">
<li id="menu-item-3" class="menu-item">LINK 3</li>
<li id="menu-item-3" class="menu-item">LINK 3</li>
<li id="menu-item-3" class="menu-item">LINK 3</li>
</ul>
</div>
</div>
</div>
what about if a click will happen on one of your link ?
actually this remove too your ".open" class
let FcolsParent = document.getElementById("Parent_of_f-cols");
FcolsParent.onclick = function(e) {
if (!e.target.matches('h3')) return;
e.stopPropagation();
let isOpen = e.target.parentNode.classList.contains('open');
FcolsParent.querySelectorAll('.main-col.open').forEach( openTabItem=>openTabItem.classList.remove('open') );
if (!isOpen) e.target.parentNode.classList.add('open');
}
h3 {
cursor: pointer;
}
.main-col .menu {
max-height: 0;
overflow: hidden;
transition: max-height 1.5s cubic-bezier(0, 1, 0, 1);
}
.main-col.open .menu {
background: #333;
max-height: 500px;
transition: max-height 1.5s ease-in-out;
}
<div id="Parent_of_f-cols">
<div id="f-col1" class="main-col" data-foo="1">
<h3 class="title-col1">Column 1 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-1">
<ul id="column-1-container" class="menu">
<li id="menu-item-1" class="menu-item">LINK 1</li>
<li id="menu-item-1" class="menu-item">LINK 1</li>
<li id="menu-item-1" class="menu-item">LINK 1</li>
</ul>
</div>
</div>
<div id="f-col2" class="main-col" data-foo="2">
<h3 class="title-col2">Column 2 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-2">
<ul id="column-2-container" class="menu">
<li id="menu-item-2" class="menu-item">LINK 2</li>
<li id="menu-item-2" class="menu-item">LINK 2</li>
<li id="menu-item-2" class="menu-item">LINK 2</li>
</ul>
</div>
</div>
<div id="f-col3" class="main-col" data-foo="3">
<h3 class="title-col3">Column 3 with sub-menu (1st click open, 2nd close and from now on will not open)</h3>
<div class="column-3">
<ul id="column-3-container" class="menu">
<li id="menu-item-3" class="menu-item">LINK 3</li>
<li id="menu-item-3" class="menu-item">LINK 3</li>
<li id="menu-item-3" class="menu-item">LINK 3</li>
</ul>
</div>
</div>
</div>
I wonder if users click "test 1" will add class active in sidebar anchor and add background to expand list "#bar1".
the result should be sidebar font will red, and expand list background will red
But,what I found here if I click "test 1" it wont add class to anchor.
Please is there anyone can help me to correct my code
$(document).ready(function(){
$('.sidebar li a').click(function(e){
e.preventDefault();
$(this).addClass('active');
$(this).removeClass('active');
var exId=$(this).attr('href');
$(exId).addClass('expandBg');
$(exId).siblings().removeClass('expandBg')
})
});
a.active{
text-decoration: none;
color: #f00;
}
.expandBg{
background-color:#f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidebar">
<ul>
<li>test 1</li>
<li>test 2</li>
<li>test 3</li>
<li>test 4</li>
</ul>
</div>
<div class="expand">
<ul>
<li id="bar1">bar1</li>
<li id="bar2">bar2</li>
<li id="bar3">bar3</li>
<li id="bar4">bar4</li>
</ul>
</div>
this line of code $(this).removeClass('active'); make an issue we want to remove active class from siblings anchor tag please find below snippet to know how to do that
$(document).ready(function(){
$('.sidebar li a').click(function(e){
e.preventDefault();
debugger;
$(this).addClass('active');
$(this).parent().siblings().find("a").removeClass("active")
var exId=$(this).attr('href');
$(exId).addClass('expandBg');
$(exId).siblings().removeClass('expandBg')
})
});
a.active{
text-decoration: none;
color: #f00;
}
.expandBg{
background-color:#f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidebar">
<ul>
<li>test 1</li>
<li>test 2</li>
<li>test 3</li>
<li>test 4</li>
</ul>
</div>
<div class="expand">
<ul>
<li id="bar1">bar1</li>
<li id="bar2">bar2</li>
<li id="bar3">bar3</li>
<li id="bar4">bar4</li>
</ul>
</div>
Here's a question on how to center a <select> scroll bar to the selected item.
I'd like to find a way to do the same thing for a Bootstrap Dropdown Menu so that the menu automatically scrolls to the .active list item.
Here's some code:
<ul>
<li class="dropdown switch">
<a href="active" class="dropdown-toggle" data-toggle="dropdown" id="switch-a">
<span>Name</span>
</a>
<ul class="dropdown-menu switch-items" id="switch-dd">
<li>...</li>
<li>...</li>
<li class="active active-dd"></li>
.
.
.
<li>...</li>
</ul>
</li>
</ul>
Is this possible or do I have to a HTML <select> and spending time styling it?
Not only is it possible, it's actually much easier to deal with native HTML objects than it is to deal with the mysteries and inconsistencies of styling the <select> element.
You just have to listen to the dropdown open event with shown.bs.dropdown.
Once it's open, just find the only .active item and call .focus() to bring it into view.
Like This:
$(".dropdown").on("shown.bs.dropdown", function() {
$(this).find(".dropdown-menu li.active a").focus()
});
Demo in Stack Snippets:
$(".dropdown.focus-active").on("shown.bs.dropdown", function() {
$(this).find(".dropdown-menu li.active a").focus()
});
.scrollable-menu {
height: auto;
max-height: 200px;
overflow-x: hidden;
}
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script>
<div class="container" >
<div class="dropdown focus-active">
<a href="#" class="btn btn-primary"
data-target="#" data-toggle="dropdown"
aria-haspopup="true" role="button" aria-expanded="false">
Dropdown trigger
<span class="caret"></span>
</a>
<ul class="dropdown-menu scrollable-menu" role="menu" aria-labelledby="dLabel">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li class="active">Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
</ul>
</div>
</div>
Event handler without jquery:
const activeOptionCollection = document.getElementsByClassName('active');
if (activeOptionCollection.length > 0) {
const [activeOption] = activeOptionCollection;
activeOption.scrollIntoView();
}