Search code examples
javascriptobjectfor-loopmultidimensional-arraymustache

How to read a multidimensionnal javascript object?


First of all, here is my Javascript object :

var languages = {
    languages: [
        { name: "French", locale: "FR", id: "-1" },
        { name: "English", locale: "IT", id: "-2" },
        { name: "Spanish", locale: "ES", id: "-3" },
        { name: "Zoulou", locale: "ZL", id: "-4" },
        { name: "Italian", locale: "EN", id: "-5" }
    ]
};

I'm using Mustache.js to generate language buttons:

function generateLanguages(languages) {
  var output = $("#languages-output");
  var template = "{{#languages}}<button id={{id}}><img src=#FLAG onclick='changeLanguage({{locale}})' /><p>{{name}}</p></button>{{/languages}}";
  html = Mustache.render(template, languages);
  output.append(html);}

I also have a folder containing all the flags images called flags (e.g flags/English.png). I'm trying to generate the buttons by adding the corresponding flag. I really have no idea how to do it, I thought to use the "locale" property of the Javascript object in a for loop and for each locale, create a big switch to choose the right image. If someone can help me ?

http://jsfiddle.net/lBrowz/7w5grype/


Solution

  • A few improvements and ideas:

    • Move templates to your HTML. That's where they should be. Reference them from JS by their ID. It's a lot easier to modify and think about templates when they are outside of the JavaScript.
    • Maybe using flags for languages isn't the best choice. Sometimes a language cannot accurately be represented by a flag (see Zulu, which I chose to represent by the flag of Mozambique, but that might not be what your users expect. The same is true for English, when you think about it.)
    • Anyway, instead of one flag image per language, use a single image that contains all flags and then use CSS sprites to display selected flags. I used this project here: http://tkrotoff.github.io/famfamfam_flags/
    • Use data-* attributes to store extra information in elements.
    • Use event delegation to handle clicks. Never use inline event handlers (like onclick).

    var languages = {
        languages: [
            { name: "French", locale: "FR", id: "-1", cls: "famfamfam-flag-fr" },
            { name: "English", locale: "IT", id: "-2", cls: "famfamfam-flag-gb" },
            { name: "Spanish", locale: "ES", id: "-3", cls: "famfamfam-flag-es" },
            { name: "Zoulou", locale: "ZL", id: "-4", cls: "famfamfam-flag-mz" },
            { name: "Italian", locale: "EN", id: "-5", cls: "famfamfam-flag-it" }
        ]
    };
    
    function changeLanguage(locale) {
        $("#locale").text(locale);
    }
    
    $(function () {
        var languagesTemplate = $("#languages-template").html();
        $("#languages-output").html( Mustache.render(languagesTemplate, languages) );
    
        $(document).on("click", ".language-button", function () {
            var locale = $(this).data("locale");
            changeLanguage(locale);
        });
    });
    .language-button {
        width: 5em;
        height: 4em;
        margin: 3px;
    }
    .language-button > span {
        display: inline-block;
        margin: 2px;
    }
    <link href="http://tkrotoff.github.io/famfamfam_flags/famfamfam-flags.css" rel="stylesheet"/>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.0/mustache.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    
    <div id="languages-output"></div>
    <div id="locale"></div>
    
    <script type="text/x-handlebars-template" id="languages-template">
    {{#languages}}
        <button id="{{id}}" class="language-button" data-locale="{{locale}}">
            <span class="{{cls}}"></span>
            <span>{{name}}</span>
        </button>
    {{/languages}}
    </script>

    Run the code snippet above to see it live.