I got a codepen where you have to select some tabs, then you can insert your name and press submit and your name gets appended to the selected tabs. The thing is when you select multiple tabs (i did that with the jQuery selectable widget) and add your name to them, your name gets displayed multiple times. Thats pretty obvious because it gets added to every tab and that should be like that.
My goal is that javascript just hides the "duplicated" list items. So your name is just there once, but still on each tab you selected.
Thats my js:
$(function() {
$('#plannername').prop('disabled', true);
$('#plannername').attr("placeholder", "zuerst Tage auswählen");
$('#plannersubmit').attr("value", " ");
function selectionChange(event, ui) {
var items = $('.ui-selected', this).map(function () {
return $(this).index();
}).get();
$("section").each(function () {
$(this).toggle(items.indexOf($(this).index()) > -1);
});
$('#plannername').prop('disabled', false);
$('#plannername').attr("placeholder", "Name eingeben");
$('#plannersubmit').attr("value", "eintragen");
}
$("#selectable").selectable();
$("#selectable").selectable({
selected: selectionChange,
unselected: selectionChange
});
});
$(function(){
$('#plannerform').submit(function(e){
var val = $(this).find('#plannername').val();
$('ul.plannerlist:visible').append('<li>' + val + '</li>');
e.preventDefault();
$('#plannername').val('');
});
});
And these are my HTML tabs:
<div id="content">
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
</div>
If you need to see my whole code, you can check out my codepen, which I mentioned above.
Looks like 2 events will make tabs show content - selecting a tab, then selecting a tab and submitting the form. On both of those events, I would loop through the visible tabs, and hide any duplicates.
Created a function called clearDupes() that will hide duplicates, and calling it in selectionChange() and on $('#plannerform').submit()
Here's a pen since the form won't submit on SO http://codepen.io/mcoker/pen/YNoVOo
$(function() {
function clearDupes() {
var arr = [];
$('.plannerlist li').removeClass('hidden');
$('.tabcontent:visible').each(function() {
$(this).find('.plannerlist li').each(function() {
var nameText = $(this).text();
if (arr.indexOf(nameText) > -1) {
$(this).addClass('hidden');
} else {
arr.push(nameText);
}
})
})
}
// define one function, to be used for both select/unselect
$('#plannername').prop('disabled', true);
$('#plannername').attr("placeholder", "zuerst Tage auswählen");
$('#plannersubmit').attr("value", " ");
function selectionChange(event, ui) {
// Get indexes of selected items in an array
var items = $('.ui-selected', this).map(function() {
return $(this).index();
}).get();
// Show or hide sections according to the corresponding option's selection
$("section").each(function() {
$(this).toggle(items.indexOf($(this).index()) > -1);
});
$('#plannername').prop('disabled', false);
$('#plannername').attr("placeholder", "Name eingeben");
$('#plannersubmit').attr("value", "eintragen");
clearDupes();
}
$("#selectable").selectable();
$("#selectable").selectable({
selected: selectionChange,
unselected: selectionChange
});
$('#plannerform').submit(function(e) {
var val = $(this).find('#plannername').val();
$('ul.plannerlist:visible').append('<li>' + val + '</li>');
e.preventDefault();
$('#plannername').val('');
clearDupes();
});
});
*{
font-family: 'Josefin Sans', sans-serif;
margin: 0;
padding: 0;
box-sizing: border-box;
}
#selectable .ui-selecting {
background: #9eefbc;
transition:.8s ease-in-out;
-webkit-transition: -webkit-transform 0.8s, background-color 0.8s;
transition: transform 0.8s, background-color 0.8s;
-webkit-transform: perspective(300px) rotate3d(1,0,0,-180deg);
transform: perspective(300px) rotate3d(1,0,0,-180deg);
-webkit-transform-origin: 50% 100%;
transform-origin: 50% 100%;
-webkit-perspective-origin: 50% 100%;
perspective-origin: 50% 100%;
}
#selectable .ui-selected {
background: #6dce91;
transition:all 0.8s;
}
#selectable {
list-style-type: none;
position:absolute;
width: 60%;
margin-left:20%;
display:flex;
transition:.3s ease-in-out;
z-index:1;
margin-top:3px;
}
#selectable li {
background:#ddffea;
padding: 0.6em;
font-size: 1.4em;
flex-grow:1;
transition:.3s ease-in-out;
border:none;
text-align:center;
line-height:0.8em;
}
#selectable .ui-selected:after,
#selectable .ui-selected::after {
position: absolute;
top: 44px;
margin-left:-50px;
transition: .2s ease-in-out;
content: '';
width: 0;
height: 0;
opacity:1;
animation:dreieckFade 1s forwards;
border-top: solid 15px #6dce91;
border-left: solid 20px transparent;
border-right: solid 20px transparent;
}
#keyframes dreieckFade{
0%{opacity:0;border-top: solid 0px #6dce91;}
100%{opacity:1;border-top: solid 15px #6dce91;}
}
.ui-selectable-helper {
visibility: hidden;
}
#content{
width:60%;
background-color:#9eefbc;
margin-left:20%;
padding-top:70px;
margin-top:3px;
padding-bottom:30px;
}
.tabcontent{
top:44px;
background-color:transparent;
z-index:0;
transition:.3s ease-in-out;
font-size:2em;
display:none;
text-align:center;
}
#plannername{
width:40%;
background-color:#9eefbc;
margin-left:20%;
border:0;
font-size:2em;
padding:20px;
}
#plannername:focus{
outline:0;
}
#plannersubmit{
width:20%;
background-color:#6dce91;
border:0;
font-size:2em;
padding:20px;
transition:.2s ease-in-out;
}
#plannersubmit:hover{
transition:.2s ease-in-out;
padding-left:40px;
cursor:pointer;
}
#plannersubmit:focus{
outline:0;
}
#plannersubmit:active{
color:white;
}
.plannerlist{
list-style-type:none;
}
.hidden {
display: none;
}
<link href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<form id="plannerform">
<input id="plannername" placeholder="Name eingeben" type="text" autocomplete="off"></input><!--
--><input id="plannersubmit" type="submit" value="eintragen"></input>
</form>
<ol id="selectable">
<li class="ui-widget-content">FR PM</li>
<li class="ui-widget-content">SA AM</li>
<li class="ui-widget-content">SA PM</li>
<li class="ui-widget-content">SO AM</li>
<li class="ui-widget-content">SO PM</li>
<li class="ui-widget-content">MO AM</li>
</ol>
<div id="content">
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
<section class="tabcontent">
<ul class="plannerlist">
</ul>
</section>
</div>
Try adding this function to your code:
function isUnique(name) {
var is_unique = true;
$('ul li').each(function(item, index) {
if ($( this ).text() === name) {
is_unique = false;
}
});
return is_unique;
}
We compare the text of every list item with the current name we're attempting to append to the visible list.
You could use the function like this:
var val = $(this).find('#plannername').val();
if (isUnique(val)) {
$('ul.plannerlist:visible').append('<li>' + val + '</li>');
$('#plannername').val('');
}
...
Forked demo
Related
I would like to know how to change the content of a div when I click on the menu
Currently it looks like this :
There is my css and html code :
body {
background-color: #555657;
margin: 20px;
}
/* CADRE PARENT */
#global {}
/* CADRE 1 */
#cadre1 {
float: left;
width: 250px;
}
#cadre1 span {
color: #33A7FF;
}
/* CADRE 2 */
#cadre2 {
color: #2370AB;
}
#menu,
#menu ul {
padding: 0;
margin: 0;
list-style: none;
text-align: center;
}
#menu li {
display: block;
position: relative;
background-color: #2370AB;
}
#menu li ul li {
background-color: white;
text-align: center;
}
#menu ul li {
display: inherit;
border-radius: 0;
}
#menu ul li:hover {
border-radius: 0;
}
#menu ul li:last-child {
border-radius: 0 0 8px 8px;
}
#menu ul {
position: absolute;
z-index: 1000;
max-height: 0;
left: 0;
right: 0;
overflow: hidden;
-moz-transition: .8s all .3s;
-webkit-transition: .8s all .3s;
transition: .8s all .3s;
}
#menu li:hover ul {
max-height: 15em;
}
#menu a {
display: block;
padding: 8px 32px;
color: #fff;
}
#menu ul a {
padding: 8px 0;
}
#menu li:hover a,
#menu li li:hover a {
color: #000;
}
/* CADRE 3 */
#div_profil {
display: block;
height: 625px;
background-color: white;
overflow: auto;
}
#div_experience {
display: none;
height: 625px;
background-color: white;
overflow: auto;
}
#div_projet {
display: none;
height: 625px;
background-color: white;
overflow: auto;
}
#div_contact {
display: none;
height: 625px;
background-color: white;
overflow: auto;
}
/* FOOTER */
#footer {
position: fixed;
bottom: 20px;
background-color: #2370AB;
text-align: center;
}
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>portfolio FIEVEZ Clément</title>
<link type="text/css" rel="stylesheet" href="boostrap/css/bootstrap.min.css">
<link rel="stylesheet" href="css/styles.css" />
</head>
<body>
<!--CADRE PRINCIPAL-->
<div class="row" id="global">
<!--INFO BASIQUE-->
<div class="col-sm-3" id="cadre1">
<img src="images/myAvatar.png" alt="avatar" id="avatar" />
<p><span>Nom :</span> FIEVEZ</p>
<p><span>Prénom :</span> Clément (René)</p>
<p><span>Date de naissance / Age :</span> né le 22 janvier 1996, 22ans</p>
<p><span>Lieu de naissance :</span> DENAIN (059)</p>
<p><span>Adresse :</span> 85 rue magenta, 53000 LAVAL</p>
</div>
<!--MENU-->
<div class="col-sm-3" id="cadre2">
<ul id="menu">
<li>Profil
</li>
<li><a id="btn_experience" href="#Experience">Expérience</a>
</li>
<li>Projets
<ul>
<li>Projet 1</li>
<li>Projet 2</li>
<li>Projet 3</li>
<li>projet 4</li>
</ul>
</li>
<li>Contact
</li>
</ul>
</div>
<!--CADRE CHANGEANT-->
<div class="col-sm-5" id="div_profil">
<p>Et Epigonus quidem amictu tenus philosophus, ut apparuit, prece frustra temptata, sulcatis lateribus mortisque metu admoto turpi confessione cogitatorum socium, quae nulla erant, fuisse firmavit cum nec vidisset quicquam nec audisset penitus expers
forensium rerum; Eusebius vero obiecta fidentius negans, suspensus in eodem gradu constantiae stetit latrocinium illud esse, non iudicium clamans.
</p>
</div>
<div class="col-sm-5" id="div_experience">
<p>div experience</p>
</div>
<div class="col-sm-5" id="div_projet">
<p>div projet</p>
</div>
<div class="col-sm-5" id="div_contact">
<p>div contact</p>
</div>
</div>
<footer class="col-sm-12" id="footer">
<div>
<p class="copyright">Tout droit reservé. FIEVEZ Corps.</p>
</div>
</footer>
<script type="text/javascript" src="javascript/script.js"></script>
</body>
</html>
I would like that when I click on one of the tabs of the menu, the div displayed be replaced by another div.
I tried to use some javascript code but this doesn't work.
What should I use to achieve what I want?
Thanks for your reply, have a good day.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>portfolio FIEVEZ Clément</title>
<link type="text/css" rel="stylesheet" href="boostrap/css/bootstrap.min.css">
<link rel="stylesheet" href="css/styles.css"/>
<style>
body{
background-color: #555657;
margin: 20px;
}
/* CADRE PARENT */
#global{
}
/* CADRE 1 */
#cadre1{
float: left;
width: 250px;
}
#cadre1 span{
color : #33A7FF;
}
/* CADRE 2 */
#cadre2{
color : #2370AB;
}
#menu, #menu ul{
padding:0;
margin:0;
list-style:none;
text-align:center;
}
#menu li{
display:block;
position:relative;
background-color: #2370AB;
}
#menu li ul li{
background-color: white;
text-align:center;
}
#menu ul li{
display:inherit;
border-radius:0;
}
#menu ul li:hover{
border-radius:0;
}
#menu ul li:last-child{
border-radius:0 0 8px 8px;
}
#menu ul{
position:absolute;
z-index: 1000;
max-height:0;
left: 0;
right: 0;
overflow:hidden;
-moz-transition: .8s all .3s;
-webkit-transition: .8s all .3s;
transition: .8s all .3s;
}
#menu li:hover ul{
max-height:15em;
}
#menu a{
display:block;
padding:8px 32px;
color:#fff;
}
#menu ul a{
padding:8px 0;
}
#menu li:hover a, #menu li li:hover a{
color:#000;
}
/* CADRE 3 */
#div_profil{
display: block;
height: 625px;
background-color : white;
overflow: auto;
}
#div_experience{
display: none;
height: 625px;
background-color : white;
overflow: auto;
}
#div_projet{
display: none;
height: 625px;
background-color : white;
overflow: auto;
}
#div_contact{
display: none;
height: 625px;
background-color : white;
overflow: auto;
}
/* FOOTER */
#footer{
position: fixed;
bottom: 20px;
background-color: #2370AB;
text-align: center;
}
</style>
</head>
<body>
<!--CADRE PRINCIPAL-->
<div class="row" id="global">
<!--INFO BASIQUE-->
<div class="col-sm-3" id="cadre1">
<img src="images/myAvatar.png" alt="avatar" id="avatar"/>
<p><span>Nom :</span> FIEVEZ</p>
<p><span>Prénom :</span> Clément (René)</p>
<p><span>Date de naissance / Age :</span> né le 22 janvier 1996, 22ans</p>
<p><span>Lieu de naissance :</span> DENAIN (059)</p>
<p><span>Adresse :</span> 85 rue magenta, 53000 LAVAL</p>
</div>
<!--MENU-->
<div class="col-sm-3" id="cadre2">
<ul id="menu">
<li>Profil
</li>
<li><a id="btn_experience" href="#Experience" onclick="div2('div_experience')">Expérience</a>
</li>
<li>Projets
<ul>
<li>Projet 1</li>
<li>Projet 2</li>
<li>Projet 3</li>
<li>projet 4</li>
</ul>
</li>
<li>Contact
</li>
</ul>
</div>
<!--CADRE CHANGEANT-->
<div class="col-sm-5" id="div_profil" >
<p>Et Epigonus quidem amictu tenus philosophus, ut apparuit, prece frustra temptata, sulcatis lateribus mortisque metu admoto turpi confessione cogitatorum socium, quae nulla erant, fuisse firmavit cum nec vidisset quicquam nec audisset penitus expers forensium rerum; Eusebius vero obiecta fidentius negans, suspensus in eodem gradu constantiae stetit latrocinium illud esse, non iudicium clamans.
</p>
</div>
<div class="col-sm-5" id="div_experience">
<p>div experience</p>
</div>
<div class="col-sm-5" id="div_projet">
<p>div projet</p>
</div>
<div class="col-sm-5" id="div_contact">
<p>div contact</p>
</div>
</div>
<footer class="col-sm-12" id="footer">
<div>
<p class="copyright">Tout droit reservé. FIEVEZ Corps.</p>
</div>
</footer>
<script>
function div2(name)
{
document.getElementById("div_profil").style.display="none";
document.getElementById("div_experience").style.display="none";
document.getElementById("div_projet").style.display="none";
document.getElementById("div_contact").style.display="none";
document.getElementById(name).style.display="block";
}
</script>
</body>
</html>
Here a quick answer I made up... jsfiddle
HTML
<a id='1' onclick='myFunction("1");'>Click me 1</a><br/>
<a id='2' onclick='myFunction("2");'>Click me 2</a><br/>
<a id='3' onclick='myFunction("3");'>Click me 3</a><br/>
<a id='4' onclick='myFunction("4");'>Click me 4</a><br/>
<div id='addText'>
</div>
Javascript
<script>
function myFunction(id){
x = document.getElementById("addText");
if(id == 1){
x.innerHTML = 'Hello'
x.style.color = "red";
} else if(id == 2){
x.innerHTML = 'Hi'
x.style.color = "red";
} else if(id ==3){
x.innerHTML = 'Option 3'
x.style.color = "red";
}else{
x.innerHTML = 'Goodbye'
x.style.color = "red";
}
}
</script>
I left all the styling for you, if you dont plan on having many options this solution will work fine.
You almost there, now you need to add some flag related to any container div with any link that should point to corresponding div, so eg:
// if you have you markup html with multiple links try this
<ul>
<li>My Profile</li>
<li>My Experience</li>
</ul>
<div>
<div class="content active" id="div_profile">Show you profile here</div>
<div class="content" id="div_experience">Show your experience here</div>
</div>
So then you need to add some JS code to do the trick, this code will do the trick
var links = document.getElementById('menu').getElementsByTagName('a');
var lastShownDiv = getActiveDiv();
for(var i = 0; i < links.length; i++) {
var currentLink = links[i];
currentLink.addEventListener('click', function(event){
var link = this;
var targetDiv = link.getAttribute('data-url');
if (lastShownDiv) {
removeClassName(lastShownDiv, 'active');
}
lastShownDiv = document.getElementById(targetDiv);
addClassName(lastShownDiv, 'active');
}, false);
}
function addClassName(element, classname) {
if (!element) {
return;
}
var classlists = element.className.split(' ');
classlists.push(classname);
element.className = classlists.join(' ');
}
function removeClassName(element, classname) {
if (!element) {
return;
}
var classlists = element.className.split(' ');
var indexOfClassName = classlists.indexOf(classname);
if (indexOfClassName > -1) {
classlists.splice(indexOfClassName, 1);
}
element.className = classlists.join(' ');
}
function getActiveDiv() {
var actives = document.getElementsByClassName('active');
for(var i = 0; i < actives.length; i++) {
return actives[i];
}
}
body {
background-color: #555657;
margin: 20px;
}
/* CADRE PARENT */
#global {}
/* CADRE 1 */
#cadre1 {
float: left;
width: 250px;
}
#cadre1 span {
color: #33A7FF;
}
/* CADRE 2 */
#cadre2 {
color: #2370AB;
}
#menu,
#menu ul {
padding: 0;
margin: 0;
list-style: none;
text-align: center;
}
#menu li {
display: block;
position: relative;
background-color: #2370AB;
}
#menu li ul li {
background-color: white;
text-align: center;
}
#menu ul li {
display: inherit;
border-radius: 0;
}
#menu ul li:hover {
border-radius: 0;
}
#menu ul li:last-child {
border-radius: 0 0 8px 8px;
}
#menu ul {
position: absolute;
z-index: 1000;
max-height: 0;
left: 0;
right: 0;
overflow: hidden;
-moz-transition: .8s all .3s;
-webkit-transition: .8s all .3s;
transition: .8s all .3s;
}
#menu li:hover ul {
max-height: 15em;
}
#menu a {
display: block;
padding: 8px 32px;
color: #fff;
}
#menu ul a {
padding: 8px 0;
}
#menu li:hover a,
#menu li li:hover a {
color: #000;
}
/* CADRE 3 */
.content {
display: none;
}
.content.active {
display: block;
}
#div_profil {
height: 625px;
background-color: white;
overflow: auto;
}
#div_experience {
height: 625px;
background-color: white;
overflow: auto;
}
#div_projet {
height: 625px;
background-color: white;
overflow: auto;
}
#div_contact {
height: 625px;
background-color: white;
overflow: auto;
}
/* FOOTER */
#footer {
position: fixed;
bottom: 20px;
background-color: #2370AB;
text-align: center;
}
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>portfolio FIEVEZ Clément</title>
<link type="text/css" rel="stylesheet" href="boostrap/css/bootstrap.min.css">
<link rel="stylesheet" href="css/styles.css" />
</head>
<body>
<!--CADRE PRINCIPAL-->
<div class="row" id="global">
<!--INFO BASIQUE-->
<div class="col-sm-3" id="cadre1">
<img src="images/myAvatar.png" alt="avatar" id="avatar" />
<p><span>Nom :</span> FIEVEZ</p>
<p><span>Prénom :</span> Clément (René)</p>
<p><span>Date de naissance / Age :</span> né le 22 janvier 1996, 22ans</p>
<p><span>Lieu de naissance :</span> DENAIN (059)</p>
<p><span>Adresse :</span> 85 rue magenta, 53000 LAVAL</p>
</div>
<!--MENU-->
<div class="col-sm-3" id="cadre2">
<ul id="menu">
<li>Profil
</li>
<li><a id="btn_experience" href="#Experience" data-url="div_experience">Expérience</a>
</li>
<li>Projets
<ul>
<li>Projet 1</li>
<li>Projet 2</li>
<li>Projet 3</li>
<li>projet 4</li>
</ul>
</li>
<li>Contact
</li>
</ul>
</div>
<!--CADRE CHANGEANT-->
<div class="col-sm-5 content active" id="div_profil">
<p>Et Epigonus quidem amictu tenus philosophus, ut apparuit, prece frustra temptata, sulcatis lateribus mortisque metu admoto turpi confessione cogitatorum socium, quae nulla erant, fuisse firmavit cum nec vidisset quicquam nec audisset penitus expers
forensium rerum; Eusebius vero obiecta fidentius negans, suspensus in eodem gradu constantiae stetit latrocinium illud esse, non iudicium clamans.
</p>
</div>
<div class="col-sm-5 content" id="div_experience">
<p>div experience</p>
</div>
<div class="col-sm-5 content" id="div_projet">
<p>div projet</p>
</div>
<div class="col-sm-5 content" id="div_contact">
<p>div contact</p>
</div>
</div>
<footer class="col-sm-12 content" id="footer">
<div>
<p class="copyright">Tout droit reservé. FIEVEZ Corps.</p>
</div>
</footer>
</body>
</html>
The code above, is your code with some updates, I hope this help you to solve your problem.
You could avoid to use Javascript and try a pure css approach using the :target pseudoclass
As you can see, all the content is already inside the document and the main functionality is preserved even if you don't rely on Javascript and /or CSS (without them the page would still work, thanks to the navigation links with a fragment identifier as their href attributes.
Codepen demo
Markup
<nav role="complementary">
<ul role="tablist">
<li role="tab" aria-controls="cnt1" id="tab1" aria-selected="true">
Content 1</li>
<li role="tab" aria-controls="cnt2" id="tab2" aria-selected="false">
Content 2</li>
<li role="tab" aria-controls="cnt3" id="tab3" aria-selected="false">
Content 3</li>
<li role="tab" aria-controls="cnt4" id="tab4" aria-selected="false">
Content 4</li>
</ul>
</nav>
<main>
<section id="cnt1" aria-hidden="false" role="tabpanel" aria-labelledby="tab1">
<h2>Content 1</h2>
<p>This is a lorem ipsum</p>
</section>
<section id="cnt2" aria-hidden="true" role="tabpanel" aria-labelledby="tab2">
<h2>Content 2</h2>
<p>I am the content of link #2</p>
</section>
<section id="cnt3" aria-hidden="true" role="tabpanel" aria-labelledby="tab3">
<h2>Content 3</h2>
<p>Here's another content</p>
</section>
<section id="cnt4" aria-hidden="true" role="tabpanel" aria-labelledby="tab4">
<h2>Content 4</h2>
<p>And that's all folks!</p>
</section>
</main>
CSS (relevant)
body { display: flex; }
main {
flex: 1;
align-self: stretch;
position: relative; }
ul { list-style: none; }
nav { align-self: flex-start; }
[role="tabpanel"] {
position: absolute;
transition: .25s opacity;
background: #fff;
padding: 0 20px;
left: 0; right: 0; top: 0; bottom: 0;
opacity: 0; }
[role="tabpanel"]:first-of-type { opacity: .99; }
[role="tabpanel"]:target { opacity: 1; }
With a simple CSS transition you can switch the content appearance.
Note that I've inserted some role and aria-* attributes: in fact this kind of navigation is really close to a tab/tabpanels widget.
Even if javascript is not used here, it could help a lot anyway to increase the accessibility of the content: e.g. you could attach a transitionend event, detect the visible section (just look at its opacity value) and change some aria-* attributes so to make the life easier for people who use assistive technology.
Javascript
(only for accessibility purpose)
var _gcs = window.getComputedStyle;
var _sections = document.querySelectorAll('[role="tabpanel"]');
var _tabs = document.querySelectorAll('[role="tab"]');
var _setARIAAttributes = () => {
var currentHash;
/* set aria-hidden on panels */
[..._sections].forEach( ( s ) => {
var hidden = +( _gcs( s ).getPropertyValue( 'opacity' ) ) < 1;
s.setAttribute( 'aria-hidden', hidden);
if (!hidden) currentHash = s.id;
});
/* set aria-controls on tabs */
[..._tabs].forEach( ( t ) => {
var selected = t.getAttribute( 'aria-controls' ) === currentHash;
t.setAttribute( 'aria-selected', selected );
});
}
if (!!location.hash) { _setARIAAttributes() }
window.addEventListener('transitionend', () => { _setARIAAttributes(); });
I'm creating a navigation structure using ul container which has some li items and that li element has a <a> element with the toggle class. Underneath <a> element also there is ul container with the class name inner. What I'm doing is when i click on any <a> element a click event is call. In that event i calculate height of all children that inner class has but when i want to set that calculated height as a css property to that inner class it doesn't expand fully.
See Code:
function CallBackFunction() {
var elm = $(this);
var height = 0;
elm.next().children().each(function () {
height = height + $(this).outerHeight(true);
});
elm.next().css('max-height', height);
}
$('.toggle').click(CallBackFunction);
.parent {
border: 1px solid black;
}
.inner {
max-height: 0;
overflow: hidden;
transition: max-height 300ms ease-in-out;
}
a:hover {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<html lang="en">
<head>
</head>
<body>
<ul class="parent">
<li>
<a class="toggle">Link 1</a>
<ul class="inner">
<li>
<p>Dummy Text</p>
</li>
<li>
<a class="toggle">Nested Link</a>
<div class="inner">
<p>Again Dummy Text</p>
</div>
</li>
</ul>
</li>
</ul>
</body>
</html>
Add this code in css
ul.inner>li {
float: left;
width: 100%;
}
Here li is not getting height of p,so need to float li
function CallBackFunction() {
var elm = $(this);
var height = 0;
elm.next().children().each(function () {
height = height + $(this).outerHeight(true);
});
elm.next().css('max-height', height);
}
$('.toggle').click(CallBackFunction);
.parent {
border: 1px solid black;
}
.inner {
max-height: 0;
overflow: hidden;
transition: max-height 300ms ease-in-out;
}
ul.inner>li {
float: left;
width: 100%;
}
a:hover {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<ul class="parent">
<li>
<a class="toggle">Link 1</a>
<ul class="inner">
<li>
<p>Dummy Text</p>
</li>
<li>
<a class="toggle">Nested Link</a>
<div class="inner">
<p>Again Dummy Text</p>
</div>
</li>
</ul>
</li>
</ul>
I have some tabs I'm making and I'd like for them to be collapsible, but with my current code, that isn't possible because the script uses addClass/removeClass instead of something else, and I'm not sure how to fix that:
Code
$(document).ready(function() {
$('.tabs .tab-links a').on('click', function(e) {
var currentAttrValue = $(this).attr('href');
$('.tabs ' + currentAttrValue).fadeIn(600).siblings().hide();
$(this).parent('li').addClass('active').siblings().removeClass('active');
e.preventDefault();
});
});
$(document).ready(function() {
$('#filterOptions li a').click(function() {
var ourClass = $(this).attr('class');
$('#filterOptions li').removeClass('active');
$(this).parent().addClass('active');
if (ourClass == 'all') {
$('#ourHolder').children('div.item').show();
} else {
$('#ourHolder').children('div:not(.' + ourClass + ')').hide();
$('#ourHolder').children('div.' + ourClass).show();
}
return false;
});
});
.tabs {
width: 200px;
padding: 0;
overflow: hidden;
}
.tab-links li {
display: inline;
text-align: center;
list-style: none;
margin-left: 0;
padding: 0;
}
ul.tab-links {
padding: 0 0 10px 0;
text-align: center;
list-style: none;
margin: 0!important;
}
.tab-links a {
color: #000;
}
.tab-links b {
color: #fff000;
font-weight: 900;
}
.tab {
display: none;
}
.tab.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="tabs">
<ul class="tab-links">
<li class="active">
<b>first</b>
</li>
<li>second
</li>
<li>third
</li>
</ul>
</div>
<div class="tabs">
<!-- TAB 1 -->
<div id="tab1" class="tab">
first
</div>
<!-- TAB 2 -->
<div id="tab2" class="tab">
second
</div>
<div id="tab3" class="tab">
third
</div>
Check this fiddle using toggleClass (not sure if I have understood your requirement though)
$(document).ready(function() {
$('.tabs .tab-links a').on('click', function(e) {
var currentAttrValue = $(this).attr('href');
if ( $('.tabs ' + currentAttrValue).is(':visible') )
{
$(this).parent('li').toggleClass('active');
$('.tabs ' + currentAttrValue).hide();
}
else
{
$('.tabs ' + currentAttrValue).fadeIn(600).siblings().hide();
$(this).parent('li').toggleClass('active').siblings().removeClass('active');
}
e.preventDefault();
});
});
.tab-links li.active {
color:#fff000;
font-weight:900;
}
<div class="tabs">
<ul class="tab-links">
<li class="active">
first</li>
<li>second</li>
<li>third</li>
</ul>
</div>
Try this:
$(document).ready(function() {
$('.tab-links li a').click(function() {
var ourClass = $(this).attr('href');
if(!$(ourClass).hasClass('active')){
$('.tabs').find('.active').removeClass('active');
}
$(ourClass).toggleClass('active');
return false;
});
});
Css:
.tab {
// display:none;
opacity: 0;
-webkit-transition: opacity .8s ease-in;
-moz-transition: opacity .8s ease-in;
-ms-transition: opacity .8s ease-in;
-o-transition: opacity .8s ease-in;
transition: opacity .8s ease-in;
height: 0px;
}
.tab.active {
// display:block;
opacity: 1;
height: 20px;
}
Fiddle
I'm trying to make a div open when you hover a link. Which is simple enough and I'm doing fine. But I also want to be able to access the div without it closing. So if I hover over the newly opened div it will stay open. But If I hover out of the div I want it to close.
I also want to make sure that if I hover out of the link that the div closes. I have done this a few times before but for the life of me I cant sort it back out. I remember using setTimeout previously but my mind has went to mush and it's late so thought I might as well ask for some help.
I'm also aware that mouseenter and mouseleave would be far better than hover in this situation I just typed it up as hover for speed.
UPDATE
Changing the HTML is not an option this is a jquery question not an html or CSS one.
jQuery(document).ready(function($) {
"use strict";
$("li.true a").hover(
function() {
$(".open").fadeIn(1000);
}, function() {
$(".open").fadeOut(1000);
}
);
$(".open").hover(
function() {
$(this).show();
}, function() {
$(this).fadeOut(1000);
}
);
});
ul,
li {
list-style: none;
}
li {
display: inline-block;
}
a {
display: block;
padding: 10px;
background-color: black;
color: white;
-webkit-transition: all 0.35s ease-in-out;
transition: all 0.35s ease-in-out;
cursor: pointer;
}
a:hover {
color: black;
background-color: white;
}
li.true a {
background-color: green;
}
li.true a:hover {
background-color: blue;
color: green;
}
div.open {
background-color: red;
width: 100%;
height: 300px;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<nav>
<ul>
<li><a>not</a>
</li>
<li><a>not</a>
</li>
<li class="true"><a>true</a>
</li>
<li><a>not</a>
</li>
<li><a>not</a>
</li>
</ul>
</nav>
<div class="open"></div>
Move the div with the class open to the li as child element. The JS is now also simpler for your case. You can find the fiddle here: https://jsfiddle.net/ej5gkgat/.
<nav>
<ul>
<li><a>not</a>
</li>
<li><a>not</a>
</li>
<li class="true">
<a>true</a>
<div class="open"></div>
</li>
<li><a>not</a>
</li>
<li><a>not</a>
</li>
</ul>
</nav>
New CSS:
ul,
li {
list-style: none;
}
li {
display: inline-block;
}
a {
display: block;
padding: 10px;
background-color: black;
color: white;
-webkit-transition: all 0.35s ease-in-out;
transition: all 0.35s ease-in-out;
cursor: pointer;
}
a:hover {
color: black;
background-color: white;
}
li.true a {
background-color: green;
}
li.true a:hover {
background-color: blue;
color: green;
}
div.open {
position: absolute;
background-color: red;
width: 300px;
height: 300px;
display: none;
}
New JS:
jQuery(document).ready(function($) {
"use strict";
$("li.true").hover(
function() {
$(".open").fadeIn(1000);
}, function() {
$(".open").fadeOut(1000);
}
);
});
Simple solution is not to use both parameters of hover in jquery.
when hover on "li.true a" simply ignore the second parameter, which hides your div. use null to skip on div.open's hover.
but if you ask for the right way. use CSS for these type of interactions. there is no need for JS to do this.
Edit: If you need to hide it when on siblings of "li.true a"'s hover.
jQuery(document).ready(function($) {
"use strict";
$("li.true a").hover(
function() {
$(".open").fadeIn(1000);
}
);
$("li:not(.true) a").hover(
function() {
$(".open").fadeOut(1000);
}
);
$(".open").hover(null, function() {
$(this).fadeOut(1000);
}
);
});
ul,
li {
list-style: none;
}
li {
display: inline-block;
}
a {
display: block;
padding: 10px;
background-color: black;
color: white;
-webkit-transition: all 0.35s ease-in-out;
transition: all 0.35s ease-in-out;
cursor: pointer;
}
a:hover {
color: black;
background-color: white;
}
li.true a {
background-color: green;
}
li.true a:hover {
background-color: blue;
color: green;
}
div.open {
background-color: red;
width: 100%;
height: 300px;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<nav>
<ul>
<li><a>not</a>
</li>
<li><a>not</a>
</li>
<li class="true"><a>true</a>
</li>
<li><a>not</a>
</li>
<li><a>not</a>
</li>
</ul>
</nav>
<div class="open"></div>
Use this js it uses timeout
jQuery(document).ready(function($) {
"use strict";
var t;
$("li.true a, .open").hover( function() {
clearTimeout (t);
$(".open").fadeIn(1000);
}, function() {
clearTimeout (t);
t = setTimeout(function(){
$(".open").fadeOut(1000);
},1000);
} );
});
You can do this with only css:
body{ font-family:sans-serif; }
nav {
background:blue;
padding:12px;
}
ul {
list-style:none;
}
ul li {
display:inline-block;
padding:6px;
border:1px inset white;
cursor:pointer;
transition:all .5s;
background:red;
}
ul li:hover {
background:white;
color:black;
}
ul ul {
display:none;
}
ul li:hover > ul {
display:inherit;
position:absolute;
top:68px;
float:none;
}
ul ul li {
display:inherit;
float:none;
position:relative;
left:-47px;
}
HTML:
<nav>
<ul>
<li> Example.com </li>
<li> Languages
<ul>
<li> HTML </li>
<li> CSS </li>
<li> Javascript </li>
</ul>
</li>
<li> Something
<ul>
<li> Something </li>
</ul>
</li>
</ul>
</nav>
You can try doing it without timeout (not a big fan of), but with fadeTo() and stop()
Opacity is used to check visibility and calculate estimate remaining fade time.
JSFiddle example
jQuery(document).ready(function($) {
"use strict";
var fadeout = 1000;
var fadein = 800;
$("li.true a").hover(function() {
var opacity = $(".open").css("opacity");
opacity = opacity && opacity < 0.8 ? opacity : 0;
$(".open").stop(true).fadeTo(fadein*(1-opacity), 1);
}, function() {
var opacity = $(".open").css("opacity");
if (opacity > 0) $(".open").fadeTo(fadeout, 0);
});
$(".open").hover(function() {
var opacity = $(this).css("opacity");
if (opacity > 0) $(this).stop(true).fadeTo(fadein*(1-opacity), 1);
}, function() {
$(this).fadeTo(fadeout, 0);
});
});
I am struggling a bit with this, I can hide/show/fadin/fadout all day long but I am trying to get my head round the logic of targetting an element in my and pulling its specific description on mouseover, I have come close to getting this but feel like im missing something, below is my HTML:
<ul id="menu" class="menu">
<li>Home</li>
<li id="menu1" class="menu-link">LINK1</li>
<li id="menu2" class="menu-link">LINK2</li>
<li id="menu3" class="menu-link">LINK3</li>
<li id="menu4" class="menu-link">LINK4</li>
</ul>
<div id="menu1content" class="menuDescription">
Description for "menu1"
</div>
<div id="menu2content" class="menuDescription">
Description for "menu2"
</div>
<div id="menu3content" class="menuDescription">
Description for "menu3"
</div>
<div id="menu4content" class="menuDescription">
Description for "menu4"
</div>
and here is my CSS, the idea is to position the description just above its corresponding element btw:
.menu{
font-family: 'LeagueGothicRegular';
position: absolute;
top:25px;
overflow:hidden;
right:100px;
float:right;
}
.menu ul{
float:left;
width:100%;
padding:0;
margin:0;
list-style-type:none;
}
.menu li{
display:inline;
clear:both;
position:relative;
overflow:hidden;
}
.menu li a{
float:left;
width:6em;
}
.menuDescription {
font-size: 11px;
color: rgb(0, 0, 0);
position: absolute;
right: 407px;
margin-left: 5px;
top: 15px;
}
and finally here is the jquery:
$(document).ready(function() {
$('div.menuDescription').hide();
$('li.menu-link').bind('mouseover', function() {
$('#' + $(this).attr('id') + 'content').prependTo("li.menu-link").fadeIn();
})
.mouseout(function() {
$('#' + $(this).attr('id') + 'content').fadeOut();
});
});
WHen you have a one-to-one relationship between 2 sets of elements and their order in each set matches, is generally easier to use indexing rather than parsing ID
var $content= $('div.menuDescription');
var $links=$('.menu-link').hover(function(){
/* "this" is element being hovered*/
var index= $links.index(this);
$content.stop().hide().eq(index).fadeIn();
},function(){
/* not sure if you want to leave current content visible if user leaves menu, if so do nothing here*/
})
DEMO
I have updated and simplified your fiddle to make it work: Working Fiddle. Here is the simplified code without any JS:
HTML:
<ul id="menu" class="menu">
<li>
Home
</li>
<li id="menu1" class="menu-link">
LINK1
<div id="menu1content" class="menuDescription">
Description for "menu1"
</div>
</li>
<li id="menu2" class="menu-link">
LINK2
<div id="menu2content" class="menuDescription">
Description for "menu2"
</div>
</li>
<li id="menu3" class="menu-link">
LINK3
<div id="menu3content" class="menuDescription">
Description for "menu3"
</div>
</li>
<li id="menu4" class="menu-link">
LINK4
<div id="menu4content" class="menuDescription">
Description for "menu4"
</div>
</li>
</ul>
CSS:
.menu{
font-family: 'LeagueGothicRegular';
position: absolute;
top:25px;
overflow:hidden;
right:100px;
float:right;
}
.menu ul{
float:left;
width:100%;
padding:0;
margin:0;
list-style-type:none;
}
.menu li{
float:left;
margin: 0 5px;
position:relative;
overflow:hidden;
width: 120px;
height: 30px;
}
.menu li a{
position: absolute;
bottom: 0;
}
.menu li .menuDescription {
display: none;
}
.menu li:hover .menuDescription {
display: block;
position: absolute;
top: 0;
left: 0;
width: 120px;
}
.menuDescription {
font-size: 11px;
color: rgb(0, 0, 0);
}
Let me know if you need any explanations and I'll edit my answer.