3

Basically I have a form that ask simple questions and the user can answer either in a select, textbox or textarea.

I used JSON to parse the questions.

However I need to know how can I insert an image above the question like this: http://prntscr.com/f5o8fc

Here's my jQuery:

survey = { questions: undefined,
           firstQuestionDisplayed: -1,
           lastQuestionDisplayed: -1};

(function (survey, $) {

    survey.setup_survey = function(questions) {
        var self = this;
        this.questions = questions;

        this.questions.forEach(function(question) {
            self.generateQuestionElement( question );
        });

        $('#backBtn').click(function() {
            if ( !$('#backBtn').hasClass('disabled') ) {
                self.showPreviousQuestionSet();
            }
        });

        $('#nextBtn').click(function() {
            var ok = true;
            for (i = self.firstQuestionDisplayed; i <= self.lastQuestionDisplayed; i++) {
                if (self.questions[i]['required'] === true && !self.getQuestionAnswer(questions[i])) {
                    $('.question-container > div.question:nth-child(' + (i+1) + ') > .required-message').show();
                    ok = false;
                }
            }
            if (!ok)
                return

            if ( $('#nextBtn').text().indexOf('Continue') === 0 ) {
                self.showNextQuestionSet();
            }
            else {
                var answers = {res: $(window).width() + "x" + $(window).height()};
                for (i = 0; i < self.questions.length; i++) {
                    answers[self.questions[i].id] = self.getQuestionAnswer(self.questions[i]);
                }

                $.ajax({type: 'post',
                        url: 'http://localhost:7000/answers',
                        contentType: "application/json",
                        data: JSON.stringify(answers),
                        processData: false,
                        success: function(response) {
                            self.hideAllQuestions();
                            $('#nextBtn').hide();
                            $('#backBtn').hide();
                            if ('success' in response) {
                                $('.completed-message').html('Thank you for participating in this survey!<br><br>'+response['success']);
                            }
                            else if ('error' in response) {
                                $('.completed-message').text('An error occurred: '+response['error']);
                            }
                            else {
                                $('.completed-message').text('An unknown error occurred.');
                            }
                        },
                        error: function(response) {
                            self.hideAllQuestions();
                            $('#nextBtn').hide();
                            $('#backBtn').hide();
                            $('.completed-message').text('An error occurred: could not send data to server');
                        }
                });
            }
        });

        this.showNextQuestionSet();

    }

    survey.getQuestionAnswer = function(question) {
        var result;
        if ( question.type === 'single-select' ) {
            result = $('input[type="radio"][name="' + question.id + '"]:checked').val();
        }
        else if ( question.type === 'single-select-oneline' ) {
            result = $('input[type="radio"][name="' + question.id + '"]:checked').val();
        }
        else if ( question.type === 'text-field-small' ) {
            result = $('input[name=' + question.id + ']').val();
        }
        else if ( question.type === 'text-field-large' ) {
            result = $('textarea[name=' + question.id + ']').val();
        }
        return result ? result : undefined;
    }

    survey.generateQuestionElement = function(question) {
        var questionElement = $('<div id="' + question.id + '" class="question"></div>');
        var questionTextElement = $('<div class="question-text"></div>');
        var questionAnswerElement = $('<div class="answer"></div>');
        var questionCommentElement = $('<div class="comment"></div>');
        questionElement.appendTo($('.question-container'));
        questionElement.append(questionTextElement);
        questionElement.append(questionAnswerElement);
        questionElement.append(questionCommentElement);
        questionTextElement.html(question.text);
        questionCommentElement.html(question.comment);
        if ( question.type === 'single-select' ) {
            questionElement.addClass('single-select');
            question.options.forEach(function(option) {
                questionAnswerElement.append('<label class="radio"><input type="radio" value="' + option + '" name="' + question.id + '"/>' + option + '</label>');
            });
        }
        else if ( question.type === 'single-select-oneline' ) {
            questionElement.addClass('single-select-oneline');
            var html = '<table border="0" cellpadding="5" cellspacing="0"><tr><td></td>';
            question.options.forEach(function(label) {
                html += '<td><label>' + label + '</label></td>';
            });
            html += '<td></td></tr><tr><td><div>' + question.labels[0] + '</div></td>';
            question.options.forEach(function(label) {
                html += '<td><div><input type="radio" value="' + label + '" name="' + question.id + '"></div></td>';
            });
            html += '<td><div>' + question.labels[1] + '</div></td></tr></table>';
            questionAnswerElement.append(html);
        }
        else if ( question.type === 'text-field-small' ) {
            questionElement.addClass('text-field-small');
            questionAnswerElement.append('<input type="text" value="" class="text" name="' + question.id + '">');
        }
        else if ( question.type === 'text-field-large' ) {
            questionElement.addClass('text-field-large');
            questionAnswerElement.append('<textarea rows="8" cols="0" class="text" name="' + question.id + '">');
        }
        if ( question.required === true ) {
            var last = questionTextElement.find(':last');
            (last.length ? last : questionTextElement).append('<span class="required-asterisk" aria-hidden="true">*</span>');
        }
        questionAnswerElement.after('<div class="required-message">This is a required question</div>');
        questionElement.hide();
    }

    survey.hideAllQuestions = function() {
        $('.question:visible').each(function(index, element){
            $(element).hide();
        });
        $('.required-message').each(function(index, element){
            $(element).hide();
        });
    }

    survey.showNextQuestionSet = function() {
        this.hideAllQuestions();
        this.firstQuestionDisplayed = this.lastQuestionDisplayed+1;

        do {
            this.lastQuestionDisplayed++;  
            $('.question-container > div.question:nth-child(' + (this.lastQuestionDisplayed+1) + ')').show();
            if ( this.questions[this.lastQuestionDisplayed]['break_after'] === true)
                break;
        } while ( this.lastQuestionDisplayed < this.questions.length-1 );

        this.doButtonStates();
    }

    survey.showPreviousQuestionSet = function() {
        this.hideAllQuestions();
        this.lastQuestionDisplayed = this.firstQuestionDisplayed-1;

        do {
            this.firstQuestionDisplayed--;  
            $('.question-container > div.question:nth-child(' + (this.firstQuestionDisplayed+1) + ')').show();
            if ( this.firstQuestionDisplayed > 0 && this.questions[this.firstQuestionDisplayed-1]['break_after'] === true)
                break;
        } while ( this.firstQuestionDisplayed > 0 );

        this.doButtonStates();
    }

    survey.doButtonStates = function() {
        if ( this.firstQuestionDisplayed == 0 ) {
            $('#backBtn').addClass('invisible');  
        }
        else if ( $('#backBtn' ).hasClass('invisible') ) {
            $('#backBtn').removeClass('invisible');
        }

        if ( this.lastQuestionDisplayed == this.questions.length-1 ) {
            $('#nextBtn').text('Finish');
            $('#nextBtn').addClass('blue');  
        }
        else if ( $('#nextBtn').text() === 'Finish' ) {
            $('#nextBtn').text('Continue »'); 
            $('#nextBtn').removeClass('blue');
        }
    }
})(survey, jQuery);


