Селектор jquery перебирает детей, затем перебирает родителей / братьев и сестер - PullRequest
0 голосов
/ 22 августа 2011

Ниже приведен упрощенный HTML-код:

<div id="coat">
<span class="Jan2011-Sales">10</span>
<span class="Feb2011-Sales">10</span>
<span class="Mar2011-Sales">10</span>
</div>

<div id="boot">
<span class="Jan2011-Sales">10</span>
<span class="Feb2011-Sales">10</span>
<span class="Mar2011-Sales">10</span>
</div>

<div id="hat">
<span class="Jan2011-Sales">10</span>
<span class="Feb-Sales">10</span>
<span class="Mar2011-Sales">10</span>
</div>

<div id="etc.">
</div>

РЕДАКТИРОВАНИЕ:

Я хотел бы создать таблицу, как показано ниже: (почти как сводная таблица)

   <th>
       <td>Period</td>
       <td>Coat</td>
       <td>Boot</td>
       <td>Hat</td>
   </th>
   <tr>
       <td>Jan2011-Sales</td>
       <td>10</td>
       <td>10</td>
       <td>10</td>
   <tr>
   <tr>
       <td>Feb2011-Sales</td>
       <td>10</td>
       <td>10</td>
       <td>10</td>
   <tr>
   etc.

Мой вопрос - как перебрать исходный HTML?Например, мое мышление состоит в том, чтобы перебирать первые элементы, чтобы получить строки, а затем получать дочерний элемент родителя, чтобы я мог найти / сопоставить его дочерний элемент для получения столбцов.

Мысли?СПАСИБО.

Ответы [ 4 ]

5 голосов
/ 22 августа 2011

Вот jsFiddle, который берет ваши HTML-данные и составляет из них таблицу: http://jsfiddle.net/jfriend00/RKBAj/.

Делая эти предположения:

  1. Каждый элемент верхнего уровня в документе является продуктом
  2. У каждого элемента верхнего уровня есть идентификатор, представляющий название продукта
  3. Каждый интервал в div верхнего уровня - это месяц
  4. Каждый диапазон в div верхнего уровня имеет класс, представляющий название продукта
  5. innerHTML диапазона - это данные для этого продукта / месяц
  6. Имена продуктов могут быть любыми (хотя они должны быть сделаны только из наших допустимых символов для идентификатора CSS).
  7. Названия месяцев могут быть любыми (хотя они должны быть сделаны только из наших допустимых символов для класса CSS).
  8. Может быть столько месяцев и продуктов, сколько вы хотите.
  9. Каждый продукт может иметь любое количество месяцев.
  10. Все продукты не обязательно должны иметь одинаковые месяцы.

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

// iterate over divs which we assume are products
var allProducts = [];
var allMonthsOrder = [];
function parseData() {
    $("body > div").each(function() {
        var allMonthsKey = {};
        var product = {};
        product.name = this.id;
        product.months = {};
        // now iterate each month in this product
        $("span", this).each(function() {
            var month = this.className;
            product.months[month] = this.innerHTML;
            // add unique months to the month array (only if we haven't seen it before)
            if (!allMonthsKey[month]) {
                allMonthsKey[month] = true;
                allMonthsOrder.push(month);     // store these in order encountered
            }
        });
        allProducts.push(product);
    });
}


// data is stored now in allProducts array
// one array element for each product
// each product is an object with a .name attribute and a .months attribute
// each .months attribute is an object where each attribute is a month name and the data for that month

Данные хранятся так:

allProducts = [
    {
        "name": "coat", 
        "months": {"Jan2011-Sales": "10", "Feb2011-Sales": "10", "Mar2011-Sales": "10"}, 
        ]
    },
    {
        "name": "boot", 
        "months": {"Jan2011-Sales": "10", "Feb2011-Sales": "10", "Mar2011-Sales": "10"}, 
    },
    {
        "name": "hat", 
        "months": {"Jan2011-Sales": "10", "Feb2011-Sales": "10", "Mar2011-Sales": "10"}, 
    }
];

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

