javascriptarraysvariablesparallax.js

Building array for jsPDF not including null variables


I’m trying figure out something that has led me to the point of not even seeing the wood through the trees. I’m a noob when it comes to JavaScript and I would normally use a database to sort this but don’t have that option here.

What I'm actually working on is:

This is a quiz application that asks users to respond to a (descrete answer/SCORM Compliant) question, then another (Free text/Long Text) question. This particular part of the code is used to create the PDF output of the user's responses (with a little bit of header information).

I have to use JavaScript to build a pdf (using “jsPDF - Parallax” ) that outputs a set of variables that I’ve generated else where. E.g.

//VARIABLES........................................................................

var NoofQuesAnswered = VarNoofQuesAnswered.getValue();
var User_Score = VarUser_Score.getValue();
var CorrectImagData = 'data:image/jpeg;base64,/9j/etc/etc'; //Omitted actual 64base text
var IncorrectImgData = 'data:image/jpeg;base64,/9j/etc/etc'; //Omitted actual 64base text

/* General Text Values */
var notAnswered = '~~~null~~~';
var questionExcludedTitle = 'Question Excluded';
var questionAnswerGivenTitle = 'Answer Given';
var openQuestionTitle = 'Open Question';

/* Question Title - Variables */
var questionTitle_1 = 'Question 1';
var questionTitle_2 = 'Question 2';
var questionTitle_3 = 'Question 3';
var questionTitle_4 = 'Question 4';
var questionTitle_5 = 'Question 5';
var questionTitle_N = 'Question N';

/* Question Response/Answer Given - Variables */

//These variables are determined elsewhere (XML/Javascript)
var UsersAnswer_Que1 = Var_UsersAnswer_Que1.getValue(); 
var UsersAnswer_Que2 = Var_UsersAnswer_Que2.getValue();
var UsersAnswer_Que3 = Var_UsersAnswer_Que3.getValue();
var UsersAnswer_Que4 = Var_UsersAnswer_Que4.getValue();
var UsersAnswer_Que5 = Var_UsersAnswer_Que5.getValue();
var UsersAnswer_QueN = Var_UsersAnswer_QueN.getValue();

/* Open Question - Variables */

var openQuestion_1 = 'Why are young people potentially at risk?';
var openQuestion_2 = 'Why are there champions for young people?';
var openQuestion_3 = 'How does social media impact on the lives of young people?';
var openQuestion_4 = 'What kinds of support are there for young people, in your area?';
var openQuestion_5 = 'What type of information are young people most likely to need in crisis?';
var openQuestion_N = 'Open question (n)';

/* Open Question - User Response/Answer Given Variables */

//These variables are determined elsewhere (XML/Javascript)
var UserResp_LongTextQue_1 = Var_UserResp_LongTextQue_1.getValue();
var UserResp_LongTextQue_2 = Var_UserResp_LongTextQue_2.getValue();
var UserResp_LongTextQue_3 = Var_UserResp_LongTextQue_3.getValue();
var UserResp_LongTextQue_4 = Var_UserResp_LongTextQue_4.getValue();
var UserResp_LongTextQue_5 = Var_UserResp_LongTextQue_5.getValue();
var UserResp_LongTextQue_N = Var_UserResp_LongTextQue_N.getValue();

