Change index of clicked element - javascript

I want to center clicked list element (so, for example, If I click the very left one then it moves to the middle, replacing the current middle element).
So I thought that maybe switching the indexes of current "active" and clicked element might be worth a shot. I couldn't change the index value of element though.
The best solution is to change index of every list element so they will keep some logical order and center the clicked one.
I am beginner in JS so I am aware that there is probably better way of doing it so I'm open for suggestions. ;)
So, two solutions I was thinking about:
It replaces its place with the clicked element. For example:
1 - 2 - 3 - 4 - 5
3 is middle and I click 5
The new order : 1 - 2 - 5 - 4 - 3
It moves every element of the list. For example:
1 - 2 - 3 - 4 - 5
3 is middle and I click 5
The new order : 3 - 4 - 5 - 1 - 2
Here is codepen: http://codepen.io/anon/pen/wMOZVd
function horizontalSlider() {
var sliderElement = $('.horizontal-slider ul li');
var active = $('.horizontal-slider .active');
var activeIndex = active.index();
var center = Math.floor(sliderElement.length / 4);
sliderElement.click(function() {
var thisElement = $(this).index();
var newActive = $('.horizontal-slider .active');
var newActiveIndex = newActive.index();
if (thisElement == newActiveIndex) {
$(this).addClass('active').children().addClass('active-sub');
} else {
$(this).addClass('active').children().addClass('active-sub');
newActive.removeClass('active').children().removeClass('active-sub');
}
});
}
horizontalSlider();
.horizontal-slider {
text-align: center;
width: 100%;
margin: 0 auto;
}
.horizontal-slider ul {
display: inline-block;
text-transform: uppercase;
font-size: 2rem;
width: 100%;
}
.horizontal-slider ul li {
padding: 3%;
cursor: pointer;
}
.horizontal-slider ul ul {
display: none;
}
.active {
transition: all .5s ease;
font-weight: 900;
position: relative;
transform: scale(1.25);
}
.active-sub {
top: 70%;
left: 1%;
display: block !important;
position: absolute;
}
.active-sub li {
text-transform: none;
font-size: 0.9rem;
font-weight: 500;
}
li {
list-style: none;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="horizontal-slider relative">
<ul>
<li>Mar 16
<ul>
<li>Lorem ips</li>
</ul>
</li>
<li>Apr 04
<ul>
<li>Lorem ips</li>
</ul>
</li>
<li>May 22
<ul>
<li>Lorem ips</li>
</ul>
</li>
<li class="active">Jun 30
<ul class="active-sub">
<li>Lorem ips</li>
</ul>
</li>
<li>Jul 12
<ul>
<li>Lorem ips</li>
</ul>
</li>
<li>Aug 15
<ul>
<li>Lorem ips</li>
</ul>
</li>
<li>Sep 03
<ul>
<li>Lorem ips</li>
</ul>
</li>
</ul>
</div>

Because you want to remove the node and insert it to other place, you need to use animation instead of transition.
Let me know if something is not clear.
function horizontalSlider() {
var sliderElement = $('.horizontal-slider ul li');
var active = $('.horizontal-slider .active');
var activeIndex = active.index();
var center = Math.floor(sliderElement.length / 4);
sliderElement.click(function() {
var elem = $(this);
var thisElement = elem.index();
var newActive = $('.horizontal-slider .active');
var newActiveIndex = newActive.index();
if (thisElement == newActiveIndex) {
elem.addClass('active').children().addClass('active-sub');
} else {
elem.addClass('active').children().addClass('active-sub');
console.log(thisElement < 3);
var middle = $('.horizontal-slider>ul>li:nth-child(' + (thisElement < 3 ? '4' : '3') + ')');
$(this).insertAfter(middle);
newActive.removeClass('active').children().removeClass('active-sub');
}
});
}
horizontalSlider();
.horizontal-slider {
text-align: center;
width: 100%;
margin: 0 auto;
}
.horizontal-slider ul {
display: inline-block;
text-transform: uppercase;
font-size: 2rem;
width: 100%;
}
.horizontal-slider ul li {
padding: 3%;
cursor: pointer;
}
.horizontal-slider ul ul {
display: none;
}
.active {
animation: active .5s ease forwards;
}
.active-sub {
top: 70%;
left: 1%;
display: block !important;
position: absolute;
}
.active-sub li {
text-transform: none;
font-size: 0.9rem;
font-weight: 500;
}
li {
list-style: none;
display: inline-block;
}
#keyframes active {
to {
font-weight: 900;
position: relative;
transform: scale(1.25);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="horizontal-slider relative">
<ul>
<li>Mar 16
<ul>
<li>Lorem ips</li>
</ul>
</li>
<li>Apr 04
<ul>
<li>Lorem ips</li>
</ul>
</li>
<li>May 22
<ul>
<li>Lorem ips</li>
</ul>
</li>
<li class="active">Jun 30
<ul class="active-sub">
<li>Lorem ips</li>
</ul>
</li>
<li>Jul 12
<ul>
<li>Lorem ips</li>
</ul>
</li>
<li>Aug 15
<ul>
<li>Lorem ips</li>
</ul>
</li>
<li>Sep 03
<ul>
<li>Lorem ips</li>
</ul>
</li>
</ul>
</div>

Ok, So i changed some things and added a div to each text element so you can edit it individually
Now Everything will come in the center.
See the Pen:
http://codepen.io/anon/pen/dGrBRJ
code` function horizontalSlider() {
var sliderElement = $('.horizontal-slider ul li');
sliderElement.click(function() {
var active = $('.horizontal-slider .active .t1');
var t1 = active.text();
var t3 = $('.horizontal-slider .active').find(".t3").text();
var thisElement = $(this);
var t2 = thisElement.children(".t2").text();
var t4 = thisElement.find(".t4").text();
thisElement.children(".t2").text(t1);
thisElement.find(".t4").text(t3);
active.text(t2);
$('.horizontal-slider .active .t3').text(t4);
});
}
horizontalSlider();`

What You can do is instead of switching the styles,you can switch the text in Them.
It can be easily done by getting the by using:
(".whateverElement").html();
Then Swap it

Related

The script activates only the main menu items. How to make the code apply to sub-items

The script activates only the main menu items. How to make the code apply to sub-items. 2.1 - 2.2 And other subparagraphs if they exist. I can’t understand how to select all li elements including those embedded in each other.
Please help me finish the code, or maybe someone has a similar script with the same functionality.
var lastId,
topMenu = $("#top-menu"),
topMenuHeight = topMenu.outerHeight() + 15,
// All list items
menuItems = topMenu.find(".scroll-to"),
// Anchors corresponding to menu items
scrollItems = menuItems.map(function() {
var item = $($(this).attr("href"));
if (item.length) {
return item;
}
});
// Bind to scroll
$(window).scroll(function() {
// Get container scroll position
var fromTop = $(this).scrollTop() + topMenuHeight;
// Get id of current scroll item
var cur = scrollItems.map(function() {
if ($(this).offset().top < fromTop)
return this;
});
// Get the id of the current element
cur = cur[cur.length - 1];
var id = cur && cur.length ? cur[0].id : "";
if (lastId !== id) {
lastId = id;
// Set/remove active class
menuItems
.parent().removeClass("active")
.end().filter("[href='#" + id + "']").parent().addClass("active");
}
});
body {
height: 6000px;
font-family: Helvetica, Arial;
}
#top-menu {
position: fixed;
z-index: 1;
background: white;
left: 0;
right: 0;
top: 50px;
}
#top-menu li {
float: left;
}
#top-menu a {
display: block;
padding: 5px 25px 7px 25px;
width: 4em;
text-align: center;
-webkit-transition: .5s all ease-out;
-moz-transition: .5s all ease-out;
transition: .5s all ease-out;
border-top: 3px solid white;
color: #aaa;
text-decoration: none;
}
#top-menu a:hover {
color: #000;
}
#top-menu li.active > a {
border-top: 3px solid #333;
color: #333;
}
#zod{
height:400px;
}
#foo{
height:400px;
}
#foo2.1{
height:400px;
display:block
}
#foo2.2{
height:400px;
display:block
}
#bar {
height:400px;
}
#baz {
height:400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="top-menu">
<li>
<a class="scroll-to" href="#zod">zod</a>
</li>
<li>
<a class="scroll-to" href="#foo">Foo</a>
<ul class="articleSubList">
<li><a class="scroll-to" href="#foo2.1">foo 1.1</a></li>
<li><a class="scroll-to" href="#foo2.2">foo 2.2</a></li>
</ul>
</li>
<li>
<a class="scroll-to" href="#bar">Bar</a>
</li>
<li>
<a class="scroll-to" href="#baz">Baz</a>
</li>
</ul>
<div id="zod">Zod</div>
<div id="foo">Foo111</div>
<div id="foo2.1">Foo 1.1</div>
<div id="foo2.2">Foo 1.2</div>
<div id="bar">Bar</div>
<div id="baz">Baz</div>