$(document).ready(function(){
    $.getJSON('questions.json', function(json) {
        survey.setup_survey(json);        
    });
});

window.onbeforeunload = function() {
    return "This will reset all answers that you've already filled in!";
}

And from here:

I parse my JSON file:

[  
    {  
        "text":"Do you know me?",
        "id":"2",
        "break_after":true,
        "required":true,
        "type":"single-select",
        "options":[  
            "YES",
            "NO"
        ]
    },
    {  
        "text":"What gets wetter and wetter the more it dries?",
        "id":"3",
        "break_after":true,
        "required":true,
        "type":"single-select",
        "options":[  
            "a car",
            "a towel",
            "a plane",
            "a television"
        ]
    },
    {  
        "text":"Are you going to?",
        "id":"4",
        "type":"text-field-small"
    },
    {  
        "text":"What goes up and down the stairs without moving?",
        "id":"5",
        "type":"single-select",
        "options":[  
            "a toddler",
            "an arrow",
            "towels",
            "a rug"
        ]
    },
    {  
        "text":"What can you catch but not throw?",
        "id":"6",
        "type":"single-select",
        "options":[  
            "a couch",
            "a cold",
            "a puppy",
            "a baseball"
        ]
    },
    {  
        "text":"I can run but not walk. Wherever I go, thought follows close behind. What am I?",
        "id":"7",
        "type":"single-select",
        "options":[  
            "a doctor",
            "a pineapple",
            "a nose",
            "pimples"
        ]
    },
    {  
        "text":"What's black and white and red all over?",
        "id":"8",
        "type":"single-select",
        "options":[  
            "an embarrased skunk",
            "a turtle",
            "a giraffe",
            "a dog"
        ]
    },
    {  
        "text":"What goes around the world but stays in a corner?",
        "id":"9",
        "type":"single-select",
        "options":[  
            "a stamp",
            "coffee",
            "a dog",
            "plants"
        ]
    }
]

