Search code examples
javascripthtmljsonmustache

Integrating a JSON file into html with Mustache


I think im fairly close, I have looked at a fair few examples of integrating an external JSON file into html with mustache, but at the moment it isnt working. The JSON file is full of trivia questions, here is a sample question that I am trying to link:

{
  "jsonquestions": [
    {
      "id":1,
      "q_category_id":0,
      "q_text":"Which of the following is regar-ded as the real founder of portugese power in India",
      "q_options_1":"Pedro Cabral",
      "q_options_2":"Almeida",
      "q_options_3":"Vasco da Gama",
      "q_options_4":"Alfonso de Albuquerque",
      "q_correct_option":4,
      "q_difficulty_level":2,
      "q_date_added":"2013-06-10T04:00:00.000Z"
    }
  ]
}

The file is named questions.json, I am trying to link it into this html table:

<!DOCTYPE html>

<html class="no-js" lang="">
<head>
    <link rel="stylesheet" href="index.css">
    <meta charset="utf-8">
    <meta content="ie=edge" http-equiv="x-ua-compatible">

    <title>Quiz</title>
    <meta content="" name="description">
    <meta content="width=device-width, initial-scale=1" name="viewport">
</head>

<body>

    <hr>

    <div id="control">
    <h1>Questions</h1>Data generated from <a href=
    "https://market.mashape.com/pareshchouhan/trivia">
    https://market.mashape.com/pareshchouhan/trivia</a>
    <br><br>

        Search questions:
        <input type="text" id="searchText">
        <button id="search">Search Questions</button>
        <select id="sortquestions">
            <option id="idascend">Ascending ID</option>
            <option id="iddescend">Descending ID</option>
            <option id="alphabetascend">Ascending Alphabetical</option>
            <option id="alphabetdescend">Descending Alphabetical</option>
            <option id="diffascend">Ascending Difficulty</option>
            <option id="diffdescend">Descending Difficulty</option>
        </select>
        <button id ="sort">Sort</button>
    <br><br>

        Filter by difficulty:
        <input type="radio" name="difficulty" id="1" value="1" checked> 1
        <input type="radio" name="difficulty" id="2" value="2"> 2
        <button id="difficultybutton">Filter</button>
        <button id="random">Randomise</button>
        <button id="quiz">Begin Quiz!</button>
    <br><br>
    </div>  

    <table id="anchor"></ul>

    <script id="questions-template" type="text/template">  
    {{#jsonquestions}}
    <table id="questions">
        <thead>
            <tr>
                <th>ID</th>

                <th>Question</th>

                <th>Answer 1</th>

                <th>Answer 2</th>

                <th>Answer 3</th>

                <th>Answer 4</th>

                <th>Correct Answer</th>

                <th>Difficulty</th>
            </tr>
            <tr>
                <td>{{id}}</td>

                <td>{{q_text}}</td>

                <td>{{q_options_1}}</td>

                <td>{{q_options_2}}</td>

                <td>{{q_options_3}}</td>

                <td>{{q_options_4}}</td>

                <td>{{q_correct_option}}</td>

                <td>{{q_difficulty_level}}</td>
            </tr>
        </thead>

        <tbody>
        </tbody>
    </table>
    {{/jsonquestions}}
    </script>

    <script> 
    $(function() {
        $.getJSON('js/questions.json', function(data) {
            var template = $('#jsonquestions-template').html();
            var info = Mustache.to_html(template, data);
            $('#anchor').html(info);
        });
    });
    </script>

    </br></br>
    <div id="answers" style="display:none";>
        <input type="radio" name="answer" value="1" id="answer1" checked><label id="answerlabel1"></label></br>
        <input type="radio" name="answer" value="2" id="answer2"><label id="answerlabel2"></label></br>
        <input type="radio" name="answer" value="3" id="answer3"><label id="answerlabel3"></label></br>
        <input type="radio" name="answer" value="4" id="answer4"><label id="answerlabel4"></label></br>
        </br>
        <button id="giveanswer">Answer</button>
        </br></br>
        <label id="answerresult"></label>
        </br></br>
        <label id="score"></label>
    </div>

    <script src="js/jquery.min.js"></script> 
    <script src="js/mustache.min.js"></script>
    <script src="js/trivia.js"></script>
    <script src="js/search.js"></script>
    <script src="js/difficulty.js"></script>
    <script src="js/random.js"></script>
    <script src="js/quiz.js"></script>
    <script src="js/sort.js"></script>
</body>
</html>

Is there something I am missing? Thanks.


Solution

  • It looks like you're missing the "render" function call Mustache.render(template, data); (to_html has essentially been deprecated) I built a partial Plunker to show it working and it's embedded below. Im hosting the json at https://api.myjson.com/bins/2oxsm

    // Code goes here
    
    	$(function(){
            var data;
            $.getJSON("https://api.myjson.com/bins/2oxsm")
                .done(function(dat) {
                    data = dat;
                    console.log("success",dat)
                    render();
                })
                .fail(function() {
                    console.log( "error",arguments);
                })
                .always(function() {
                    console.log( "complete" );
                });
                function render(){
                    // mustache
                    var tmpl = $('#questions-template').html();
                    var html = Mustache.render(tmpl, data);
                    $('#questions').find('tbody').html(html);
                }  
    	});
        // lets make them clickable
        $(function(){
        
            var choices = [];
            $(document).on("click","td.choice",updateAnswers)
            
            function updateAnswers(e){
                
                var $t = $(this),
                    $p = $t.parents('tr'),
                    $answer = $p.find('.answer'),
                    correct = $answer.data('value'),
                    good = $t.data('value') === correct;
    
                $p.find('td')
                    .toggleClass("checked",false)
                    .toggleClass("correct",false);
                $t.addClass("checked");
                $answer.toggleClass("correct",good);
                $t.toggleClass("correct",good);
                $("#choices").html('');
                $('td.checked').each(show);
            }
            
            function show(i,v){
                // send this data to the backend?
                var $v = $(v),
                    $p = $v.parents('tr'),
                    div = $("<div/>").html($p.index()+1 + ":" + $v.html());
                $("#choices").append(div);
                div.toggleClass('correct',$v.is(".correct"))
            }
            
        })
        	
    /* Styles go here */
    * {
      font: 0.95em arial; }
    
    #choices {
      color: white;
      background-color: #F00; }
      #choices div {
        padding: 1em; }
        #choices div.correct {
          background-color: green; }
    
    table#questions {
      border-collapse: collapse; }
      table#questions thead {
        background: #000;
        color: #FFF;
        font-weight: bold; }
        table#questions thead th {
          white-space: nowrap;
          padding: 1em; }
      table#questions td {
        border: 1px solid black;
        padding: 0.5em;
        border-spacing: 1px; }
        table#questions td.choice {
          background-color: #666;
          color: white;
          cursor: pointer; }
          table#questions td.choice.checked {
            background-color: red;
            color: white; }
          table#questions td.choice.correct {
            background-color: green; }
        table#questions td.answer {
          background-color: pink; }
          table#questions td.answer.correct {
            background-color: lime; }
    <script src="//cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.2/mustache.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
            <table id="questions">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Question</th>
                    <th>Answer 1</th>
                    <th>Answer 2</th>
                    <th>Answer 3</th>
                    <th>Answer 4</th>
                    <th>Correct</th>
                    <th>Difficulty</th>
                </tr>
                <tbody></tbody>
            </table>
            <div id="choices">
                
            </div>
            <script id="questions-template" type="text/template">  
                {{#jsonquestions}}
                <tr>
                    <td>{{id}}</td>
                    <td>{{q_text}}</td>
                    <td class="choice" data-value="1">{{q_options_1}}</td>
                    <td class="choice" data-value="2">{{q_options_2}}</td>
                    <td class="choice" data-value="3">{{q_options_3}}</td>
                    <td class="choice" data-value="4">{{q_options_4}}</td>
                    <td class="answer" data-value="{{q_correct_option}}"></td>
                    <td>{{q_difficulty_level}}</td>
                </tr>
                {{/jsonquestions}}
            </script>

    (Also do you really want to repeat the table header for each question?)

    $(function(){
        var data;
        $.getJSON("./data.json")
            .done(function(dat) {
                data = dat;
                render();
            })
            .fail(function() {
                console.error( "error",arguments);
            })
            .always(function() {
                console.info( "complete" );
            });
            function render(){
                // mustache
                var tmpl = $('#template').html();
                var html = Mustache.render(tmpl, data);
                $('#target').html(html);
            }  
    });