How to use dynamic e.parameter with Google Apps? - textbox

I have created a grid in a doGet() function. This grid contains a dynamic number of rows choose by the user. In each rows i have some TextBox. I would like to be able to get all the data inserted by the user on the textboxes once the user clicked on the submit button.
So i give a dynamic ID to each textBox :
app.createTextBox().setName('gridText'+countRow);
countRow ++;
.........
My problem is that I dont know how to dynamicaly access to my TextBox on my submit function.
I tried something like this :
for( i = 0 ; i < countRow ; i++){
var buffer = e.parameter[e.parameter.gridText]+i;
.........
}
based on this : http://productforums.google.com/forum/#!category-topic/apps-script/services/nWN14AQ-9gQ
But it does'nt work... whereas this works :
var buffer = e.parameter.gridText3;
Any idea of what i'm doing wrong ?
Thanks for your help

Try
var buffer = e.parameter['gridText' + i.toString()];

Related

Prevent Duplicate Google form submissions which add to a google sheet

I have a google form which reflects its submissions to a google sheet, is there anyway i can prevent a duplicate phone number to be added in the google sheet?
you can use triggers which fires on every form submit and somewhat the following script to do whatever you want.
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActive().getSheetByName('sheet1') //change sheet name
var range = sheet.getRange("C").getValues(); // assuming mobile is 3rd field so C
var res = e.response.formResponses.getItemResponses();
var mobile = res[2].getResponse(); // if mobile is 3rd field res[2] (0 indexed)
for(i = 0; i < range.length; i++) {
if(mobile==range[i][0]) // mobile number found, delete it if more than one found?
}
You may also want to check out this for help.

Display a Message box based on a value in a cell in Google spreadsheet

I am trying to display a browser message box based on a particular value in range. I tried with the following
function onEdit(e){
var sheet = SpreadsheetApp.getActiveSheet();
var panType = sheet.getRange("A4:A100").getValues();
if (panType=="CSF");
Browser.msgBox('Make sure you enter the PAN No in the alloted slot');
}
But the problem is, with each and every edit in any cell, the message box pops up.
The said range A4:A100 has a validation dropdown with options like "New" and "CSF". So whenever the value CSF is chosen, the dialogue box should popup.
Thanks
You just need to check if it is the xorrect sheet, column, and value. Event has these values. If they match, show your messagebox.
function onEdit(event){
var sheet = event.source.getActiveSheet().getName()
var editedCell = event.range.getSheet().getActiveCell();
if(sheet=="Sheet1"){
if(editedCell.getColumn() == 1 && event.value=="CSF"){
Browser.msgBox('Make sure you enter the PAN No in the alloted slot');
}}}

AppMaker and picker widget - uploading to a specific folder

