0

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!

Tobias Glaus
  • 3,008
  • 3
  • 18
  • 37

1 Answers1

1

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>
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thanks alot for your answer! This works exactly as i want. I am aware that I have to change the CSS so it gets display nicely. But you mentioned that I have to create an array with the selected indexes. But where do you create an array in your code? I thought arrays are surrounded with var arrayname = `[1, 2, 3, 4, ...]` but I cant see any of these in the code. – Tobias Glaus Feb 18 '17 at 16:09
  • The jQuery `.get()` method returns an array. In fact it converts a jQuery collection to a plain array. It is a bit awkward, but jQuery `.map` returns another jQuery object, even though it consists in this actual case only of indexes, not DOM elements. To make it a plain array, you need `.get()`. – trincot Feb 18 '17 at 16:12
  • So: `$('.ui-selected', this)` returns a jQuery object with the selected DOM elements, then `.map(...)` turns that into a jQuery object of the indexes of those DOM elements, and finally `.get()` turns that into a plain array of those indexes. That result is then assigned to the variable `items`. – trincot Feb 18 '17 at 16:16
  • Ah didn't know that `.get()` creates an array. Thanks alot for your help! – Tobias Glaus Feb 18 '17 at 16:37
  • Sorry for spamming you :D But when I log the variable 'items', its like this `[0]` `[0, 1]` `[0, 1, 2]` when 1, 2 and 3 are selected. Can I somehow get the average of the last logged array `[0, 1, 2]` ? So I can center that triangle of the bottom of the selected tabs. Now there are just 3 different triangles. – Tobias Glaus Feb 18 '17 at 16:48
  • See [this answer](http://stackoverflow.com/a/29544442/5459839) on how to get the average from an array of numbers. – trincot Feb 18 '17 at 17:16