Adjacent sibling selector element.querySelector("+element") is invalid

This simple code will work:
<!DOCTYPE html>
<html>
<body>
<br>
<div>
Link 1
Link 2
Link 3
Link 4
</div>
Link 1 <span>color me plz!</span>
<br><br>
<div>
Link 1
Link 2
Link 3
Link 4
</div>
Link 1 <span>color me plz!</span>
Link 2 <span>color me plz!</span>
<script>
testing = document.querySelectorAll("div + a");
for (let i = 0; i < testing.length; i++){
testing[i].addEventListener("mouseenter", function(){
const x = testing[i];
x.style.backgroundColor = "cyan";
x.querySelector("span").style.backgroundColor = "pink";
});
}
</script>
</body>
</html>
But my real problem is this:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style-test.css">
</head>
<body>
<nav>
<div>
Menu A.1
Menu A.2
</div>
<div class="right">
<div>
Menu B.1
<ul>
<li>B.1 Sub 1</li>
<li>B.1 Sub 2</li>
</ul>
</div>
<div>
Menu B.2
<ul>
<li>B.2 Sub 1</li>
<li>B.2 Sub 2</li>
</ul>
</div>
<div>
Menu B.3
<ul>
<li>B.3 Sub 1 Test Longer Text</li>
<li>B.3 Sub 2</li>
</ul>
</div>
<div>
Menu B.4
<ul>
<li>B.4 Sub 1</li>
<li>B.4 Sub 2</li>
</ul>
</div>
</div>
</nav>
<div style="float: left; margin-top: 1000px"></div>
<script>
const menu = document.querySelectorAll("nav div > a");
console.log("Get all menu:");
console.log(menu);
for (let i = 0; i < menu.length; i++) {
menu[i].addEventListener("mouseenter", function(){
console.log("mouseEnter");
console.log("menu[i].addEventListener:");
console.log(menu[i]);
//console.log(menu[i].querySelector("+ ul"));
const subMenu = menu[i].querySelector(` + ul`);
/* ^^^ The problem is here above ^^^ --- Everything stops here */
console.log("OK! 'querySelector' is valid"); //<-- this won't display...
//if(window.getComputedStyle(subMenu).getPropertyValue("display") === "block") /*Corrected*/
if(subMenu.style.display === "block")
{
console.log("subMenu.style.display === block");
const subMenuBox = subMenu.getBoundingClientRect();
const posX = (subMenuBox.left + subMenuBox.width) - window.innerWidth;
if(posX > 0)
subMenu.style.left = (-posX - 20) + "px";
/*padding problem (need -20): didn't .getBoundingClientRect() include padding?*/
// /*or just*/ subMenu.style.right = "0px";
console.log("When here successfully!");
}
else{
console.log("Failed...");
}
})
}
</script>
</body>
</html>
css:
body{
color: #fff;
font-size: 20px;
background: #999;
margin: 0;
}
a{
color: #cfc;
}
nav, nav div > a, nav div{
float: left;
}
nav{
width: 100%;
background: #4169E1;
white-space: nowrap;
}
nav div{
margin: 0em 0.2em;
}
nav div:first-child{
margin-left: 0;
}
nav div div{
position: relative;
margin: 0;
}
nav a{
color: #cff;
display: block;
font-weight: 600;
text-decoration: none;
padding: 0.5em 1em;
}
nav a:hover{
color: #fff;
background: #f90;
}
nav div > a + ul{
position: absolute;
top: 2.15em;
float: left;
background: #666;
list-style-type: none;
margin: 0;
padding: 0;
min-width: 180px;
display: none;
}
nav div:hover > a + ul{
display: block;
}
.right{
float: right;
}
I just want to get the sibling of <a> just next to it, the <ul> after <a>, which is a + ul in css
<div>
Menu B.1
<ul>
<li>B.1 Sub 1</li>
<li>B.1 Sub 2</li>
</ul>
</div>
Focus here:
<script>
const menu = document.querySelectorAll("nav div > a");
for (let i = 0; i < menu.length; i++) {
menu[i].addEventListener("mouseenter", function(){
//Problem is here...
const subMenu = menu[i].querySelector(" + ul");
/*Corrected*/
//if(window.getComputedStyle(subMenu).getPropertyValue("display") === "block")
if(subMenu != null && subMenu.style.display === "block")
{
const subMenuBox = subMenu.getBoundingClientRect();
const posX = (subMenuBox.left + subMenuBox.width) - window.innerWidth;
if(posX > 0)
subMenu.style.left = (-posX -20) + "px";
/*padding problem (need -20): didn't .getBoundingClientRect() include
padding?*/
// /*or just*/ subMenu.style.right = "0px";
}
})
}
</script>
Now, what I done here:
First, I select all the <a> inside <nav>.
Then using for() loop and put mouseenter event to all the selected <a>.
When user hover over the <a>, the mouseenter know exactly which <a> was hover.
Now here's the problem: I want to select the a + ul of hovered <a>.
I have tried this:
console.log(document.querySelector("menu[i] + ul"));
gives me a null value
console.log(document.querySelector(menu[i] + " + ul"));
gives me SyntaxError: 'file:///C:/Users/path/path/thisPage.html + ul' is not a valid selector
console.log(menu[i].querySelector(" + ul"));
gives me SyntaxError: '+ul' is not a valid selector
How can I fix this? What is the right thing to do with .querySelector() for continuing selection but with adjacent sibling tag?
On one hand, on non-ancient browsers, you can use :scope to indicate the element on which the querySelector is being called on. But querySelector will only select elements which are children of the current element, and the <ul> you want is a sibling.
Take the nextElementSibling of the element instead, check that it exists, and check that it's a ul instead:
for (const menu of document.querySelectorAll("nav div > a")) {
menu.addEventListener("mouseenter", function() {
console.log(menu, menu.nextElementSibling);
const subMenu = menu.nextElementSibling;
if (!subMenu || !subMenu.matches('ul')) {
return;
}
if (subMenu.style.display === "block") {
console.log("subMenu.style.display === block");
const subMenuBox = subMenu.getBoundingClientRect();
const posX = (subMenuBox.left + subMenuBox.width) - window.innerWidth;
subMenu.style.left = -posX;
console.log("When here successfully!");
} else {
console.log("Failed...");
}
})
}
body {
color: #fff;
font-size: 20px;
background: #999;
margin: 0;
}
a {
color: #cfc;
}
nav,
nav div>a,
nav div {
float: left;
}
nav {
width: 100%;
background: #4169E1;
white-space: nowrap;
}
nav div {
margin: 0em 0.2em;
}
nav div:first-child {
margin-left: 0;
}
nav div div {
position: relative;
margin: 0;
}
nav a {
color: #cff;
display: block;
font-weight: 600;
text-decoration: none;
padding: 0.5em 1em;
}
nav a:hover {
color: #fff;
background: #f90;
}
nav div>a+ul {
position: absolute;
top: 2.15em;
float: left;
background: #666;
list-style-type: none;
margin: 0;
padding: 0;
min-width: 180px;
display: none;
}
nav div:hover>a+ul {
display: block;
}
.right {
float: right;
}
<nav>
<div>
Menu A.1
Menu A.2
</div>
<div class="right">
<div>
Menu B.1
<ul>
<li>B.1 Sub 1</li>
<li>B.1 Sub 2</li>
</ul>
</div>
<div>
Menu B.2
<ul>
<li>B.2 Sub 1</li>
<li>B.2 Sub 2</li>
</ul>
</div>
<div>
Menu B.3
<ul>
<li>B.3 Sub 1 Test Longer Text</li>
<li>B.3 Sub 2</li>
</ul>
</div>
<div>
Menu B.4
<ul>
<li>B.4 Sub 1</li>
<li>B.4 Sub 2</li>
</ul>
</div>
</div>
</nav>
<div style="float: left; margin-top: 1000px "></div>
Because not all menus have sub-menus, you do need to test if the UL exists first before trying to do stuff with it.
Note that subMenu.style.display === "block" is never fulfilled in the given code because the <ul>s don't have style properties directly on the elements. If they did, the test would succeed. If you're trying to see if they currently are being displayed, use window.getComputedStyle instead:
for (const menu of document.querySelectorAll("nav div > a")) {
menu.addEventListener("mouseenter", function() {
console.log(menu, menu.nextElementSibling);
const subMenu = menu.nextElementSibling;
if (!subMenu || !subMenu.matches('ul')) {
return;
}
if (window.getComputedStyle(subMenu).display === "block") {
console.log("subMenu.style.display === block");
const subMenuBox = subMenu.getBoundingClientRect();
const posX = (subMenuBox.left + subMenuBox.width) - window.innerWidth;
subMenu.style.left = -posX;
console.log("When here successfully!");
} else {
console.log("Failed...");
}
})
}
body {
color: #fff;
font-size: 20px;
background: #999;
margin: 0;
}
a {
color: #cfc;
}
nav,
nav div>a,
nav div {
float: left;
}
nav {
width: 100%;
background: #4169E1;
white-space: nowrap;
}
nav div {
margin: 0em 0.2em;
}
nav div:first-child {
margin-left: 0;
}
nav div div {
position: relative;
margin: 0;
}
nav a {
color: #cff;
display: block;
font-weight: 600;
text-decoration: none;
padding: 0.5em 1em;
}
nav a:hover {
color: #fff;
background: #f90;
}
nav div>a+ul {
position: absolute;
top: 2.15em;
float: left;
background: #666;
list-style-type: none;
margin: 0;
padding: 0;
min-width: 180px;
display: none;
}
nav div:hover>a+ul {
display: block;
}
.right {
float: right;
}
<nav>
<div>
Menu A.1
Menu A.2
</div>
<div class="right">
<div>
Menu B.1
<ul>
<li>B.1 Sub 1</li>
<li>B.1 Sub 2</li>
</ul>
</div>
<div>
Menu B.2
<ul>
<li>B.2 Sub 1</li>
<li>B.2 Sub 2</li>
</ul>
</div>
<div>
Menu B.3
<ul>
<li>B.3 Sub 1 Test Longer Text</li>
<li>B.3 Sub 2</li>
</ul>
</div>
<div>
Menu B.4
<ul>
<li>B.4 Sub 1</li>
<li>B.4 Sub 2</li>
</ul>
</div>
</div>
</nav>
<div style="float: left; margin-top: 1000px "></div>

