Form Validation: Select - forms

I'm trying to display an error message if the select button in my form is not changed. It works fine for the rest but not the select, please help! and I know that the image wont work like that, I cant post images as a new member.
Html is:
<div id='first_name_error' class='error'><image code here></div>
<div><input type='text' name='first_name' id='first_name' placeholder="YOUR FIRST NAME*"></div>
Number of Guests:*<div id='guests_error' class='error'><img src='img/booking/error.png'></div>
<div><select name='guests' id='guests' style="margin:0px;" SIZE="1"><OPTION SELECTED value="guests">Guests<OPTION>2<OPTION>3<OPTION>4</SELECT></div>
Code Is
var error = false;
var first_name = $('#first_name').val();
var second_name = $('#second_name').val();
var email = $('#email').val();
var number = $('#number').val();
var guests = $('#guests').val();
var message = $('#message').val();
if(first_name.length == 0){var error = true;$('#first_name_error').fadeIn(500);}else{$('#first_name_error').fadeOut(500);}
if(guests.value == Guests){var error = true;$('#guests_error').fadeIn(500);}else{$('#guests_error').fadeOut(500);}

Notice that your "guests" variable is already set to the value of the select element (using jQuery val()). There is no need to attempt to access the "value" property of the "guests" variable.
Second, the comparison you are making is to the identifier Guests, not to the string "Guests". You'll want to put quotes around that to make it a string literal.
You can see an example of this here: http://jsfiddle.net/tbuCJ/

Related

How can I create a function that automatically takes data from Google Sheets and replaces the tags in a Slides template?

I am new to Google Apps Script and coding in general and wasn't entirely sure how to do this. I want to create code that allows me to create a new set of Google Slides based on a Slides template using the relevant rows from a Google Sheets document.
function generateNewSlides() {
var wsID = "would insert worksheet URL ID here";
var ws = SpreadsheetApp.openById(wsID).getSheetByName("Data");
var data = ws.getRange(2, 1, ws.getLastRow()-1, 5).getValues();
>the above should get the relevant table from the sheet
data.forEach(function(info){
if(info[0]){
var firstname = info[0];
var surname = info[1];
var email = info[2];
var phone = info[3];
var image = info[4];
var presName = info[5];
>the above are columns where the different pieces of data would be taken from for the placeholders in the Slides template
var slidesTemplateID = "would insert slides template URL ID here";
var slidesTemplate = SlidesApp.openById(slidesTemplateID);
var template = slidesTemplate.getSlides();
var folderID = "would insert desired folder ID for saving in here";
>the above should get me the Slides template
template.makeCopy(presName,DriveApp.getFolderById(folderID)); **>line where error occurred**
var newPresentation = DriveApp.getFilesByName(presName).next().getUrl();
var Presentation = SlidesApp.openByUrl(newPresentation);
>the above should create a copy and then open it
var shapes = (Presentation.getShapes());
shapes.forEach(function(shape){
shape.getText().replaceAllText('{{firstname}}',firstname);
shape.getText().replaceAllText('{{surname}}',surname);
shape.getText().replaceAllText('{{email}}',email);
shape.getText().replaceAllText('{{phone}}',phone);
shape.getText().replaceAllText('{{presname}}', presName)
});
>the above should replace all the placeholder tags in the template with the row data
}
});
}
Above is the code I have so far. The worksheet I am extracting data from has columns: first name, surname, email address, phone number, image (URL), and presentation name. When I try to run it I encounter an error on line 37 where it says template.makeCopy is not a function, however I am certain .makeCopy should be able to create a copy for it, no?
My main questions are:
1) What should I change to make it work, generating a new set slides for each row in the worksheet?
2) How can I add images to it replacing placeholder tags I've added in squares (not textboxes) in the template?
Thanks in advance!
Issue 1. makeCopy:
makeCopy(name, destination) is a method of the class File, which belongs to the Drive Service, not to the Slides Service. In your code, template is a list of Slides (you retrieve it by calling the method getSlides() from a Presentation). makeCopy cannot work here.
In order to make a copy of a Presentation, you should be using the Drive Service instead. You should replace these lines:
var slidesTemplate = SlidesApp.openById(slidesTemplateID);
var template = slidesTemplate.getSlides();
With this one:
var template = DriveApp.getFileById(slidesTemplateID);
Issue 2. Iterating through all shapes:
Next, you want to iterate through all shapes in your Presentation, and replace all placeholder tags with your desired text. In order to do that, you are using Presentation.getShapes(), which cannot work, since getShapes() is not a method of Presentation, but of Slide.
You should first iterate through all Slides in the Presentation, and for each Slide, iterate through all Shapes. You should replace these lines:
var shapes = (Presentation.getShapes());
shapes.forEach(function(shape){
// Replacing text lines
});
With these ones:
Presentation.getSlides().forEach(function(slide) {
slide.getShapes().forEach(function(shape) {
// Replacing text lines
})
});
Note:
In order to retrieve the copied presentation, you are currently doing this:
template.makeCopy(presName,DriveApp.getFolderById(folderID));
var newPresentation = DriveApp.getFilesByName(presName).next().getUrl();
var Presentation = SlidesApp.openByUrl(newPresentation);
There is no need to do this, you can just retrieve the ID of the created template, and open by ID, like this:
var copiedTemplate = template.makeCopy(presName,DriveApp.getFolderById(folderID));
var Presentation = SlidesApp.openById(copiedTemplate.getId());
Reference:
Slides Service
Drive Service

