Как я могу сгруппировать коллекцию элементов по их смежности? - PullRequest
4 голосов
/ 19 января 2012

Допустим, у меня есть список, который выглядит так:

<ul>
    <li id="q"></li>
    <li id="w"></li>
    <li id="e"></li>
    <li id="r"></li>
    <li id="t"></li>
    <li id="y"></li>
    <li id="u"></li>
    <li id="i"></li>
    <li id="o"></li>
</ul>

Мне нужно сделать что-то вроде этого:

function get_important_elements() {
    // completely contrived;
    // elements are guaranteed to be contained within same ul
    // but nothing else unique in common (class, attrs, etc)
    return $('#q, #w, #r, #u, #i, #o');
}

function group_adjacent($elems) {
    return $elems; //:(    
}

$(function () {
    var $filtered_list = get_important_elements();

    var groups = group_adjacent($filtered_list);

    // groups should be 
    // (shown by ID here, should contained actual elements contained
    // within jQuery objects): 
    // [$([q, w]), $([r]), $([u, i, o])]
});

Как я мог пойти по этому поводу?

Обратите внимание, что идентификаторы и классы, используемые в списке, вымышлены на 100%. В реальном коде, на котором я это основываю, у меня есть коллекция li элементов, которые являются подмножеством li s, содержащихся в одном ul. Это подмножество определялось их содержанием, которое не важно для рассматриваемого вопроса, а не для класса. Они только разделяют класс в примере для простоты понимания моей мысли.

Ответы [ 3 ]

4 голосов
/ 19 января 2012
function group_adjacent($elems) {
    var rArr = [],
        currArr = $([]);
    $elems.each(function() {
        var $this = $(this);
        currArr = currArr.add($this);
        if (!$elems.filter($this.next()).length) {
            rArr.push(currArr);
            currArr = $([]);
        }
    });
    return rArr;
}

http://jsfiddle.net/adamjford/5q8fZ/3/

1 голос
/ 19 января 2012

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

function groupLis(){
    var el, els = document.getElementsByTagName('li');
    var group = [], groups = [group];

    for (var i=0, iLen=els.length; i<iLen; i++) {
      el = els[i];

      if (hasClass(el, 'true')) {

        if (!group) {
          group = [];
          groups.push(group);
        }
        group.push(el);

      } else if (group && group.length != 0) {
        group = null;
      }
    }
    return groups;
}

// Helper function
function hasClass(el, cName) {
    var re = new RegExp('(^|\\s+)' + cName + '(\\s+|$)');
    return el && re.test(el.className);
}

Редактировать

Хорошо, вот ответ на пересмотренный вопрос: учитывая массив элементов, сгруппируйте их в массивы соседних братьев и сестер.

Обратите внимание, чтоне имеет значения, относятся ли элементы к одному типу, только то, что они являются соседними братьями и сестрами (или нет).

// el is a DOM node
// Returns the next element sibling, or undefined if here isn't one
function getNextSiblingElement(el) {
  while ((el = el.nextSibling)) {
    if (el.nodeType == 1) {
      return el;
    }
  }
}

// els is an array of DOM elements
// Returns an array of sibling element arrays
function groupEls2(els) {
  var el = els[0],
      group = [el],
      groups = [group];

  for (var i=1, iLen=els.length; i<iLen; i++) {
    el = els[i];
    el == getNextSiblingElement(els[i-1])? group.push(el) : groups.push((group = [el]));
  }
  return groups;
}
1 голос
/ 19 января 2012
function group_adjacent($elems) {
    var temp = new Array();
    var i = 0;
    var j = 0;
    var last = null;
    for(i = 0; i < $elems.length; i++) {
         if(last == $elems[i].previousSibling) {
             temp[i][j++] = $elems[i];
         }
         else {
             j = 0;
             temp[i] = new Array();
             temp[i][j++] = $elems[i];
         }
         last = $elems[i];
    }
    return temp;
}  
...