Adding more button for <ul> in responsive navigation - Angular

I have a navigation of 8 items (li), and when resolution gets smaller items drop in a new line. I need to make it so that when an item doesn't fit on a navigation anymore it should put a "MORE" dropdown button on the right side of nav and put the item that doesn't fit in a dropdown.
I don't know how I can do it with the Angular project, I don't need JQuery code.
This is my code:
<div id="mainMenu" class="main-menu">
<ul id="autoNav" class="main-nav">
<li>
home
</li>
<li>
about us
</li>
<li>
portfolio
</li>
<li>
team
</li>
<li>
blog
</li>
<li>
contact
</li>
<li id="autoNavMore" class="auto-nav-more">
more
<ul id="autoNavMoreList" class="auto-nav-more-list">
<li>
policy
</li>
</ul>
</li>
</ul>
</div>
Javascript Code:
const $mainMenu = $("#mainMenu");
const $autoNav = $("#autoNav");
const $autoNavMore = $("#autoNavMore");
const $autoNavMoreList = $("#autoNavMoreList");
autoNavMore = () => {
let childNumber = 2;
if($(window).width() >= 320) {
// GET MENU AND NAV WIDTH
const $menuWidth = $mainMenu.width();
const $autoNavWidth = $autoNav.width();
if($autoNavWidth > $menuWidth) {
// CODE FIRES WHEN WINDOW SIZE GOES DOWN
$autoNav.children(`li:nth-last-child(${childNumber})`).prependTo($autoNavMoreList);
autoNavMore();
} else {
// CODE FIRES WHEN WINDOW SIZE GOES UP
const $autoNavMoreFirst = $autoNavMoreList.children('li:first-child').width();
// CHECK IF ITEM HAS ENOUGH SPACE TO PLACE IN MENU
if(($autoNavWidth + $autoNavMoreFirst) < $menuWidth) {
$autoNavMoreList.children('li:first-child').insertBefore($autoNavMore);
}
}
if($autoNavMoreList.children().length > 0) {
$autoNavMore.show();
childNumber = 2;
} else {
$autoNavMore.hide();
childNumber = 1;
}
}
}
// INIT
autoNavMore();
$(window).resize(autoNavMore);
CSS Code:
.main-menu {
max-width: 800px;
}
.main-nav {
display: inline-flex;
padding: 0;
list-style: none;
}
.main-nav li a {
padding: 10px;
text-transform: capitalize;
white-space: nowrap;
font-size: 30px;
font-family: sans-serif;
text-decoration: none;
}
.more-btn {
color: red;
}
.auto-nav-more {
position: relative;
}
.auto-nav-more-list {
position: absolute;
right: 0;
opacity: 0;
visibility: hidden;
transition: 0.2s;
text-align: right;
padding: 0;
list-style: none;
background: grey;
border-radius: 4px;
}
.auto-nav-more:hover .auto-nav-more-list {
opacity: 1;
visibility: visible;
}
Any help to how I can do it with the Angular project (Typescript)?.
You can use the ng-repeat-start (ngRepeat directive)
https://docs.angularjs.org/api/ng/directive/ngRepeat
Example
<header ng-repeat-start="item in items">
Header {{ item }}
</header>
<div class="body">
Body {{ item }}
</div>
<footer ng-repeat-end>
Footer {{ item }}
</footer>