I'm trying to have a button to allow users to upload a file, into a specific folder. I tried to follow other advise, and add this hook to
onPickerInit:
var uploadView = new google.picker.DocsUploadView()
uploadView.setParent('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'); // test folder
pickerBuilder.addView(uploadView);
I've set the MULTISELECT_ENABLED feature (without it, the destination folder is not respected), and I can in fact now upload the files where they belong. Yay!
HOWEVER: The picker widget now has two upload tabs. The first one just does the regular upload into the drive main folder, the second tab does the right thing. My guess is that appmaker contstructs the first upload tab behind the curtains and there is no feature to disable this.
This is obviously fairly quirky and hardly usable. My questions are:
1) are there (possibly undocumented) API calls in the pickerbuilder to remove the original upload view?
2) Is it possible to respect the destination folder even is the MULTISELECT feature is off ?
Many thanks in advance for any pragmatic solutions!
EDIT 07/28/2020
Due to the constant changes in drive picker, this code aims for a more permanent solution:
var folderId = "10fYS3l32R6gk79POOSS8X_Vbsz7vqzRWX"; //the desired folder id
var prps = [];
for(var prop in pickerBuilder){
var value = pickerBuilder[prop];
if(!!value){
if(typeof(value)==="object"){
var proto = value.__proto__; //jshint ignore: line
if(!!proto["addLabel"] && !!proto["addView"]){
prps.push(prop);
for(var key in value){
var target = value[key];
var type = Object.prototype.toString.call(target);
if(type === "[object Array]"){
prps.push(key);
for(var key in target[0]){
var value = target[0][key];
if(typeof(value)==="object"){
prps.push(key);
}
}
for(var key in target[0]){
var value = target[0][key];
if(typeof(value)==="string") {
prps.push(key);
}
}
}
}
}
}
}
}
var views = pickerBuilder[prps[0]][prps[1]];
for(var i=0; i<views.length; i++){
var view = views[i];
if(view[prps[3]] === "upload"){
view[prps[2]].parent = folderId;
}
}
EDIT 06/29/2020
There has been another change in the Drive picker API. To make this work please change what you have to:
var folderId = "10fYS3l32R6gk79POOSS8X_Vbsz7vqzRWX"; //the desired folder id
pickerBuilder.rw.kf["0"].Ta.parent = folderId;
EDIT 05/26/2020
There has been another change in the Drive picker API. To make this work please change what you have to:
var folderId = "10fYS3l32R6gk79POOSS8X_Vbsz7vqzRWX"; //the desired folder id
pickerBuilder.xw.jf["0"].Ta.parent = folderId;
EDIT 02/17/2020
There has been a change in the Drive picker API. To make this work please change what you have to:
var folderId = "10fYS3l32R6gk79POOSS8X_Vbsz7vqzRWX"; //the desired folder id
pickerBuilder.mw.$e["0"].Ra.parent = folderId;
To answer your questions directly:
1.) YES
2.) YES
Now, let's dig a little bit into what's happening under the hood. You are right:
My guess is that appmaker contstructs the first upload tab behind the curtains and there is no feature to disable this.
However, we can manipulate the object. So instead of creating a new picker view, let's simply configure the default one to upload the files to the folder you want. We can achieve that by doing the following:
1.) After you insert a Drive Picker into your UI, make sure the Drive Picker Properties are all empty:
2.) Next, go to the event handlers and click on the onPickerInit event handler. Type in this code:
var folderId = "10fYS3l32R6gk79POOSS8X_Vbsz7vqzRWX"; //the desired folder id
pickerBuilder.SW.Vq["0"].mc.parent = folderId;
In summary, I've come to the conclusion that the property SW contains the array of drive views, which are saved under the property Vq. Vq["0"] is the first view in the array of views and the mc property contains the features; hence parent = folderId.

Cycle through array in iOS

In this app I save an NSOrderedSet of cards to a "Subject" entity in core data so that users can quiz themselves. The card flips and drags in tinder like fashion well but in the update card method I'm having some trouble. The current card displays fine as I set that in view did load (the first card of the NSOrderedSet's array property). When I drag and update however it immediately goes to the last card, for example if I have 5 cards in a deck it will start with the first then immediately go to the fifth. What would be the best way to update this method so that it will cycle through as desired?
I suppose I should pass it an index property like a tableViewDelegate method but if someone has done something like this before and has a better way that's greatly appreciated.
Thanks for the help like always.
func updateCard() {
//cycle through questions here
for var i = 0; i < (self.subject.cards?.count)!; i++ {
self.currentCard = self.subject.cards?.array[i] as? Card
self.draggableView.questionLabel.text = self.currentCard?.question
self.draggableView.answerLabel.text = self.currentCard?.answer
}
}
Currently, when you call updateCard the for loop is computing at computer-speed and you only get to see the last index.
Here's one option:
In your class, set a stored variable called selectedCardIndex as an implementation detail and then just increment and update the view in updateCard.
var selectedCardIndex = 0
func updateCard() {
self.selectedCardIndex += 1
self.currentCard = self.subject.cards?.array[self.selectedCardIndex] as? Card
self.draggableView.questionLabel.text = self.currentCard?.question
self.draggableView.answerLabel.text = self.currentCard?.answer
}

Add an event to HTML elements with a specific class

I'm working on a modal window, and I want to make the function as reusable as possible. Said that, I want to set a few anchor tags with a class equals to "modal", and when a particular anchor tag is clicked, get its Id and pass it to a function that will execute another function based on the Id that was passed.
This is what I have so far:
// this gets an array with all the elements that have a class equals to "modal"
var anchorTrigger = document.getElementsByClassName('modal');
Then I tried to set the addEventListener for each item in the array by doing this:
var anchorTotal = anchorTrigger.length;
for(var i = 0; i < anchorTotal ; i++){
anchorTrigger.addEventListener('click', fireModal, false);
}
and then run the last function "fireModal" that will open the modal, like so:
function fireModal(){
//some more code here ...
}
My problem is that in the "for" loop, I get an error saying that anchorTrigger.addEvent ... is not a function.
I can tell that the error might be related to the fact that I'm trying to set up the "addEventListener" to an array as oppose to individual elements, but I don't know what I'm supposed to do.
Any help would be greatly appreciated.
anchorTrigger[i].addEventListener...

Resources