If statement to allow single and multiple if options - if-statement

I have an If statement dependent on a choice made in a google form. Everything currently works as needed BUT, the question choice allows them to choose ALL OPTIONS THAT APPLY. If more than one option is chosen, the script fails.
How it currently works - person fills out form, script grabs info and inputs to a document, gives specified message based on choice from question (cif and message in script below), then emails the correct recipient (chosen in form). It works beautifully if cif is submitted with one choice.
What do I add/edit to the script to allow for multiple choices, and therefore multiple messages input to the document, without having to write an If state for each scenario?
// Global variables
var docTemplate = "1EoBcz0BK4R5hm-q5pR68xnQnR8DlR56XzjxRrgsu4uE"; // *** replace with your template ID ***
var docName = "You got a High 5";
function onFormSubmit(e) { // add an onsubmit trigger
// Values come from the spreadsheet form
var observer = e.values[1]
var teacher = e.values[2]
var email = e.values[2]
var period = e.values[4]
var time = e.values[3]
var cif = e.values[5]
var comments = e.values[6]
var message;
if (cif == 'READ - Variety of texts') {
message = 'read quote'
}
else if (cif == 'WRITE - Paper or electronic') {
message = 'write quote'
}
else if (cif == 'THINK - Actively engaged students') {
message = 'think quote'
}
else if (cif == 'TALK - Purposeful discussion') {
message = 'talk quote'
}
else if (cif == 'MOVE - Students moving through class') {
message = 'move quote'
}
else if (cif == 'CIF not observed') {
message = 'CIF not observed'
}
// Get document template, copy it as a new temp doc, and save the Doc’s id
var copyId = DriveApp.getFileById(docTemplate)
.makeCopy(docName+' for '+teacher)
.getId();
// Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
// Get the document’s body section
var copyBody = copyDoc.getActiveSection();
// Replace place holder keys,
copyBody.replaceText('keyobserver', observer);
copyBody.replaceText('keyperiod', period);
copyBody.replaceText('keytime', time);
copyBody.replaceText('keycif', cif);
copyBody.replaceText('keycomments', comments);
copyBody.replaceText('keymessage', message)
var todaysDate = Utilities.formatDate(new Date(), "GMT", "MM/dd/yyyy");
copyBody.replaceText('keyTodaysDate', todaysDate);
// Save and close the temporary document
copyDoc.saveAndClose();
// Convert temporary document to PDF by using the getAs blob conversion
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
// Attach PDF and send the email
var subject = "High 5 - it matters.";
var body = "You got a High 5! See attached PDF. " +
"Please do not reply to this email. You will be asked to supply a response thorugh a link within the attached PDF. " +
"'Do all the good you can. By all the means you can. In all the ways you can. In all the places you can. At all the times you can. To all the people you can. As long as you ever can. -John Wesley'";
MailApp.sendEmail(email, subject, body, {htmlBody: body, attachments: pdf});
// Delete temp file
DriveApp.getFileById(copyId).setTrashed(true);
}