Clicking Child Component closes the list that is opened

I have implemented a menu example where when i click on parent menu link all the child elements are visible inside them and when i click on any of the child element it collapses...I have made a demo here http://codepen.io/anon/pen/KzpKrm ...When i click on child link i want the list to be opened like that only and indicate that this link has been selected...Somebody please help
function showmenu(elem) {
// Clear any currently open menu
var openMenu = document.getElementById("activeMenu");
if (openMenu) {
openMenu.removeAttribute("id");
// Stop if we're just closing the current menu
if (openMenu === elem) {
return;
}
}
// Only apply it if the element actually has LI child nodes.
// OPTIONAL: Will still work without if statement.
if (elem.getElementsByTagName("li").length > 0) {
elem.setAttribute("id", "activeMenu");
}
}
Well you can add event.stopPropagation() to the nested ul:
<ul id="nav">
<li onclick="showmenu(this)" class="sectionMenu">
Service
<ul onclick="event.stopPropagation()">
<li><a> Ro </a> </li>
<li> <a>List</a> </li>
<li><a>Service Plan</a> </li>
</ul>
</li>
....
</ul>
You could check if the actual element clicked is a parent (i.e. has class sectionMenu). If not then return.
You can do this by adding the following code to your javascript:
// Checks if element clicked has class sectionMenu. Otherwise return.
var $elementClicked = event.target;
if ($elementClicked.className != 'sectionMenu')
return;
CodePen
function showmenu(elem) {
// Checks if element clicked has class sectionMenu. Otherwise return.
var $elementClicked = event.target;
if ($elementClicked.className != 'sectionMenu')
return;
// Clear any currently open menu
var openMenu = document.getElementById("activeMenu");
if (openMenu) {
openMenu.removeAttribute("id");
// Stop if we're just closing the current menu
if (openMenu === elem) {
return;
}
}
// Only apply it if the element actually has LI child nodes.
// OPTIONAL: Will still work without if statement.
if (elem.getElementsByTagName("li").length > 0) {
elem.setAttribute("id", "activeMenu");
}
}
img {
padding-left: 5px;
}
#nav {
height: 100%;
padding: 20px;
cursor: pointer;
border: 3px solid #3e4547;
box-shadow: 2px 2px 8px #000000;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
ul {
width: 200px;
list-style: none;
margin: 0;
padding: 5px;
}
ul li {
display: block;
padding: 0 10px;
overflow: hidden;
padding: 5px;
}
ul ul {
display: none;
}
ul ul li {
float: none;
user-select: #b6ff00;
}
#activeMenu ul {
display: block;
}
ul li:hover {
background-color: #bcbdc1;
}
ul ul li:hover {
background-color: red;
}
.arrow {
background-image: url("./png/2.png");
transition: 0.3s;
transform: rotateX(-180deg);
}
li.sectionMenu:before {
content: '\2795';
font-size: 13px;
color: #777;
float: right;
margin-left: 5px;
}
li.sectionMenu#activeMenu:before {
content: "\2796";
}
<div>
<ul id="nav">
<li onclick="showmenu(this)" class="sectionMenu">
Service
<ul>
<li><a> Ro </a>
</li>
<li> <a>List</a>
</li>
<li><a>Service Plan</a>
</li>
</ul>
</li>
<li onclick="showmenu(this)" class="sectionMenu">
Customer
<ul>
<li>New Customer</li>
<li>customer List</li>
</ul>
</li>
<li onclick="showmenu(this)" class="sectionMenu">
Parts
<ul>
<li>New Part</li>
<li>Parts List</li>
</ul>
</li>
<li onclick="showmenu(this)" class="sectionMenu">
Admin
<ul>
<li>New Employee</li>
<li>Employee List</li>
<li>Employee Roles</li>
<li>Employee Work Schedulee</li>
<li>Holidays</li>
<li>Employee List</li>
</ul>
</li>
</ul>
</div>
Even U could try this....Remember to pass event argument for the onclick handlers
function showmenu(elem,event) {
// Clear any currently open menu
event.preventDefault();
// alert(event.currentTarget.getAttribute("id"))
var openMenu = document.getElementById("activeMenu");
if (openMenu) {
if(openMenu.children[0]==event.target.parentNode)
return;
openMenu.removeAttribute("id");
// Stop if we're just closing the current menu
if (openMenu === elem) {
return;
}
}
// Only apply it if the element actually has LI child nodes.
// OPTIONAL: Will still work without if statement.
if (elem.getElementsByTagName("li").length > 0) {
event.currentTarget.setAttribute("id", "activeMenu");
}
}
CodePen

