Как я могу сгруппировать коллекцию элементов по их смежности?
Допустим, у меня есть список, который выглядит так:
<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
содержится в одном ul
, Это подмножество определялось их содержанием, которое не важно для рассматриваемого вопроса, а не для класса. Они только разделяют класс в примере для простоты понимания моей точки зрения.
3 ответа
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;
}
Используя обычный сценарий, вы можете получить коллекцию всех LI и перебрать их. Если элемент имеет истинный класс, поместите его в групповой массив. Если следующий элемент имеет класс, поместите его в тот же массив. Если это не так, запустите новый массив. например
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;
}
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;
}