jquery选择器迭代子进程,然后迭代父/兄弟

时间:2011-08-22 00:39:10

标签: jquery iterator selector parent-child

我在下面有以下简化的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? 例如我的想法是迭代第一个元素来获取行,然后获取父级的兄弟div,以便我可以找到/匹配其子元素来获取列。

思考? 谢谢你。

4 个答案:

答案 0 :(得分:5)

这是一个jsFiddle,可以获取HTML数据并从中创建一个表格:http://jsfiddle.net/jfriend00/RKBAj/

做出这些假设:

  1. 文档中的每个顶级div都是产品
  2. 每个顶级div都有一个代表产品名称的ID
  3. 顶级div中的每个跨度都是一个月
  4. 顶级div中的每个范围都有一个代表产品名称的类
  5. span的innerHTML是该产品/月的数据
  6. 产品名称可以是任何名称(尽管只需要为CSS ID设置我们的合法字符)。
  7. 月份名称可以是任何内容(尽管必须只为CSS类制作我们的合法字符。)
  8. 可以有多少个月和产品。
  9. 每种产品可以有任意数月。
  10. 所有产品的月份不一定相同。
  11. 然后,这里是你如何迭代数据并将所有数据收集到一个有组织的数据结构中,你可以从中构建一个表。

    // 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>";
    }
    

答案 1 :(得分:2)

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/

注意:此代码可以改进。这只是朝着正确方向的推动。

答案 2 :(得分:0)

对于完全不同的观点,您可以通过简单地指定此CSS来获取现有HTML并将其显示为每个产品的列:

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

这将在每个产品列中从左到右布置产品div,从上到下布置月份。

您可以在此处查看:http://jsfiddle.net/jfriend00/V6Dnm/

显然,您可以使用更多的CSS格式将其格式化为表格(分隔符,适当的间距)。而且,您可以使用JS在其上放置列或行标题。

答案 3 :(得分:0)

为了做选择,我最终使用了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