jQuery — выберите и сгруппируйте набор элементов по контейнеру

#javascript #jquery #html #jquery-selectors

#javascript #jquery #HTML #jquery-селекторы

Вопрос:

Мне нужно выбрать и сгруппировать набор ссылок на изображения на основе их <DIV> или <UL> контейнера.

Например, в этом HTML: выберите первые две ссылки, прикрепите к ним мою функцию, выберите следующие две ссылки, запустите функцию … и так далее

 DIV
  LINK
  LINK

  DIV
    LINK
    LINK

    UL
      LINK
      LINK
    /UL

  /DIV

  UL
    LINK
    LINK
  /UL

/DIV

LINK
LINK

...
  

(каждый div / ul может иметь любое количество ссылок)

Прямо сейчас у меня есть это:

 $('div').each(function(index){
  var elements = $(this).find('a').filter(function(){
    return !!this.href.match('(.jpg|.jpeg|.png|.gif)$');
  });

  console.log('------'   index   '------');
  console.log(elements);
});
  

который отфильтровывает ссылки только на те, которые являются изображениями.
но на самом деле это не группирует их так, как я хочу, и моя функция выполняется более одного раза для одного и того же элемента…

Есть предложения?

Комментарии:

1. Каков ваш конечный результат? Не могли бы вы просто сделать $("a").filter(function(){}).DoSomething() ?

2. да, но мне нужен какой-то уникальный идентификатор для каждой группы ссылок, я бы предпочел использовать index из div / ul…

Ответ №1:

Поскольку у вас, вероятно, есть элементы между DIV / UL и A, такие как LI, вы можете начать с выбора A и «сгруппировать» их:

 var groups =  [];
$('a')
  .filter(function(){ return !!this.href.match('(.jpg|.jpeg|.png|.gif)$'); })
  .map(function(idx,el) { return [$(this).closest("div, ul"), $(this)]; })
  .each(function(idx,el) { 
        var c= el[0];
        var imglink = el[1];
        if(!c.data("groupId")) {
           c.data("groupId", groups.length);
           groups.push({ "container": c, "links": [] });
        }
        groups[c.data("groupId")].links.push(imglink);
  });

// optional: remove the "groupId" data() from the container DOM elements:
$.each(groups, function(idx,el) { el.container.data("groupId", null); });
  

Ответ №2:

Если вам просто нужно сгруппировать вещи вместе, возможно, что-то вроде этого подойдет для вас.

 $("div, ul, body").each(function(index, elm) {
    $(elm).children("a").text(function(i, text) {
        return text   "index: "   index;
    });
    $(elm).children("li").children("a").text(function(i, text) {
        return text   "index: "   index;
    });
});
  

С вашей разметкой:

 <DIV>
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
    <DIV>
        <a href="#">Link 3</a>
        <a href="#">Link 4</a>
        <UL>
            <li><a href="#">Link 5</a></li>
            <li><a href="#">Link 6</a></li>
        </UL>
    </DIV>
    <UL>
        <li><a href="#">Link 7</a></li>
        <li><a href="#">Link 8</a></li>
    </UL>

</DIV>
<a href="#">Link 9</a>
<a href="#">Link 10</a>
  

Приведет к следующему:

 Link 1index: 1 Link 2index: 1
Link 3index: 2 Link 4index: 2
Link 5index: 3
Link 6index: 3
Link 7index: 4
Link 8index: 4
Link 9index: 0 Link 10index: 0
  

Ответ №3:

Нельзя ли использовать селектор с дочерним свойством?

ie:

 $('div, ul').each(function(index){
    var elements = $(this).child('a');
    //run foreach on elements
});
  

Выше будут выбраны все divs и uls (возможно, потребуется применить определенный стиль или что-то еще здесь, чтобы выбрать только те, которые вы хотите), затем он получит дочерние элементы a.

Ответ №4:

Я думаю, это то, что вы хотите, но я не уверен точно, что вы хотите сделать с элементами:

    $('div > img').each(function(index) {

      if ((index % 4) === 1)
        // do something to every first element in a group of 4
      if ((index % 4) === 2)
        // do something to every second element in a group of 4
      if ((index % 4) === 3)
        // do something to every third element in a group of 4
      if ((index % 4) === 0)
        // do something to every fourth element in a group of 4
   });