Name email attachment in Google Apps Script

I have the following G.A.S script to email a google sheet as a pdf attachment.
var spreadsheet = SpreadsheetApp.getActive();
var subject = spreadsheet.getRange("U1:U1").getValues();
var emailTo = spreadsheet.getRange("V1:V1").getValues();
var message = spreadsheet.getRange("W1:W1").getValues();
var pdf = DriveApp.getFileById(spreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:subject,content:pdf, mimeType:'application/pdf'};
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
The above code works well except that the file attached to the email message has a bizarre name like "[Ljava.lang.Object_#4e63998c" with no ".pdf" extension!
I am looking for a way to set a name for the pdf file before being attached to the email. The file name should equal the "subject" variable.
Thanks in advance.
Omid
Values retrieved by getValues() is 2 dimensional array. I think that the filename becomes such string because the array is used as the filename. Please retrieve the element from the array and try again. So could you please modify as follows?
From :
var attach = {fileName:subject,content:pdf, mimeType:'application/pdf'};
To :
var attach = {fileName:subject[0][0],content:pdf, mimeType:'application/pdf'};
You can also use the following modification. In this case, getValue() can retrieve the value as a string from the cell "U1".
From :
var subject = spreadsheet.getRange("U1:U1").getValues();
To :
var subject = spreadsheet.getRange("U1:U1").getValue();
Reference :
getValue()
getValues()
If this was not what you want, please tell me. I would like to think of other solutions.
I'm a bit late, but another way to solve this problem might be:
var spreadsheet = SpreadsheetApp.getActive();
var subject = spreadsheet.getRange("U1:U1").getValues();
var emailTo = spreadsheet.getRange("V1:V1").getValues();
var message = spreadsheet.getRange("W1:W1").getValues();
var pdf = DriveApp.getFileById(spreadsheet.getId())
.getAs('application/pdf')
.getBlob()
.setName(subject);
MailApp.sendEmail(emailTo, subject, message, {attachments:[pdf]});
The Blob class has a setName method https://developers.google.com/apps-script/reference/base/blob#setName(String), that can be chained into a Blob object (which is the result of getBlob())
After that you just need to add the Blob object inside attachments array of function MailApp.sendEmail

google script column change email notification

This is my first attempt at writing any kind of script, and also posting a question.
I have created a google sheet, and I would like to send an e-mail notification every time a row is added in this spreadsheet (or to keep things simple, every time a new cell is populated in column A).
I've been searching these forums for a couple of hours, and put together the following script, and tried installing both "onedit" & "onchange" triggers in google scripts but nothing working.
The following links have been helpful, but still not able to get the result I want. No notification is being triggered at all automatically upon the relevant edits.
how to attach onChange cell value event/script to google sheet
email notification if cell is changed
//Open function
function sendNotification() {
//Get spreadsheet & sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Define notification details
var recipients = "myname#email.com";
var subject = "New lead";
var body = 'A new lead has been added to Simba. For message: ' + message + '';
//Specify several sheet variables
var cell = ss.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
var message = '';
//Specify if statement
if(cell.indexOf('A')!=-1){
message = sheet.getRange('B'+ sheet.getActiveCell().getRowIndex()).getValue()
}
//Send the Email
MailApp.sendEmail(recipients, subject, body);
//Close function
};
var body = 'A new lead has been added to Simba. For message: ' + message + '';
At this line, "message" is undefined. It occurs an error. By this error, mail cannot be sent. Because the definition of "message" is below from this line. So please change this line to below
message = sheet.getRange('B'+ sheet.getActiveCell().getRowIndex()).getValue()
And please install a trigger for this function. The method of installing trigger is shown at your reference URL.