function createTable() {
    var i, j, product, month;
    var html = "<table><tr>";
    // iterate over the product names to make the header row
    html += "<th>Month</th>";
    for (i = 0; i < allProducts.length; i++)
        html += "<th>" + allProducts[i].name + "</th>";
    }
    html += "</tr">

    // now create all the rows.  First column is month, then each column after that is the sales for 
    // a given month for a particular product (one product per columnn)

    for (i = 0; i < allMonthsOrder.length; i++) {
        month = allMonthsOrder[i];
        html += "<tr>" + "<td>" + month + "</td>";
        // iterate through each product and find if it has data for this month
        for (j = 0; j < allProducts.length; j++) {
            product = allProducts[j];
            html += "<td>";
            if (product.months[month]) {
                html += product.months[month];
            }
            html += "</td>";
        }
        html += "</tr>";
    }
    html += "</table>";
}
2 голосов
/ 22 августа 2011
var snippet = ['<table><thead><tr><th>Name</th><th>Jan-Sales</th><th>Feb-Sales</th><th>Mar-Sales</th></tr></thead><tbody>'];

$('div').each(function()
{
    snippet.push('<tr><td>' + $(this).attr('id') + '</td>');

    $(this).find('span').each(function()
    {
        snippet.push('<td>' + $(this).text() + '</td>');
    });

    snippet.push('</tr>');
});

snippet.push('</tbody></table>');

$('body').html( snippet.join('') );

http://jsfiddle.net/eqfEE/


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

При объединении строк JavaScript отбрасывает старую строку и создает новую.Это приводит к тому, что создается и уничтожается слишком много объектов.

С другой стороны, при использовании .push() старый массив никогда не отбрасывается;JavaScript просто добавляет новый элемент в конец массива ...


Теперь, когда вы обновили свой вопрос и пояснили, что хотите, чтобы названия продуктов были в качестве заголовков таблиц, вы должны сделать следующее:

var productsInfo = {},
    periods = [],
    countProducts = 0,
    countPeriods = 0,
    i,
    snippet = ['<table><thead><tr><th>Period</th>'];

$('div').each(function()
{
    var $this = $(this),
        productName = $this.attr('id'),
        periodsCounted = false;

    productsInfo[productName] = [];

    countPeriods = Math.max($(this).find('span').each(function()
    {
        productsInfo[productName].push( $(this).text() );

        if (!periodsCounted) periods.push( $(this).attr('class') );
    })
    .length, countPeriods);

    periodsCounted = true;
});

for ( var productName in productsInfo )
{
    snippet.push('<th>' + productName + '</th>');
    countProducts++;
}

snippet.push('</tr></thead><tbody>');

for(i = 0; i < countPeriods; i++)
{
    snippet.push('<tr><th>' + periods[i] + '</th>');

    $.each(productsInfo, function(index, e)
    {
        snippet.push('<td>' + e[i] + '</td>');
    });

    snippet.push('</tr>');
}

snippet.push('</tbody></table>');

$('body').html(snippet.join(''));

С помощью скрипта здесь: http://jsfiddle.net/eqfEE/1/

Примечание: этот код может быть улучшен.Это просто толчок в правильном направлении.

0 голосов
/ 22 августа 2011

Для выбора я использовал 2 цикла, примерно так:

 // first loop, get all the "months" from the first div/product
 $("div#coat").each(function(idxMonth) 

 // second loop, get all the products and look for the matching "month"
 $(this).parent().siblings().children('div' + monthClassSelector).each(function(idxSiblingMonth) {

 // where monthClassSelector is something like "Jan2011-Sales" that we got from the 1st loop
0 голосов
/ 22 августа 2011

Для совершенно другого взятия вы можете взять существующий HTML и отобразить его с колонкой для каждого продукта, просто указав этот CSS:

#coat, #boot, #hat {float: left;}
.Jan-Sales, .Feb-Sales, .Mar-Sales {display: block; margin: 10px;}

В этом столбце будет отображаться деление продуктов слева направо и месяцы сверху вниз.

Вы можете увидеть это здесь: http://jsfiddle.net/jfriend00/V6Dnm/

Очевидно, что вы можете использовать больше CSS-форматирования для форматирования его в виде таблицы (разделители, соответствующий интервал). Кроме того, вы можете использовать JS для размещения заголовков столбцов или строк.

...