-1

I am trying to build a Chrome extension (the intention is, this extension reads a badly coded and formatted table, generates a JSON and replaces the table with a cleaner, prettier table generated from the JSON). The table/script looks as follows (they are executable)

function arrayify(collection) {
  return Array.prototype.slice.call(collection);
}

function factory(headings) {
  return function(row) {
    return arrayify(row.cells).reduce(function(prev, curr, i) {
      prev[headings[i]] = curr.innerHTML ;
      return prev;
    }, {});
  }
}

function parseTable(table) {
  var headings = arrayify(table.tHead.rows[0].cells).map(function(heading) {
    return heading.innerHTML ;
  });
  return arrayify(table.tBodies[0].rows).map(factory(headings));
}
 
var table = document.querySelector("table");
var data  = parseTable(table);
console.log(data);
<!DOCTYPE html>
<html>

<head>
</head>

<body>
    <table>
        <thead>
            <th class="col-sm-2"></th>
            <th class="col-sm-3"></th>
            <th class="col-sm-1">Eats Grass</th>
            <th class="col-sm-1">Eats Fish</th>
            <th class="col-sm-1">Eats Meat</th>
            <th class="col-sm-1">Drinks Wine</th>
        </thead>
        <tbody>
            <tr>
                <td class="td-dark" rowspan="2">Animal</td>
            </tr>
            <tr>
                <td class="td-dark">Cow</td>
                <td class="td-dark">
                    <input checked="checked" disabled="disabled" type="checkbox" />
                </td>
                <td class="td-dark"></td>
                <td class="td-dark"></td>
                <td class="td-dark"></td>
            </tr>
            <tr>
                <td class="" rowspan="9">Mammal</td>
            </tr>
            <tr>
                <td class="">Whale</td>
                <td class="">
                    <input checked="checked" disabled="disabled" type="checkbox" />
                </td>
                <td class="">
                    <input checked="checked" disabled="disabled" type="checkbox" />
                </td>
                <td class=""></td>
                <td class=""></td>
            </tr>
            <tr>
                <td class="">Area 51 Alien</td>
                <td class="">
                    <input checked="checked" disabled="disabled" type="checkbox" />
                </td>
                <td class="">
                    <input checked="checked" disabled="disabled" type="checkbox" />
                </td>
                <td class=""></td>
                <td class="">
                    <input checked="checked" disabled="disabled" type="checkbox" />
                </td>
            </tr>
        </tbody>
    </table>
</body>

</html>

Problem is, as you see, the console JSON is not at all what I am hoping to get. What I do want is:

+-+
+-+
 |
 |
 +------+Animal
 |             +
 |             |
 |             |
 |             |
 |             +----+ Cow
 |                     +
 |                     +-----+ Eats Grass
 +-------+Mammal
               +----+ Whale
               |       +
               |       |
               |       +---+  Eats Grass
               |       |
               |       +---+  Eats Fish
               |
               |
               |
               |
               |
               |
               +-----+ Area 51 Alien
                           +
                           |
                           +-----+
                           |
                           +-----+

The table is huge with around a 100 columns and several sections (like Animal) with multiple, one or no subsections (like Cow, Whale). How can this be done? I know the table is primitive, but changing it is impossible as it is beyond my control.

Edit: The table is malformed. This is the challenge! I cannot fix the table anyway. Therefore I am trying to write an addon to show it properly.

Longer example of table: http://pasted.co/5d779888