Here's what the HTML looks like:

<div class="main">

<div><h1 class="title">Test Questionaire</h1><br>

<div class="question-container"></div>
<a id="backBtn" href="#" class="button">« Back</a>
<a id="nextBtn" href="#" class="button">Continue »</a>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="survey.js" type="text/javascript"></script>

</div><div class="completed-message"></div>
</div></div>

Any idea?

  • 2
    can you just include the URL to the image? – Daniel A. White May 09 '17 at 00:53
  • a data uri may be what you need – Jaromanda X May 09 '17 at 00:54
  • How can I add that on my JSON file? its a series of text questions. –  May 09 '17 at 00:54
  • what about base64? – grzesiekmq May 09 '17 at 00:55
  • Can you tell me exactly how to implement that? sorry I am a bit loss about the suggestions. –  May 09 '17 at 01:00
  • Upload the image somewhere, to your site or a CDN or something, and instead of `image.jpg` in your JSON, store the path to the file. Or you could do something more programatic like reference /the-unique-test-name-or-id-or-key/question#/image#.jpg like `/test-questionaire/3/1.jpg` and `/test-questionaire/3/2.jpg` assuming you have 2 images in question #3 – Michael Coker May 09 '17 at 01:01
  • relative path to your file it is another option. Do you want to store it locally or remote? – grzesiekmq May 09 '17 at 01:04
  • take a look at filepicker https://www.filepicker.com/docs for getting a feel for the flow of getting the user to upload the image and then retrieve the URL to the file – maxwell May 09 '17 at 01:05
  • @MichaelCoker: I like your idea. But I will be 100% be grateful if you could point out directly on how to implement it on my codes? –  May 09 '17 at 01:12

1 Answers1

5

One way to achieve this is to use a site like WebSemantics Image to DataURL converter to create a data-string representation of your desired image. As this is a String it can be stored in a JSON file and inserted as the src attribute of an HTML img tag once fetched and parsed, like so...

/* JSON example */
{
    "text": "Some text blah blah...",
    "img": "data:image/png;base64,iVBORw0KGgoAAA..."
}

/* Javascript example */
var obj = theParsedJSON;

var img = '<img src="'+obj.img+'" />';
element.innerHTML = img;

...or...

var img = new Image();

img.addEventListener('load', function() {
    /* do something with 'this' image: EG */
    element.appendChild(this);
}, false);

img.src = obj.img;

The only thing to keep in mind is that image data URLs can add quite a bit of weight to your JSON files, so an absolute reference to an online resource may be a better option: EG...

{
    "text": "Some text blah blah...",
    "img": "http://domain.co/path/to/image.jpg"
}

Hope that helped. :)

Brian Peacock
  • 1,801
  • 16
  • 24
  • Note that, if he has the image file in its computer, he could simply use commands for generating the base64 string, avoiding using a third-party website. In macOS, `base64 ` will give the base64 encoding for the contents of ``. That applies to most GNU/Linux environments too. Then he would only need to format the string as `data:;base64,`, for example: `data:image/png;base64,.......` – Alejandro Iván May 09 '17 at 02:12
  • I tried to add it survey.doButtonStates = function() but it did not work.I also added this: { "text":"What gets wetter and wetter the more it dries?", "id":"3", "img": "data:image/png;base64,asdas", "break_after":true, "required":true, "type":"single-select", "options":[ "a car", "a towel", "a plane", "a television" ] }, –  May 09 '17 at 02:30
  • @Gaara : To append an image to an HTML page element dynamically with JQuery see [this StackOverflow question](http://stackoverflow.com/a/14830115/4746328). – Brian Peacock May 09 '17 at 15:47
  • 1
    Thanks, referencing my SVG's worked! I had them in an "assets" directory of my project. Auto-completion for references did not work, so it was a bit of a hustle to find the right path. Eventually I did not need the absolute path, just starting with ```assets/...``` worked :) – MikhailRatner Feb 20 '22 at 19:23