2

As the title says, I am trying to write a function which would create some HTML based on the array I feed it. If the array were simply one dimensional, I wouldn't have any problems. But the "multidimensionality" of the array is where I'm having issues. Namely since it's not always consistent.

I should also note that I am trying to accomplish this without any 3rd party JS libraries.

For example, here is a sample array:

var template = [
    ['div', {id: 'wrapper'}, [
        ['link', {rel:'stylesheet', href:'//mysite.com/css.css', type:'text/css'}],
        ['header', "Look at me!  I'm a header!"],
        ['nav', {class:'main-nav'}, [
            ['ul', [
                ['li', ['a', {'href':'/home'}, "Home"]],
                ['li', ['a', {'href':'/about'}, "About Us"]],
                ['li', ['a', {'href':'/erase_internet.php'}, "Don't click me!"]]
            ]]
        ]],
        ['section', "Some sample text!"],
        ['footer', "Copyright © 1984"]
    ]]
];


The format of the array is:
[string "type" [, json obj "attributes" ][, string "text"][, array "children"]]


Now I already have one function which takes a single array object and creates an element:

function createEl(type, attr, text) {
    var key, el = d.createElement(type);

    if (typeof attr === 'object' && !Array.isArray(attr)) {
        for (key in attr) {
            if (attr.hasOwnProperty(key)) {
                el.setAttribute(key, attr[key]);
            }
        }
    }
    else if (typeof attr === 'string' && text.length > 0) {
        el.appendChild(d.createTextNode(attr));
    }

    if (typeof text === 'string' && text.length > 0) {
        el.appendChild(d.createTextNode(text));
    }

    return el;
}


But I want to be able to process all of the "children" and append them to their parents, as indicated by the sample array, so that the output would look like this:

<div id="wrapper">
    <link rel="stylesheet" href="//mysite.com/css.css" type="text/css" />
    <header>Look at me!  I'm a header!</header>
    <nav class="main-nav">
        <ul>
            <li><a href="/home">Home</a></li>
            <li><a href="/about">About us</a></li>
            <li><a href="/erase_internet.php">Don't click me!</a></li>
        </ul>
    </nav>
    <section>Some sample text!</section>
    <footer>Copyright &copy; 1984</footer>
</div>


So here are my questions:

  1. If I don't know how many levels deep the array goes, what's the best-practice method for traversing through the children and all of the grand-children?
  2. Would I call the createEl() function again from within itself to create and append those children elements, if they exist?
    • Is that even possible?
  3. Would it help at all if I changed the structure of the array to this?:
    [string "type" [, json obj "attributes" [, string "text" [, array "children"]]]]
  4. Is there maybe a better way of doing this altogether, without having to resort to jQuery or the like? (subjective, but I value the expertise and experience of the SO Community)


Many thanks in advance!

5
  • Don't reinvent the wheel at least in templating case. Have a look at template plugins for JS Commented Mar 1, 2014 at 21:05
  • 2
    Also, this is a tiny pedantic comment but technically you should put class on line 5 of template in quotes because it is actually a reserved word in JS (sorry) Commented Mar 1, 2014 at 21:12
  • @redV - I didn't mention this in my question but this is sort of an exercise for me... Reinventing the wheel is kinda what I'm shooting for here. ;) Commented Mar 1, 2014 at 21:14
  • @user2521439 Agreed! I don't actually have class in my code, but I did fail to encapsulate that in my example. Thanks for pointing that out! Commented Mar 1, 2014 at 21:16
  • @DondeEstaMiCulo That's ok :) Just saw it and made me think - I believe the class keyword is being implemented in ES6 Commented Mar 1, 2014 at 21:17

1 Answer 1

1
  1. You will need to setup your createEl in a recursive fashion. So, if you have deeper children, the function is triggered recursively for those children.

  2. Yes, look at 1.

  3. Your preference.

  4. I don't think, but not sure, that jQuery would buy you anything in your case. My suggestion is to look up how recursion works as an idea and apply it to JavaScript syntax.

A good place to get started

Sign up to request clarification or add additional context in comments.

2 Comments

I'm going to check that out right now. Thanks for the help!
Took me a minute to get my head wrapped around this, but once I did it worked perfectly. Thanks for the steering me in the right direction!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.