How to Use sendkeys when input type is number with Chrome

HTML
<ion-input [(ngModel)]="login.username" ngControl="username1" type="number" #username1="ngForm" id="userName" required>
</ion-input>
PROTRACTOR TEST CODE
let usern: ElementFinder = element.all(by.css('.text-input')).get(0);
usern.sendKeys('error');
expect(usern.getAttribute("value")).toEqual("error");
browser.sleep(500);
usern.clear();
browser.sleep(1000);
usern.sendKeys('12345');
The element is found but no text is entered into the field. If I change the element to type="text" the protractor command works.And the page view is 'e' and can't be clear.
Secondly if I send string like this: "we2124will", the actually send data is '2124' and the result from getAttribute("value") is 2124.
Thirdly even if I changed the sendKeys to number, the result is not full number string. For example:
Failures:
1) Login page should input username and password
Message:
Expected '125' to equal '12345'.
Stack:
Error: Failed expectation
There are some number missing.
Since you're using an <ion-input>, the actual HTML <input> tag will be nested within, and it won't have an id attribute. The effect is that the wrong element can get selected.
Try something like below to grab the nested input tag:
let username = element(by.id('userName')).all(by.tagName('input')).first();
username.sendKeys('fakeUser');
That worked for me.
As a workaround, you can introduce a reusable function that would perform a slow type by adding delays between send every key.
First of all, add a custom sleep() browser action, put this to onPrepare():
protractor.ActionSequence.prototype.sleep = function (delay) {
var driver = this.driver_;
this.schedule_("sleep", function () { driver.sleep(delay); });
return this;
};
Then, create a reusable function:
function slowSendKeys(elm, text) {
var actions = browser.actions();
for (var i = 0, len = text.length; i < len; i++) {
actions = actions.sendKeys(str[i]).sleep(300);
}
return actions.perform();
}
Usage:
var elm = $("ion-input#userName");
slowSendKeys(elm, "12345");
What version of protractor are you using?
Not sure this is the issue but try grabbing the element by ng-model
var elem = element(by.model('login.username'));
elem.sendKeys('error');
expect(elem.getAttribute("value")).toEqual("error");
elem.clear();
elem.sendKeys('12345');
expect(elem.getAttribute("value")).toEqual("12345");

Manipulate google form associated with a google sheet from app script in that sheet

I have a google spreadsheet which contains multiple sheets (or tabs) within it. Each sheet is populated from its own unique form. None of the forms are embedded in the spreadsheet.
Periodically, I need to delete all the data in the sheets, and also delete all the old responses which are saved in each of the forms. I can do this using a .gs script which resides in the spreadsheet. It accesses the form by its ID (the long string which appears in its URI). This requires the ID string to be hardcoded in my .gs script.
Ideally, I would like to access each form from the sheet object (i.e. the destination for each forms entries). Mock up code would look like this...
var ss = SpreadSheedApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var form = sheet.getMyAssociatedSourceForm(); // my dream method :-)
form.deleteAllResponses() // this method already exists
Does anyone know if this is possible? Or will I have to continue to use the ID (which is currently working)?
rgds...
I think you can do this without literally typing in ID's into your script. But, you would need to get every Form in your drive, loop through them all and get the destinationId() of every Form.
Google Documentation
Then compare the destinationId with the current spreadsheets ID, which you can get without needing to "hard code" it:
function deleteAllResponses() {
var thisSS_ID = SpreadsheetApp.getActiveSpreadsheet().getId();
var allForms = DriveApp.getFilesByType(MimeType.GOOGLE_FORMS);
var thisFormFile, thisFormFileID = "", thisForm, theDestID = "";
while (allForms.hasNext()) {
thisFormFile = allForms.next();
thisFormFileID = thisFormFile.getId();
thisForm = FormApp.openById(thisFormFileID);
try {
theDestID = thisForm.getDestinationId();
} catch(err) {
continue;
};
if (theDestID === "" || theDestID === undefined) {
continue;
};
if (theDestID === thisFormFileID) {
thisForm.deleteAllResponses();
};
};
};
I have not tested this, so don't know if it works. If it does, let me know in the comments section.