Then by using jsPDF I am building the page like this, to setup the header information on the first page (which is the only page that has different content on it:

function genPDF() { //Function to output the pdf using jsPDF

  var doc = new jsPDF();

  /* Begin Page Build */

  // Page Header Space........................................................................

  /* There are some other logos and other header bits here but I have ommitted them due to copyright */

  doc.setFont('helvetica')

  doc.setFontSize(30)
  doc.text(50, 55, 'Results and Responses')

  doc.setFontSize(14)
  doc.text(45, 78, 'No. of Questions Answered -')
  doc.text(113, 78, NoofQuesAnswered)

  doc.text(125, 78, 'Final score -')
  doc.text(158, 78, User_Score)

  doc.line(20, 82, 195, 82)

  // Questions with responses

  /* This is the point at which i need to build the page dynamically becasue the stuff above is all static and everything below could be built dynically */

  //	Question_1

  doc.line(20, 113, 195, 113)

  if (Var_UsersAnswer_Que1.equals(notAnswered)) {
    doc.setFontSize(25)
    doc.text(65, 125, questionTitle_1)
    doc.line(20, 130, 195, 130)
    doc.setFontSize(30)
    doc.text(58, 155, questionExcludedTitle)
  } else {
    doc.setFontSize(14)
    doc.text(20, 120, questionAnswerGivenTitle)
    doc.setFontSize(12)
    var splitUsersAnswer_Que1 = doc.splitTextToSize(usersAnswer_Que1, 150);
    doc.text(20, 127, splitUsersAnswer_Que1)

    doc.line(20, 130, 195, 130)

    doc.setFontSize(14)
    doc.text(20, 137, openQuestionTitle)

    doc.setFontSize(12)
    var splitOpenQuestion_1 = doc.splitTextToSize(openQuestion_1, 180);
    doc.text(20, 145, splitOpenQuestion_1)

    if (Var_UsersAnswer_Que1.isCorr('\u0041\u006C\u006C\u0020\u0061\u0072\u0065')) {
      doc.addImage(CorrectImagData, 'Correct Image', 185, 115, 10, 11)
    } else {
      doc.addImage(IncorrectImgData, 'Incorrect Image', 185, 115, 10, 11)
    }

    doc.setFontSize(12)
    var splitUserResp_LongTextQue_1 = doc.splitTextToSize(userResp_LongTextQue_1, 170);
    doc.text(20, 160, splitUserResp_LongTextQue_1)
    doc.line(20, 153, 195, 153)
  }

  //	Question_2

  doc.line(20, 190, 195, 190)

  if (Var_UsersAnswer_Que2.equals(notAnswered)) {
    doc.setFontSize(25)
    doc.text(65, 202, questionTitle_2)
    doc.line(20, 207, 195, 207)
    doc.setFontSize(30)
    doc.text(58, 232, questionExcludedTitle)
  } else {
    doc.setFontSize(14)
    doc.text(20, 197, questionAnswerGivenTitle)
    doc.setFontSize(12)
    var splitUsersAnswer_Que2 = doc.splitTextToSize(usersAnswer_Que2, 150);
    doc.text(20, 204, splitUsersAnswer_Que2)

    doc.line(20, 207, 195, 207)

    doc.setFontSize(14)
    doc.text(20, 214, openQuestionTitle)

    doc.setFontSize(12)
    var splitOpenQuestion_2 = doc.splitTextToSize(openQuestion_2, 180);
    doc.text(20, 222, splitOpenQuestion_2)

    if (Var_UsersAnswer_Que2.isCorr('\u0049\u006E\u0066\u006F\u0072\u006D\u0061\u0074\u0069\u006F\u006E')) {
      doc.addImage(CorrectImagData, 'Correct Image', 185, 192, 10, 11)
    } else {
      doc.addImage(IncorrectImgData, 'Incorrect Image', 185, 192, 10, 11)
    }

    doc.setFontSize(12)
    var splitUserResp_LongTextQue_2 = doc.splitTextToSize(userResp_LongTextQue_2, 170);
    doc.text(20, 237, splitUserResp_LongTextQue_2)
    doc.line(20, 230, 195, 230)
  }

  //New Page - From here down, the position of everything on the page will be the same

  doc.addPage()

  //	Question_3

  doc.line(20, 13, 195, 13)

  if (Var_UsersAnswer_Que3.equals(notAnswered)) {
    doc.setFontSize(25)
    doc.text(65, 25, questionTitle_3)
    doc.line(20, 30, 195, 30)
    doc.setFontSize(30)
    doc.text(58, 55, questionExcludedTitle)
  } else {
    doc.setFontSize(14)
    doc.text(20, 20, questionAnswerGivenTitle)
    doc.setFontSize(12)
    var splitUsersAnswer_Que3 = doc.splitTextToSize(usersAnswer_Que3, 150);
    doc.text(20, 27, splitUsersAnswer_Que3)

    doc.line(20, 30, 195, 30)

    doc.setFontSize(14)
    doc.text(20, 37, openQuestionTitle)

    doc.setFontSize(12)
    var splitOpenQuestion_3 = doc.splitTextToSize(openQuestion_3, 180);
    doc.text(20, 45, splitOpenQuestion_3)

    if (Var_UsersAnswer_Que3.isCorr('\u0041\u006C\u006C\u0020')) {
      doc.addImage(CorrectImagData, 'Correct Image', 185, 15, 10, 11)
    } else {
      doc.addImage(IncorrectImgData, 'Incorrect Image', 185, 15, 10, 11)
    }

    doc.setFontSize(12)
    var splitUserResp_LongTextQue_3 = doc.splitTextToSize(userResp_LongTextQue_3, 170);
    doc.text(20, 60, splitUserResp_LongTextQue_3)
    doc.line(20, 53, 195, 53)
  }

  //	Question_4

  doc.line(20, 90, 195, 90)

  if (Var_UsersAnswer_Que4.equals(notAnswered)) {
    doc.setFontSize(25)
    doc.text(65, 102, questionTitle_4)
    doc.line(20, 107, 195, 107)
    doc.setFontSize(30)
    doc.text(58, 132, questionExcludedTitle)
  } else {
    doc.setFontSize(14)
    doc.text(20, 97, questionAnswerGivenTitle)
    doc.setFontSize(12)
    var splitUsersAnswer_Que4 = doc.splitTextToSize(usersAnswer_Que4, 150);
    doc.text(20, 104, splitUsersAnswer_Que4)

    doc.line(20, 107, 195, 107)

    doc.setFontSize(14)
    doc.text(20, 114, openQuestionTitle)

    doc.setFontSize(12)
    var splitOpenQuestion_4 = doc.splitTextToSize(openQuestion_4, 180);
    doc.text(20, 122, splitOpenQuestion_4)

    if (Var_UsersAnswer_Que4.isCorr('\u0041\u006C\u006C\u0020\u0061\u0072\u0065\u0020')) {
      doc.addImage(CorrectImagData, 'Correct Image', 185, 92, 10, 11)
    } else {
      doc.addImage(IncorrectImgData, 'Incorrect Image', 185, 92, 10, 11)
    }

    doc.setFontSize(12)
    var splitUserResp_LongTextQue_4 = doc.splitTextToSize(UserResp_LongTextQue_4, 170);
    doc.text(20, 137, splitUserResp_LongTextQue_4)
    doc.line(20, 130, 195, 130)
  }

  //	Question_5

  doc.line(20, 167, 195, 167)

  if (Var_UsersAnswer_Que5.equals(notAnswered)) {
    doc.setFontSize(25)
    doc.text(65, 179, questionTitle_5)
    doc.line(20, 184, 195, 184)
    doc.setFontSize(30)
    doc.text(58, 209, questionExcludedTitle)
  } else {
    doc.setFontSize(14)
    doc.text(20, 174, questionAnswerGivenTitle)
    doc.setFontSize(12)
    var splitUsersAnswer_Que5 = doc.splitTextToSize(usersAnswer_Que5, 150);
    doc.text(20, 181, splitUsersAnswer_Que5)

    doc.line(20, 184, 195, 184)

    doc.setFontSize(14)
    doc.text(20, 191, openQuestionTitle)

    doc.setFontSize(12)
    var splitOpenQuestion_5 = doc.splitTextToSize(openQuestion_5, 180);
    doc.text(20, 199, splitOpenQuestion_5)

    if (Var_UsersAnswer_Que5.isCorr('\u0048\u006F\u0077\u0020\u0074\u006F\u0020\u0067\u0065\u0074')) {
      doc.addImage(CorrectImagData, 'Correct Image', 185, 169, 10, 11)
    } else {
      doc.addImage(IncorrectImgData, 'Incorrect Image', 185, 169, 10, 11)
    }

    doc.setFontSize(12)
    var splitUserResp_LongTextQue_5 = doc.splitTextToSize(openQuestion_5, 170);
    doc.text(20, 214, splitUserResp_LongTextQue_5)
    doc.line(20, 207, 195, 207)
  }

  //New Page - There are another 55 questions

  // doc.addPage()

  /*	Question_N

  doc.line(20, 13, 195, 13)

  if (Var_UsersAnswer_QueN.equals(notAnswered)) {
  	doc.setFontSize(25)
  	doc.text(65, 25, questionTitle_N)
  	doc.line(20, 30, 195, 30)
  	doc.setFontSize(30)
  	doc.text(58, 55, questionExcludedTitle)
  } else {
  	doc.setFontSize(14)
  	doc.text(20, 20, questionAnswerGivenTitle)
  	doc.setFontSize(12)
  	var splitUsersAnswer_QueN = doc.splitTextToSize(usersAnswer_QueN, 150);
  	doc.text(20, 27, splitUsersAnswer_QueN)

  	doc.line(20, 30, 195, 30)

  	doc.setFontSize(14)
  	doc.text(20, 37, openQuestionTitle)

  	doc.setFontSize(12)
  	var splitOpenQuestion_N = doc.splitTextToSize(openQuestion_N, 180);
  	doc.text(20, 45, splitOpenQuestion_N)

  	if (Var_UsersAnswer_QueN.isCorr('\u0041\u006C\u006C\u0020')) {
  		doc.addImage(CorrectImagData, 'Correct Image', 185, 15, 10, 11)
  	} else {
  		doc.addImage(IncorrectImgData, 'Incorrect Image', 185, 15, 10, 11)
  	}

  	doc.setFontSize(12)
  	var splitUserResp_LongTextQue_N = doc.splitTextToSize(userResp_LongTextQue_N, 170);
  	doc.text(20, 60, splitUserResp_LongTextQue_N)
  	doc.line(20, 53, 195, 53)
  }
	
  etc................................................
	
  */

  // Save document/Create PDF

  doc.save('Test.pdf');
}

At the moment, the result of this code is the production of a pdf with each question (1-60) with a predefined page position for each question and each element for that particular question. It will however, check to see if there is response given (users are only asked to answer 30 randomly determined questions throughout all of the 60 questions), and if there is no response to that question (because the application didn't even present that question to the user) it will say "Question Excluded" but will keep the space on the page.

As a result, I end up with 40+ pages, where only the answered questions display the user response, whist the questions that have been excluded are displayed as such.

I would love to be able to dynamically build the page using (I think) an array that is populated with the variables once it has established the questions that haven't been answered and then completely ignores them, before building the pdf with only the questions that the user has responded to.

What I am trying to achieve, is to reduce the number of pages based on the number of questions the user has answered (which could be 1 or 2 but might be as many as 30). The thing I can't get my head around is the fact that, because I have to state the actual position on the page for each element, I can't just get it to stack them automatically AND because I have to use Javascript I can't just Query the responses and then insert them into the page on the fly.

Any help would be greatly appreciated.

I might be going down completely the wrong track here so happy to hear a better approach.

Thanks in advance.


Solution

  • It sounds like you just want an array of responses, filtered for null:

    const answers = [AnswerToQuestion1, AnswerToQuestion2, AnswerToQuestion3].filter(x => x);
    

    the filter function it removing any records that are null or undefined. If your equivalent of a null answer isn't null, but is a string or something else, then you could filter it out like this:

    const answers = [AnswerToQuestion1, AnswerToQuestion2, AnswerToQuestion3].filter(x => x != whateverYourNullLooksLike);