Having multiple selected answer will return a comma separated values in form of string.
For example:
e.values[5] can have:
'READ - Variety of texts, WRITE - Paper or electronic, THINK - Actively engaged students, TALK - Purposeful discussion, MOVE - Students moving through class, CIF not observed'
in one single string and using == will not work since it has different content versus the string you are comparing to. This causes all of your if statements to fail because non of them matches the string. This leads to an undefined variable message which causes error on replaceText() function.
To fix the issue replace this line of code:
var message;
if (cif == 'READ - Variety of texts') {
message = 'read quote'
}
else if (cif == 'WRITE - Paper or electronic') {
message = 'write quote'
}
else if (cif == 'THINK - Actively engaged students') {
message = 'think quote'
}
else if (cif == 'TALK - Purposeful discussion') {
message = 'talk quote'
}
else if (cif == 'MOVE - Students moving through class') {
message = 'move quote'
}
else if (cif == 'CIF not observed') {
message = 'CIF not observed'
}
with:
var message = [];
if (cif.match('READ - Variety of texts')) {
message.push('read quote');
}
if (cif.match('WRITE - Paper or electronic')) {
message.push('write quote');
}
if (cif.match('THINK - Actively engaged students')) {
message.push('think quote');
}
if (cif.match('TALK - Purposeful discussion')) {
message.push('talk quote');
}
if (cif.match('MOVE - Students moving through class')) {
message.push('move quote');
}
if (cif.match('CIF not observed')) {
message.push('CIF not observed')
}
and in your
copyBody.replaceText('keymessage', message);
just add join function to make message a comma separated values when the content is more than 1:
copyBody.replaceText('keymessage', message.join(',');
Example Usage:
Multiple CIF:
var cif = 'READ - Variety of texts, WRITE - Paper or electronic, THINK - Actively engaged students, TALK - Purposeful discussion, MOVE - Students moving through class, CIF not observed';
Output:
Single CIF:
var cif = 'WRITE - Paper or electronic';
Output:
References
Array.join()
String.match()

Related

Google App Script IF function checking only one row, and applying the result to all rows

I seem to be going quite wrong somewhere.
I'm writing a script that will automatically send out a reminder email if a Google sheet cell turns to "Yes".
The problem is my script seems to read it as:
if the second row has a "yes" it will return true for all rows and send out an email to everyone, regardless of the other rows saying "yes" or "no".
if any other row has a yes, then it seems to be completely ignored.
Defining the range to check:
//looping through all of the rows
for (var i = 0; i < data.length; ++i) {
var row = data[i];
// Creating where the if statement is check
var ss = SpreadsheetApp.getActiveSheet();
var thisQuarter = ss.getRange("H2:H50").getValue();
The IF statement to check against:
// checking for this quarter
if (
thisQuarter == "Yes") {
var subject =
'Your BCP is due to expire this quarter: ';
MailApp.sendEmail(emailAddress, subject, message,);
Logger.log('this quarter');
}
}
}
If anyone could give me a couple pointers as to where I'm going wrong, that would be greatly appreciated.
Thank you,
Ideally post a view only copy of the sheet. I believe the problem is this section of code:
// checking for this quarter
if (
thisQuarter == "Yes") {
var subject =
'Your BCP is due to expire this quarter: ';
MailApp.sendEmail(emailAddress, subject, message,);
Logger.log('this quarter');
}
thisQuarter is assigned here:
var thisQuarter = ss.getRange("H2:H50").getValue();
change that line to this:
var thisQuarter = ss.getRange("H2:H50").getValues();
so thisQuarter is an array of values from the range specified
change the if statement to this and see if it helps:
for (i = 0; i < thisQuarter.length; i++) {
if (thisQuarter[i][0] == "Yes" {
// send email
}
}

How to automatically go through and edit long txt files?

I have an issue: I've got some chat logs that are thousands of lines ong, and I'm trying to isolate the messages from one specific user. The log looks like this:
[dd-mm-yy hh:mm pm/am] Username
message
[dd-mm-yy hh:mm pm/am] Username
message
[dd-mm-yy hh:mm pm/am] Username
message
In my file, I want to only keep the messages (not the other information like day hour or their username) that one specific user has send, and delete everything else, so I can process the contents of those messages. Is there anything out there that can help me achieve it, because as you can see its a very tedious process to go through thousands of lines of logs doing this by hand.
I ended up writing a js script to do what I wanted since I couldnt find anything anywhere else, here it is:
const fs = require("fs");
const readline = require("readline");
async function processLineByLine() {
const fileStream = fs.createReadStream("./input.txt");
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity,
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
let trigger = false;
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
if (line.includes("YOU DID THIS TO MY BOI LIM#7483") == true) {
console.log("true");
trigger = true;
}
else if (trigger == true) {
console.log(`Line sent by user: ${line}`);
fs.appendFile("output.txt", line + " ", (err) => {
// throws an error, you could also catch it here
if (err) throw err;
// success case, the file was saved
console.log("line saved");
});
trigger = false;
}
}
}
processLineByLine();

