Working with multiple selectable tabs - javascript

I got this little codepen which I am working on. I am pretty new to javascript and just worked some solutions out the best as I could. Now my question is: Would there have been any better ways to do this?
That's my JS:
$(function() {
$("#selectable").selectable();
$("#selectable").selectable({
selected: function(event, ui) {
var nthchild = ($(ui.selected).index() + 1);
$("section:nth-child(" + nthchild + ")").css('opacity', '1');
$("section:not(:nth-child(" + nthchild + "))").css('opacity', '0');
}
});
});
As you can see, I just got the nth-child with the index + 1 of the selected list item. Then I called the matching section with section:nth-child(" + nthchild + ") and set the opacity to 1. Would there been any better ways to get multiple selectable tabs? Atm there aren't even multiple selectable tabs. The $("section:not(:nth-child(" + nthchild + "))").css('opacity', '0'); only leaves the last selected one.
My final goal for this codepen is to get multiple selectable tabs, whose content get merged (like put below each other), when there are multiple tabs selected.
Remember, I am pretty new to javascript and like to improve. I am open to any solution. For the multi select I am using the jQuery Seletable widget (http://api.jqueryui.com/selectable/). Thanks for your help!

You can get the list of selected items with $('.ui-selected', this). Use .map() on it to get an array of selected indexes. Then you can iterate of the sections and set their visibility depending on whether their index is in that array.
If you want multiple sections to appear at the same time, you'll have to abandon the current absolute position you have for them, and just use visibility (display) to show or hide them. That way they will not take space unless they are visible, and when you have more than one visible, they will not overlap.
So change the CSS as follows:
For .tabcontent replace this:
position:absolute;
opacity:0;
with this:
display:none;
And then use this code:
$(function() {
// define one function, to be used for both select/unselect
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);
});
}
$("#selectable").selectable();
$("#selectable").selectable({
selected: selectionChange,
unselected: selectionChange
});
});
Of course, this is just a starting point. Right now, when you select many sections, they will flow out of your green box. So depending on what you are actually going to show, you will need to play with the CSS to make it render nicely.
$(function() {
// define one function, to be used for both select/unselect
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);
});
}
$("#selectable").selectable();
$("#selectable").selectable({
selected: selectionChange,
unselected: selectionChange
});
});
*{
font-family: 'Josefin Sans', sans-serif;
margin: 0;
padding: 0;
}
#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;
}
#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;}
}
#content{
width:60%;
background-color:#9eefbc;
height:500px;
margin-left:20%;
}
.tabcontent{
width:60%;
top:44px;
height:100px;
display:none; /* no abs position, no opacity:0 */
background-color:transparent;
z-index:0;
transition:.3s ease-in-out;
text-align:center;
font-size:5em;
padding-top:100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<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">1</section>
<section class="tabcontent">2</section>
<section class="tabcontent">3</section>
<section class="tabcontent">4</section>
<section class="tabcontent">5</section>
<section class="tabcontent">6</section>
</div>

Related

Is there any way to set CSS animation to work differently on e.g. button On / Off?

I am in a situation where I want to animate mobile navigation. User clicks on a burger and the nav slides down, by clicking on any link or the burger itself nav slides back up.
Till this day I solved this by making 2 divs where first has
display: block; with animation to slide down and the another has display: none; with animation to slide up. After clicking on burger these two options would switch and that will do the thing.
It works just fine, however, I think it can be done with less code.
Something like this?
This uses the css transition property to animate the sliding.
document.getElementById("toggle").addEventListener("click", e => {
document.getElementById("menu").classList.toggle("menu-hidden");
});
body {
margin: 0;
}
.menu {
height: 300px;
width: 100%;
background-color: lightgreen;
transition: all 0.5s;
overflow: hidden;
}
.menu-hidden {
height: 0;
}
<button id="toggle">Toggle menu</button>
<div class="menu" id="menu">Menu content</div>
Please try this. Make click () event to assign ON & OFF value to button.
function onoff(){
currentvalue = $('#onoff').val();
if(currentvalue == "Off"){
$('#onoff').val("On");
}else{
$('#onoff').val("Off")
}
}
</script>
<input type="button" value="On" id="onoff" onclick="onoff();"> ```
Here is another method. This simply makes it so the menu is positioned out of the screen using transform translate, transitions and z-index, and on hamburger click it toggles the menu to slide down to its original position. I have also added functionality so that menu items, on click, will also toggle the menu slide.
document.getElementById("hamburger").addEventListener("click", e => {
document.getElementById("menu").classList.toggle("slide");
});
Array.from(document.getElementsByClassName("menu-item")).forEach((item) => {
item.addEventListener("click", function() {
document.getElementById("menu").classList.toggle("slide");
});
}
);
body {
box-sizing: border-box;
margin: 0;
padding: 0;
}
nav {
position: relative;
background: #fff;
z-index: 2;
}
#menu {
background: lightblue;
margin: 0;
padding: 0;
position: absolute;
z-index: 1;
transform: translateY(-100%);
transition: 0.3s ease-in-out;
}
#menu li {
list-style: none;
padding: 0.5rem 1rem;
cursor: pointer;
}
.slide {
transform: translateY(0) !important;
transition: 0.3s ease-in-out;
}
<nav>
<button id="hamburger">Toggle</button>
</nav>
<ul id="menu">
<li class="menu-item">Link 1</li>
<li class="menu-item">Link 2</li>
<li class="menu-item">Link 3</li>
</ul>

jQuery circle menu navigation creating tiny circle after toggle close

when I click on the main circle the surrounding 5 circles will get minimized completely( to 100% hide), but those are not minimizing completely. There is a small circle over the main circle after minimizing. How to completely minimize (hide) the tiny circle on top of the main circle after toggle close.
I have tried jQuery hide but it was hiding entire element,
Below is the jQuery code,
var nbOptions = 8;
var angleStart = -360;
// jquery rotate animation
function rotate(li,d) {
$({d:angleStart}).animate({d:d}, {
step: function(now) {
$(li)
.css({ transform: 'rotate('+now+'deg)' })
.find('label')
.css({ transform: 'rotate('+(-now)+'deg)' });
}, duration: 0
});
}
// show / hide the options
function toggleOptions(s) {
$(s).toggleClass('open');
var li = $(s).find('li');
var deg = $(s).hasClass('half') ? 180/(li.length-1) : 360/li.length;
for(var i=0; i<li.length; i++) {
var d = $(s).hasClass('half') ? (i*deg)-90 : i*deg;
$(s).hasClass('open') ? rotate(li[i],d) : rotate(li[i],angleStart);
}
}
$('.selector button').click(function(e) {
toggleOptions($(this).parent());
});
setTimeout(function() { toggleOptions('.selector'); }, 100);
http://jsfiddle.net/adzFe/2574/
You do need to remove the border and padding inside .selector.open li input + label but you can toggle on and off with another class.
.open1 {
padding: 6px;
border:1px solid #999;
}
Add this JS:
function toggleOptions(s) {
$(s).toggleClass('open');
var li = $(s).find('li');
li.find("label").toggleClass("open1"); // NEW
...
}
Fiddle: http://jsfiddle.net/adzFe/2576/
I agree, the mini circle is caused by extra padding at wrong class, I have moved the padding to the selector.open. Now it is not showing any mini circle.
.selector li input + label {
position: absolute;
left: 50%;
bottom: 120%;
width: 0;
height: 0;
margin-left: 0;
background: #fff;
border-radius: 50%;
text-align: center;
overflow: hidden;
cursor: pointer;
background:#eee;
transition: all 0.8s ease-in-out, color 0.1s, background 0.1s;
}
.selector li input + label img {
border-radius:50%;
}
.selector.open li input + label {
width: 90px;
height: 90px;
margin-left: -40px;
padding:6px;
border:1px solid #999;
box-shadow: 0 3px 3px rgba(0, 0, 0, 0.1);
}
.selector.open li input + label:hover {
border:1px solid #fff;
padding:6px;
background:#fff;
}
.mainimage{
width:100%;
height:100%;
border-radius:50%;
}
Working code
http://jsfiddle.net/adzFe/2577/
Looks like the problem is in your CSS .selector li input + label rule. You still have some padding and border width in this rule which is giving the circles some size. Change those 2 values to 0 and they should completely hide:
.selector li input + label {
position: absolute;
left: 50%;
bottom: 120%;
width: 0;
height: 0;
margin-left: 0;
background: #fff;
border-radius: 50%;
text-align: center;
overflow: hidden;
cursor: pointer;
border:0 solid #999; /* previously 1px */
padding:0; /* previously 6px */
background:#eee;
transition: all 0.8s ease-in-out, color 0.1s, background 0.1s;
}
Update:
Since the padding and border are needed, you can adjust your ruleset to have these values while the menu circles have the open class and remove them when the class is not present
http://jsfiddle.net/avt0fvk4/

closing a jquery popup when a element is already active

I got quite a bit of help from another great user on this site already, am curious if someone could help with one more question on this code.
this is essentially where I am at.
one hovers the gray boxes to highlight an element on the screen. when one gray element is clicked a blue box appears, and the highlighted element stays as well. if the new blue element is clicked, the red box goes away and the blue box go away, and the hovers function accordingly after. if one element is active, and I want to click the other gray element, currently, another new element pops in, giving me two blue boxes. I only want the corresponding blue box active at a time. so if element 1 blue box is active, I want to click element 2, and deactivate blue box 1, while activating blue box 2.
here is I am currently at
html
<div class="bg">1</div>
<div class="bg2">1</div>
<div class="bgpopup">1</div>
<div class="bg">2</div>
<div class="bg2">2</div>
<div class="bgpopup">2</div>
css
.bg {
background: #ccc;
width: 200px;
height: 120px;
}
.bg:hover {
background: #000;
}
.bg2 {
position:absolute; top:250px;
left:250px;
background: red;
width: 200px;
height: 120px;
display:none;
}
.bgpopup {
background: blue;
width: 200px;
height: 120px;
display:none;
}
script
$(".bg").each(function(){
var $bg = $(this);
var $bg2 = $bg.nextAll('.bg2:first');
var $bgP = $bg.nextAll('.bgpopup:first');
$bg.data("activated", 0).hover(function(){
if($bg.data("activated") === 0) $bg2.toggle();
}).click(function(){
$bg.data("activated", 1);
$bgP.show().on("click", function(){
$bg.data("activated", 0);
$bg2.add( this ).hide();
});
});
});
with link http://jsfiddle.net/skinnyb/0vvk945y/8/
In that case and knowing that the HTML will not be changed in the future (cause the order is important!) I'd do it almost all using CSS's + next-sibling selector.
Regarding jQuery i'd keep it at the minimum and use it exclusively to toggle CSS classes:
var $bg = $(".bg"); // Cache all buttons
$(".bg").on("click", function(){
$bg.removeClass("active");
$(this).addClass("active");
});
$(".blue").on("click", function(){
$bg.removeClass("active");
});
.bg {
background: #ccc;
margin-top: 10px;
width: 200px;
height: 120px;
transition:0.3s;
}
.bg:hover {
background: #000;
}
.red {
position: absolute;
top: 250px;
left: 250px;
background: red;
width: 200px;
height: 120px;
visibility:hidden;
transition: 0.3s;
cursor:pointer;
opacity: 0;
}
.bg:hover + .red{
visibility: visible;
z-index:2; /* prioritize (overlay) hovered - over active ones*/
opacity: 1;
}
.bg.active + .red{
visibility: visible;
z-index:1; /* keep below hovered ones */
opacity: 1;
}
.bg.active + .red + .blue{
display: block;
}
.blue {
background: blue;
width: 200px;
height: 120px;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bg">1</div>
<div class="red">1</div>
<div class="blue">1</div>
<div class="bg">2</div>
<div class="red">2</div>
<div class="blue">2</div>
PS: I've used other classNames to prevent headaches. Usually a popup shows at the screen center, not below some other element like you did... Feel free to edit my classes as you need.
Try hiding both blue's before one appears to ensure there is only one at a time:
jsfiddle.net/2sxy9mzw/
All I did was added one line before $bg.data("activated", 1);
which was:
$('.bgpopup').hide();

Hover effect disappear after calling function through button

I have the following code which works only that not as I desire:
HTML:
<div class="horizontal-ribbon">
<div class="list" id="pseudoCheckBoxes">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
</div>
<input type="button" id="but" value="next" onclick="check()">
CSS:
.horizontal-ribbon {
padding: 8px 8px 8px 8px;
background: #d6dbdf;
}
.list {
position:relative;
}
.list ul {
display:inline-block;
background:#d6dbdf;
margin:0;
padding:0;
border-radius:0px;
color:#ffffff;
}
.list ul li {
cursor: pointer;
cursor: hand;
display:inline-block;
vertical-align:middle;
border-radius: 50%;
width:14px;
height:14px;
padding:0px;
background:#fff;
border: 5px solid #d6dbdf;
color: #ffffff;
text-align:center;
font: 700 13px"Lato", Helvetica, Arial sans-serif;
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-transition: background 0.2s ease-out, border-color 0.2s ease-out;
transition: background 0.2s ease-out, border-color 0.2s ease-out;
}
.list ul li:first-child {
margin-left: 20px;
}
.list ul li:last-child {
margin-right: 20px;
}
.list ul li:hover {
background:#1abc9c;
border-color:#1abc9c;
}
JAVASCRIPT:
function check() {
element = document.getElementById("pseudoCheckBoxes");
items = element.getElementsByTagName("LI");
items[0].style.backgroundColor = "#1abc9c";
items[0].style.borderColor = "#1abc9c";
setTimeout(function () {
uncheck()
}, 2000);
}
function uncheck() {
element = document.getElementById("pseudoCheckBoxes");
items = element.getElementsByTagName("LI");
items[0].style.backgroundColor = "white";
items[0].style.borderColor = "#d6dbdf";
}
I wish to control that effect both from button press and by hovering the mouse of <li> elements.
The hover effect works well but after I click the button next the hover effect disappears and I don't know why. Please be kind and help me (http://jsfiddle.net/xfpyM/).
You are applying :hover effect using CSS hover and adding inline style after clicking the next button.
You can try doing it by adding class.
Here is the demo
JS
function check(){
element=document.getElementById("pseudoCheckBoxes");
items=element.getElementsByTagName("LI");
items[0].className ="active";
setTimeout(function(){uncheck()}, 2000);
}
function uncheck(){
element=document.getElementById("pseudoCheckBoxes");
items=element.getElementsByTagName("LI");
items[0].className=" ";
}
CSS
.list ul li.active,
.list ul li:hover{
background:#1abc9c;
border-color:#1abc9c;
}
Your uncheck function have some error. Instead of removing style attribute you are adding different styels. So the actual hover style not applying.
Instead of this
function uncheck() {
element = document.getElementById("pseudoCheckBoxes");
items = element.getElementsByTagName("LI");
items[0].style.backgroundColor = "white";
items[0].style.borderColor = "#d6dbdf";
}
Use like this.
function uncheck() {
element = document.getElementById("pseudoCheckBoxes");
items = element.getElementsByTagName("LI");
items[0].removeAttribute("style");
}
DEMO

Struggling to understand jquery - Fade in/out a class on mouseover

I'm currently trying to learn jQuery and JavaScript, and for my navigation I'm trying to make it look underlined on mouseover which, although it might not be the cleaned of code, I have managed to do it using a addClass and removeClass.
I am now trying to make the underline class fade in and fade out, which I believe is something normally done with CSS3 but due to just trying to learn jquery, I've been trying to figure it out.
I've tried putting .fadeIn() and .fadeOut() in different places in the code, but nothing seems to work, so I'm assuming this is not the correct way to do it.
Here's my code
HTML
<div class="navleft">
<ul>
<li class="active">Home</li>
<li class="active1">Dealerships</li>
<li class="active1">Contact</li>
</ul>
</div>
CSS
.navleft ul li.active1 {
border-width: 0 0 1px 0;
border-color: #999;
border-style: solid;
cursor: pointer;
}
.navleft ul li.active {
border-width: 0 0 1px 0;
border-color: #999;
border-style: solid;
cursor: pointer;
}
Javascript
$(function(){
$('.navleft ul li').removeClass('active1');
$('.navleft ul li').mouseover(function(){
$(this).addClass('active1');
});
$('.navleft ul li').mouseout(function(){
$(this).removeClass('active1');
})
});
If anyone could help, that would be great, as I'm really stuck on this one.
Classes can't fade in or out. fadeIn and fadeOut are for the opacity of elements. If you actually want to ›fade‹ a style you have to either write your own animation code (which I wouldn't recommend) or use CSS3 transitions, which I would recommend anyways.
Here's a CSS way to smoothly transition from one border to another on hovering: http://jsfiddle.net/u4h7k/2/.
HTML:
<ul id = "nav">
<li>Home</li>
<li>Dealerships</li>
<li>Contact</li>
</ul>
CSS:
#nav > li {
position: relative;
cursor: pointer;
}
#nav > li:before, #nav > li:after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
border-bottom: 1px solid blue;
opacity: 0;
-webkit-transition: opacity 0.5s linear;
transition: opacity 0.5s linear;
}
#nav > li:after {
border-bottom: 1px solid red;
opacity: 1;
}
#nav > li:hover:after {
opacity: 0;
}
#nav > li:hover:before {
opacity: 1;
}

Categories

Resources