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/
Related
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>
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>
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>
I click a button and it displays a drop down whenever it changes I want to take it's value and replace it in the input field but If I create many drop downs when I return to the first drop down and change its value the corresponding input field value can't be changed as it is depending on the button click number.
<button type="button" id="buttonadd" onclick="addMore()">Add</button>
<div id='container'>
</div>
<script>
var i = 0;
var x = 0;
var selectid = 0;
var input2;
var select;
var button;
var select_id;
var input2_hiddenID;
var input2hidden;
var counter = 0;
var select_value;
function addMore()
{
if(counter >= 1 && (!select_value || select_value == 0)){
$("#buttonadd").prop('disabled', true);
}else{
select_value = 0;
button = document.getElementById('container');
select = document.createElement("select");
select.options.add( new Option("...select...","0", true, true) );
select.options.add( new Option("name","1") );
select.options.add( new Option("phone","2") );
select.setAttribute("id","selectid" + selectid);
select_id = "selectid";
select.setAttribute("onchange", "getValue(select_id, selectid)");
button.appendChild(select);
input2 = document.createElement("input");
input2.setAttribute("type","hidden");
input2.setAttribute("id","x" + x);
input2.setAttribute("name","x" + x);
button.appendChild( input2 );
var linebreak1 = document.createElement("br");
var linebreak2 = document.createElement("br");
button.append(linebreak1, linebreak2);
i++;
x++;
selectid++;
counter++;
}
}
function getValue(selectid, a){
var lastId = a-1;
var data = selectid + lastId;
select_value =
document.getElementById(data).value;
var x= "x"+lastId;
input2hidden = document.getElementById(x);
if(counter >= 1 && (!select_value || select_value == 0) ){
alert("Please choose from the select menu");
$("#buttonadd").prop('disabled', true);
input2hidden.value = select_value;
}else {
$("#buttonadd").prop('disabled', false);
input2hidden.value = select_value;
}
}
I do not know if I understood your problem well but give you a solution as to how I understand a dropdown with one click
**
HTML
**
<html>
<head>
<title>DropDown</title>
</head>
<body>
<ul class="nav">
<li>
<a href="#">
No dropdown
</a>
</li>
<li class="button-dropdown">
<a href="javascript:void(0)" class="dropdown-toggle">
Dropdown 1 <span>▼</span>
</a>
<ul class="dropdown-menu">
<li>
<a href="#">
Drop Item 1
</a>
</li>
<li>
<a href="#">
Drop Item 2
</a>
</li>
<li>
<a href="#">
Drop Item 3
</a>
</li>
</ul>
</li>
<li>
<a href="#">
No dropdown
</a>
</li>
<li class="button-dropdown">
<a href="javascript:void(0)" class="dropdown-toggle">
Dropdown 2 <span>▼</span>
</a>
<ul class="dropdown-menu">
<li>
<a href="#">
asdf
</a>
</li>
</ul>
</li>
</ul>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
**
CSS
**
body {
background-color: #eee;
text-align: center;
padding-top: 50px;
}
.nav {
display: block;
font: 13px Helvetica, Tahoma, serif;
text-transform: uppercase;
margin: 0;
padding: 0;
}
.nav li {
display: inline-block;
list-style: none;
}
.nav .button-dropdown {
position: relative;
}
.nav li a {
display: block;
color: #333;
background-color: #fff;
padding: 10px 20px;
text-decoration: none;
}
.nav li a span {
display: inline-block;
margin-left: 5px;
font-size: 10px;
color: #999;
}
.nav li a:hover, .nav li a.dropdown-toggle.active {
background-color: #289dcc;
color: #fff;
}
.nav li a:hover span, .nav li a.dropdown-toggle.active span {
color: #fff;
}
.nav li .dropdown-menu {
display: none;
position: absolute;
left: 0;
padding: 0;
margin: 0;
margin-top: 3px;
text-align: left;
}
.nav li .dropdown-menu.active {
display: block;
}
.nav li .dropdown-menu a {
width: 150px;
}
**
JavaScript
**
jQuery(document).ready(function (e) {
function t(t) {
e(t).bind("click", function (t) {
t.preventDefault();
e(this).parent().fadeOut()
})
}
e(".dropdown-toggle").click(function () {
var t = e(this).parents(".button-dropdown").children(".dropdown-menu").is(":hidden");
e(".button-dropdown .dropdown-menu").hide();
e(".button-dropdown .dropdown-toggle").removeClass("active");
if (t) {
e(this).parents(".button-dropdown").children(".dropdown-menu").toggle().parents(".button-dropdown").children(".dropdown-toggle").addClass("active")
}
});
e(document).bind("click", function (t) {
var n = e(t.target);
if (!n.parents().hasClass("button-dropdown")) e(".button-dropdown .dropdown-menu").hide();
});
e(document).bind("click", function (t) {
var n = e(t.target);
if (!n.parents().hasClass("button-dropdown")) e(".button-dropdown .dropdown-toggle").removeClass("active");
})
});
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