how to start intro.js tour only on first visit to website

I have implemented intro.js to my website. But I wanted to start the tour only on first visit. may be by using cookies.. website is made with html no php..
JavaScript cookies are a solution although I should point out that it will only work for as long as the user keeps the cookie.
//set the cookie when they first hit the site
function setCookie(c_name,value,exdays)
{
var exdate=new Date();
exdate.setDate(exdate.getDate() + exdays);
var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
document.cookie=c_name + "=" + c_value;
}
//check for the cookie when user first arrives, if cookie doesn't exist call the intro.
function getCookie(c_name)
{
var c_value = document.cookie;
var c_start = c_value.indexOf(" " + c_name + "=");
if (c_start == -1)
{
c_start = c_value.indexOf(c_name + "=");
}
if (c_start == -1)
{
c_value = null;
}
else
{
c_start = c_value.indexOf("=", c_start) + 1;
var c_end = c_value.indexOf(";", c_start);
if (c_end == -1)
{
c_end = c_value.length;
}
c_value = unescape(c_value.substring(c_start,c_end));
}
return c_value;
}
code is from http://www.w3schools.com/js/js_cookies.asp
obviously there's some blanks you'll have to fill in there, but it's a good starting point for working with cookies in javascript.
EDIT:
So you want to make a new function, put it in the head, inside script tags (if you have them already, just copy the function into there (you'll want to put the other two functions I provided within the script tag also)). This function will check to see if you have a cookie. If you do, just return. If you don't, create the cookie and run the intro,
<head>
<script type="text/javascript">
function checkCookieIntro(){
var cookie=getCookie("mySite");
if (cookie==null || cookie=="") {
setCookie("mySite", "1",90);
runIntro(); //change this to whatever function you need to call to run the intro
}
}
</script>
</head>
now change your body to be:
<body onload="checkCookieIntro()">
so when the body loads it will check to see if a cookie exists, if it doesn't, create a cookie with a value of one that will last for 90 days (unless the user deletes it) and then run the intro. If the cookie does exist with a value then it does nothing.

Vote Restriction Coding Error by Programmer

I am not able to properly launch my site at http://www.enbloc.sg
This is because my programmer is not able to figure out a problem. Any help would be much appreciated.
Visitors vote by clicking on one colour on the traffic light. They are supposed to only have one vote.
The site first checks for cookies and then ip address of voter. If the 2 are identical to a previous visitor, then voting is not allowed. If only one of the 2 are repeated, then voting is permitted.
The idea of having a double restriction is to allow different voters behind a fixed IP to vote. E.g. the employees of a company would not be able to vote since they are likely to be accessing the site via a fixed IP address.
However, currently, visitors are able to click on ALL 3 colours to register 3 votes on their first visit to the site. My coder is not able to resolve this issue and has abandoned me.
I would be most grateful if someone can help. I believe the relevant codes are appended below.
Apologies if my posting is wrongly formatted.
Thanks very much,
Lin En
Extracted from http://www.enbloc.sg/js/functions.js
//update dashboard when vote by user
function vote_update(ip_address, issue_num, vote_status){
var vote_cookie = document.getElementById('vote_cookie').value;
if(vote_cookie != '')
{
if(document.getElementById('thanks').style.display == "none")
{
$("#multi_error").fadeIn("slow");
}
else
{
document.getElementById("thanks").style.display = "none";
$("#multi_error").fadeIn("slow");
}
}
else
{
if(ip_address != ' ' && issue_num != ' ')
{
http.open("POST", "update_vote.php"); // true
http.onreadystatechange = update_vote;
http.setRequestHeader("Content-Type", "application/x-www-form- urlencoded;charset=UTF-8");
http.send("ip="+ ip_address +"&issue_num="+ issue_num + "&vote_status=" + vote_status);
}
else
{
alert("Occur Error for IP or ISSUE!");
}
}
}
// ajax response function
function update_vote(){
if (http.readyState == 4)
{
if (http.status == 200)
{
var xmlDoc = http.responseXML;
var listElements = xmlDoc.getElementsByTagName("list");
var result = listElements[0].getElementsByTagName("total") [0].childNodes[0].nodeValue;
if (result == 1)
{
var issue_num = listElements[0].getElementsByTagName("issue")[0].childNodes[0].nodeValue;
var vote = listElements[0].getElementsByTagName("vote") [0].childNodes[0].nodeValue;
$("#thanks").fadeIn("slow");
load(issue_num, vote);
}
else if (result == 'Multi')
{
if(document.getElementById('thanks').style.display == "none")
{
$("#multi_error").fadeIn("slow");
}
else
{
document.getElementById("thanks").style.display = "none";
$("#multi_error").fadeIn("slow");
}
}
else
{
alert("error");
}
}
}
}
These changes will help:
var already_voted = false;
function vote_update(ip_address, issue_num, vote_status)
{
if(alread_voted) return;
already_voted = true;
// rest of the code
}
This will make sure that only one vote can be cast during a single visit. The cookies take care of the rest and are already working fine.

Replicating Google Analytics DateRange picker

I need to replicate the Google Analytics date picker (plus a few new options). Can anyone tell me how to highlight all the cells on a calendar between two dates. My basic JavaScript is OK but I think I'm getting a bit out of my depth.
I'm using JQuery 1.5.1 and JQuery UI 1.8.14.
In needed to replicate Google Analytics date picker as well. I know you were asking just about highlighting cells, but if someone else would prefer complete solution, you can see my answer from another question: jquery google analytics datepicker
Here's a solution using the built-in 'onSelect' event (jsFiddle):
$(document).ready(function() {
'use strict';
var range = {
'start': null,
'stop': null
};
$('#picker').datepicker({
'onSelect': function(dateText, inst) {
var d, ds, i, sel, $this = $(this);
if (range.start === null || range.stop === null) {
if (range.start === null) {
range.start = new Date(dateText);
} else {
range.stop = new Date(dateText);
}
}
if (range.start !== null && range.stop !== null) {
if ($this.find('td').hasClass('selected')) {
//clear selected range
$this.children().removeClass('selected');
range.start = new Date(dateText);
range.stop = null;
//call internal method '_updateDatepicker'.
inst.inline = true;
} else {
//prevent internal method '_updateDatepicker' from being called.
inst.inline = false;
if (range.start > range.stop) {
d = range.stop;
range.stop = range.start;
range.start = d;
}
sel = (range.start.toString() === range.stop.toString()) ? 0 : (new Date(range.stop - range.start)).getDate();
for (i = 0; i <= sel; i += 1) {
ds = (range.start.getMonth() + 1).toString() + '/' + (range.start.getDate() + i).toString() + '/' + (range.start.getFullYear()).toString();
d = new Date(ds);
$this.find('td a').filter(function(index) {
return $(this).text() === d.getDate().toString();
}).parents('td').addClass('selected');
}
}
}
}
});
});
I became desperate and came up with a solution on my own. It wasn't pretty but I'll detail it.
I was able to construct a div that had the text boxes, buttons and the datepicker that looked like the Google Analytics control but I couldn't make the datepicker work properly. Eventually, I came up with the idea of creating a toggle variable that kept track of which date you were selecting (start date or end date). Using that variable in a custom onSelect event handler worked well but I still couldn't figure out how to get the cells between dates to highlight.
It took a while, but I slowly came to the realization that I couldn't do it with the datepicker as it existed out of the box. Once I figured that out, I was able to come up with a solution.
My solution was to add a new event call afterSelect. This is code that would run after all the internal adjustments and formatting were complete. I then wrote a function that, given a cell in the datepicker calendar, would return the date that it represented. I identified the calendar date cells by using jQuery to find all the elements that had the "ui-state-default" class. Once I had the date function and a list of all the calendar cells, I just needed to iterate over all of them and, if the date was in the correct range, add a new class to the parent.
It was extremely tedious but I was able to make it work.