Horizontal scrolling list center when needed

I have to move a horizontal navigation bar when clicked on a link in the list. I have created a JSFiddle to illustrate my problem.
When a user clicks on a link in the list, the list needs to scroll to the left or right. This part is already finished.
When you click on the link, the active link needs to be centered inside the list.
Link to JSFiddle:
https://jsfiddle.net/7yq0jq9s/2/
html
<div class="container">
<ul>
<li class="active"> 1
</li>
<li> 2
</li>
<li> 3
</li>
<li> 4
</li>
<li> 5
</li>
<li> 6
</li>
<li> 7
</li>
<li> 8
</li>
</ul>
CSS
div.container {
width: 600px;
overflow: hidden;
}
ul {
white-space: nowrap;
}
ul li {
display: inline-block;
background: green;
}
ul li a {
padding: 80px;
display: block;
color: white;
font-weight: bold;
text-decoration: none;
}
ul li.active {
background: blue;
}
JS
$(document).ready(function () {
var scrollTo = 0;
$('body').on('click', "a", function () {
var activeItem = $('li.active');
var selectedItem = $(this).parent()
var activeIndex = $('li').index(activeItem);
var selectedIndex = $('li').index(selectedItem);
if (selectedIndex > activeIndex) {
scrollTo -= selectedItem.position().left - activeItem.position().left;
console.log('Scroll right');
} else {
scrollTo += Math.abs(selectedItem.position().left - activeItem.position().left);
console.log('Scroll left');
if (scrollTo >= 0) {
scrollTo = 0;
}
}
$('ul').css('transform', 'translateX(' + scrollTo + 'px)');
activeItem.removeClass('active');
selectedItem.addClass('active');
});
});
I think it's easier to just get the absolute position of the clicked element and calculate the middle position of the container instead of checking if it needs to scroll left or right:
var scrollTo = 0;
$('body').on('click', "a", function () {
var activeItem = $('li.active');
var selectedItem = $(this).parent()
var activeIndex = $('li').index(activeItem);
var selectedIndex = $('li').index(selectedItem);
scrollTo =- selectedItem.position().left + $('.container').width() / 2 - selectedItem.width() / 2;
$('ul').css('transform', 'translateX(' + scrollTo + 'px)');
activeItem.removeClass('active');
selectedItem.addClass('active');
});
div.container {
width: 600px;
overflow: hidden;
}
ul {
white-space: nowrap;
transition: all ease 750ms;
position:relative;
}
ul li {
display: inline-block;
background: green;
}
ul li a {
padding: 80px;
display: block;
color: white;
font-weight: bold;
text-decoration: none;
}
ul li.active {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="container">
<ul>
<li class="active"> 1
</li>
<li> 2
</li>
<li> 3
</li>
<li> 4
</li>
<li> 5
</li>
<li> 6
</li>
<li> 7
</li>
<li> 8
</li>
</ul>
</div>
var scrollTo = 0;
$('body').on('click', "a", function () {
var activeItem = $('li.active');
var selectedItem = $(this).parent()
var activeIndex = $('li').index(activeItem);
var selectedIndex = $('li').index(selectedItem);
scrollTo =- selectedItem.position().left + $('.container').width() / 2 - selectedItem.width() / 2;
$('ul').css('transform', 'translateX(' + scrollTo + 'px)');
activeItem.removeClass('active');
selectedItem.addClass('active');
});
div.container {
width: 600px;
overflow: hidden;
}
ul {
white-space: nowrap;
transition: all ease 750ms;
position:relative;
}
ul li {
display: inline-block;
background: green;
}
ul li a {
padding: 80px;
display: block;
color: white;
font-weight: bold;
text-decoration: none;
}
ul li.active {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="container">
<ul>
<li class="active"> 1
</li>
<li> 2
</li>
<li> 3
</li>
<li> 4
</li>
<li> 5
</li>
<li> 6
</li>
<li> 7
</li>
<li> 8
</li>
</ul>
</div>
I think you just needed to change one little bit on line 10:
if (selectedIndex = activeIndex) {
https://jsfiddle.net/7yq0jq9s/3/

Categories