romuleald
romuleald

Reputation: 1434

jQuery merging/filter selector

I want to merge a selector split by another selector.
My actual selector looks like $('.JS_toggle-submenu')

<li class=​"JS_toggle-submenu" data-submenu=​"#submenu-l2-foo">​…​</li>​
<h2 class=​"JS_toggle-submenu" data-submenu=​"#submenu-l2-foo">​…​</h2>​
<p class=​"JS_toggle-submenu" data-submenu=​"#submenu-l3-bar">​…</p>​
<h3 class=​"JS_toggle-submenu" data-submenu=​"#submenu-l3-bar">​…</h3>​

And would like to filter it to the first of each data-submenu like
$('.JS_toggle-submenu').filter('[data=GROUPING]:first')

<li class=​"JS_toggle-submenu" data-submenu=​"#submenu-l2-foo">​…​</li>​
<p class=​"JS_toggle-submenu" data-submenu=​"#submenu-l3-bar">​…</p>​

Of course, I'm not looking for a static solution.
I don't see an efficient way to do this, it seems I need to loop again but I would prefer to avoid, but maybe someone here have a magical solution?

//EDIT:
I need a IE7/8 compatibility, that's why I didn't choose the indexOf solution, but I omitted to explain in my original question.
I compared the both result here http://jsperf.com/filter-loop-or-regex same Ops/sec.

Upvotes: 1

Views: 67

Answers (2)

Taplar
Taplar

Reputation: 24965

Here's using a jquery each loop: http://jsfiddle.net/3y69usxv/

var submenus = [];
var firstMenus = [];

$('.JS_toggle-submenu').each(function(){
    var $this = $(this);

    if (submenus.indexOf($this.data('submenu')) < 0) {
        submenus.push($this.data('submenu'));
        firstMenus.push($this);
    }
});

console.log(firstMenus);

Upvotes: 1

CodingIntrigue
CodingIntrigue

Reputation: 78525

You could filter the IDs out based on an array of objects you'd found before. Something like:

// Array of IDs already found
var existing = [];
// Regex to pull the level number from the data attribute
var regexp = new RegExp("#submenu-l([0-9]+)-(.*?)", "i");
console.log($(".JS_toggle-submenu[data-submenu^='#submenu-l']").filter(function() {
    // Get the ID
    var id = regexp.exec($(this).data("submenu"))[1];
    // If we have already found a DOM element for this level, continue
    if(existing[id]) return false;
    // Otherwise add it to the existing found elements...
    existing[id] = true;
    // Allow it to pass through the filter
    return true;
}).get());

Working Example

Upvotes: 1

Related Questions