Jishan
  • 1,654
  • 4
  • 28
  • 62
  • 2
    `` should have a `` to put those ``s in. Don't read HTML to just create the Object that you want from the data. Then it would have to be reread upon changes. Update only the Object properties as needed. – StackSlave Jul 18 '19 at 23:01
  • I don't see any JSON here. – melpomene Jul 18 '19 at 23:04
  • Table is malformed. Not valid. – JC Hernández Jul 18 '19 at 23:08
  • 1
    Why bother "arrayifying" things instead of just using the DOM tree API? You just get the table and `HTMLElement.children` is already an array of an element's children, so it seems like you could just do that instead. – ocket8888 Jul 18 '19 at 23:10
  • @melpomene I printing the JSON output to console. Instead of writing the schema I drew it for easier understanding – Jishan Jul 18 '19 at 23:11
  • There is no JSON output. Also, what schema? I have no idea what result you're trying to get. – melpomene Jul 18 '19 at 23:11
  • 1
    @melpomene Please run the code snippet - the output is in console. And the target schema is the tree diagram I made at the end of the question. – Jishan Jul 18 '19 at 23:13
  • @ocket8888 The table is malformed, I am skeptic that will not work! – Jishan Jul 18 '19 at 23:26
  • 1
    Well, to be fair, your code already assumes that the table is valid HTML, and that the THEAD contains a set of headers, and that the TBODY contains a set of rows, so you could at least get all that for free. – ocket8888 Jul 18 '19 at 23:34
  • 1
    can you post a longer example table ? – François Huppé Jul 21 '19 at 16:58
  • @FrançoisHuppé Here you go: http://pasted.co/5d779888 – Jishan Jul 21 '19 at 19:09

1 Answers1

2

Ok you may need to add some little tweaks, but i got something:

var json_result = [];

var tds = document.querySelectorAll('td');
var ths = document.querySelectorAll('th');
var current_section = '';
var current_subsection = '';
var current_col = 0;

for(j in tds){
    if(typeof tds[j].innerHTML !== "undefined"){
        if(tds[j].innerHTML.indexOf('<input') > -1){
            // checked box
            json_result[current_section][current_subsection].push(ths[current_col+2].innerHTML);
            current_col++;
        }
        else{
            if(tds[j].innerHTML.indexOf('            ') == -1){
                if(tds[j].attributes.rowspan){
                    //section
                    current_section = tds[j].innerHTML;
                    json_result[current_section] = [];

                }
                else{
                    //subsection
                    current_subsection = tds[j].innerHTML;
                    json_result[current_section][current_subsection] = [];
                    current_col = 0;
                }
            }
            else{
                current_col++;
            }
        } 
    } 
}
console.log(json_result);

With your long table example, this gives me:

{
    "": {
        "Grass Eater": [
            "Grass Eater"
        ]
    },
    "Animal": {
        "Cow": [
            "Grass Eater",
            "Plant Eater",
            "Singer",
            "Wings"
        ],
        "Platypus": [
            "Grass Eater",
            "Plant Eater",
            "Water Drinker",
            "Singer",
            "Wings"
        ],
        "Horse": [
            "Grass Eater",
            "Plant Eater",
            "Singer",
            "Wings"
        ],
        "Alien": [
            "Grass Eater",
            "Plant Eater",
            "Singer"
        ],
        "Doggo": [
            "Grass Eater",
            "Plant Eater",
            "Singer"
        ],
        "Dragon": [
            "Grass Eater",
            "Plant Eater",
            "Singer"
        ],
        "Horse Cart": [
            "Grass Eater",
            "Plant Eater",
            "Singer"
        ],
        "Alligator": [
            "Grass Eater",
            "Plant Eater"
        ]
    },
    "Mammal": {
        "Cow": [
            "Grass Eater",
            "Plant Eater",
            "Singer",
            "Dancer",
            "Someone",
            "Wings"
        ],
        "Platypus": [
            "Grass Eater",
            "Plant Eater",
            "Water Drinker",
            "Singer",
            "Dancer",
            "Someone",
            "LSleepyerally",
            "Running",
            "Out",
            "Of",
            "Now",
            "Vegan",
            "Sausage",
            "Cheese",
            "Nugget",
            "Wings",
            "Foodie",
            "Hoodie",
            "Finished",
            ""
        ],
        "Horse": [
            "Grass Eater",
            "Plant Eater",
            "Singer",
            "Dancer",
            "Someone",
            "Wings"
        ],
        "Alien": [
            "Grass Eater",
            "Plant Eater",
            "Singer",
            "Dancer"
        ],
        "Doggo": [
            "Grass Eater",
            "Plant Eater",
            "Singer",
            "Dancer"
        ],
        "Dragon": [
            "Grass Eater",
            "Plant Eater",
            "Dancer"
        ],
        "Horse Cart": [
            "Grass Eater",
            "Plant Eater"
        ],
        "Alligator": [
            "Grass Eater",
            "Plant Eater"
        ]
    },
    "Marsupial": {
        "Cow": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater",
            "Singer"
        ],
        "Platypus": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater",
            "Water Drinker",
            "Singer"
        ],
        "Horse": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater",
            "Singer"
        ],
        "Alien": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater",
            "Singer"
        ],
        "Doggo": [
            "Grass Eater",
            "Plant Eater",
            "Singer"
        ],
        "Dragon": [
            "Grass Eater"
        ],
        "Horse Cart": [
            "Grass Eater",
            "Plant Eater"
        ],
        "Alligator": [
            "Grass Eater"
        ]
    },
    "Sleepy Mammal": {
        "Cow": [
            "Grass Eater",
            "Fish Eater",
            "Singer",
            "Words",
            "Hoodie"
        ],
        "Platypus": [
            "Grass Eater",
            "Fish Eater",
            "Water Drinker",
            "Singer",
            "Words",
            "Hoodie"
        ],
        "Horse": [
            "Grass Eater",
            "Fish Eater",
            "Singer",
            "Words",
            "Hoodie"
        ],
        "Alien": [
            "Grass Eater",
            "Fish Eater",
            "Singer"
        ],
        "Doggo": [
            "Grass Eater",
            "Fish Eater",
            "Singer",
            "Words",
            "Hoodie"
        ],
        "Dragon": [
            "Grass Eater",
            "Fish Eater",
            "Words",
            "Hoodie"
        ],
        "Horse Cart": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater"
        ],
        "Alligator": [
            "Grass Eater",
            "Fish Eater"
        ]
    },
    "Squsihy": {
        "Cow": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater",
            "Singer"
        ],
        "Platypus": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater",
            "Water Drinker",
            "Singer"
        ],
        "Horse": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater",
            "Singer"
        ],
        "Alien": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater",
            "Singer"
        ],
        "Doggo": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater",
            "Singer"
        ],
        "Dragon": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater"
        ],
        "Horse Cart": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater"
        ],
        "Alligator": [
            "Grass Eater",
            "Plant Eater",
            "Fish Eater"
        ]
    },
    "Plushies": {
        "Cow": [
            "Grass Eater",
            "Plant Eater",
            "Singer",
            "Someone",
            "Running",
            "Out",
            "Of",
            "Fake"
        ],
        "Platypus": [
            "Grass Eater",
            "Plant Eater",
            "Water Drinker",
            "Oil Drinker",
            "Milk Drinker",
            "Singer",
            "Someone",
            "LSleepyerally",
            "Running",
            "Out",
            "Of",
            "Fake",
            "Words",
            "Now",
            "Vegan",
            "Sausage",
            "Cheese",
            "Nugget",
            "Wings",
            "Foodie",
            "Hoodie",
            "Finished",
            ""
        ],
        "Horse": [
            "Grass Eater",
            "Plant Eater",
            "Oil Drinker",
            "Milk Drinker",
            "Singer",
            "Someone",
            "LSleepyerally",
            "Running",
            "Out",
            "Of",
            "Fake",
            "Words",
            "Now",
            "Vegan",
            "Sausage",
            "Cheese",
            "Nugget",
            "Wings",
            "Foodie",
            "Hoodie",
            "Finished",
            ""
        ],
        "Alien": [
            "Grass Eater",
            "Plant Eater"
        ]
    }
}
François Huppé
  • 2,006
  • 1
  • 6
  • 15
  • Can you pretty print it? Every time I try returns a `[]` array. – Jishan Jul 22 '19 at 21:07
  • 1
    This is weird, when i try in the code snippet editor, i get [], but in chrome with a simple html file with the exact same code, i get the output in my answer – François Huppé Jul 23 '19 at 06:19
  • 1
    What do you mean exactly by "pretty print it" ? – François Huppé Jul 23 '19 at 06:21
  • https://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript I tried all the tricks (like changing `[]` to `{}` - it seems the JSON is malformed or I am mistaken somehow. – Jishan Jul 23 '19 at 07:30