sfarzoso
sfarzoso

Reputation: 1610

Get all previous items in list based on specific value?

I have this list:

<ul id="tabs-list" class="nav nav-pills">
   <li class="nav-item" style="width: 25%;"><a class="nav-link checked" href="#registry" data-toggle="tab"></a></li>
   <li class="nav-item" style="width: 25%;"><a class="nav-link checked" href="#tab1" data-toggle="tab" data-question-id="1"><i class="tim-icons icon-bulb-63"></i></a></li>
   <li class="nav-item" style="width: 25%;"><a class="nav-link checked active show" href="#tab2" data-toggle="tab" data-question-id="3"><i class="tim-icons icon-bulb-63"></i></a></li>
   <li class="nav-item" style="width: 25%;"><a class="nav-link" href="#tab3" data-toggle="tab" data-question-id="2"><i class="tim-icons icon-bulb-63"></i></a></li>
</ul>

As you can see I have the third element tab#2 which has the class active. My goal is to take all the data-question-id that are located before the active item.

The output should be: ["1"] because before the tab2 there is just one item with that attribute.

I can easily get the active item using this code:

var active_id = Number($(".tab-pane.active").attr('data-question-id'));

But how can I get all the previous item of the active item?

Upvotes: 1

Views: 422

Answers (3)

Mamun
Mamun

Reputation: 68923

You can use some built in jQuery methods to achieve the output.

.parent()

Get the parent of each element in the current set of matched elements, optionally filtered by a selector.

.prevAll()

Get all preceding siblings of each element in the set of matched elements, optionally filtered by a selector.

.filter()

Reduce the set of matched elements to those that match the selector or pass the function's test.

.get()

Retrieve the DOM elements matched by the jQuery object

and .map() like the following way:

var active_id = $('.active').parent().prevAll().filter(function() {
    return $(this).find('a').attr('data-question-id');
}).get().map(el => $(el).find('a').attr('data-question-id'));

console.log(active_id);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="tabs-list" class="nav nav-pills">
   <li class="nav-item" style="width: 25%;"><a class="nav-link checked" href="#registry" data-toggle="tab"></a></li>
   <li class="nav-item" style="width: 25%;"><a class="nav-link checked" href="#tab1" data-toggle="tab" data-question-id="1"><i class="tim-icons icon-bulb-63"></i></a></li>
   <li class="nav-item" style="width: 25%;"><a class="nav-link checked active show" href="#tab2" data-toggle="tab" data-question-id="3"><i class="tim-icons icon-bulb-63"></i></a></li>
   <li class="nav-item" style="width: 25%;"><a class="nav-link" href="#tab3" data-toggle="tab" data-question-id="2"><i class="tim-icons icon-bulb-63"></i></a></li>
</ul>

Upvotes: 1

jo_va
jo_va

Reputation: 13973

Here is a way to do it with pure JS in the functional style.

You query all selectors with the attribute data-question-id. Then you map this array to an array of objects with the questions ids and a boolean indicating if these elements hold the active class.

Then you find the index of the first object with active = true and you slice the array to get all the previous questions ids.

const questions = Array.from(document.querySelectorAll('a[data-question-id]'))
  .map(elem => ({
      id: elem.getAttribute('data-question-id'),
      active: elem.classList.contains('active')
   }));
  
const result = questions
    .slice(0, questions.findIndex(elem => elem.active))
    .map(elem => elem.id);
  
console.log(result)
<ul id="tabs-list" class="nav nav-pills">
   <li class="nav-item" style="width: 25%;"><a class="nav-link checked" href="#registry" data-toggle="tab"></a></li>
   <li class="nav-item" style="width: 25%;"><a class="nav-link checked" href="#tab1" data-toggle="tab" data-question-id="1"><i class="tim-icons icon-bulb-63"></i></a></li>
   <li class="nav-item" style="width: 25%;"><a class="nav-link checked active show" href="#tab2" data-toggle="tab" data-question-id="3"><i class="tim-icons icon-bulb-63"></i></a></li>
   <li class="nav-item" style="width: 25%;"><a class="nav-link" href="#tab3" data-toggle="tab" data-question-id="2"><i class="tim-icons icon-bulb-63"></i></a></li>
</ul>

Upvotes: 2

ymz
ymz

Reputation: 6924

Something like that?

var prevs = []
$(".tab-pane.active").each(function()
{
    if ($(this).attr('data-question-id') == active_id)
    {
        // Do something with previous elements

        prevs = null; // empty array
    }
    else if (prevs)
    {
        prevs.push($(this));
    }
})

Upvotes: 1

Related Questions