The idea of this apps script is to populate listbox LbxJobs based on the selected item in listbox LbxJobTypes.
I am getting an undefined value for e.parameter.LbxJobType which seems to be preventing conditional population of LbxJobs.
I successfully tested the handler(JobTypeValueHandler) by hard coding(I set JobType=T300_JOB_TYPE) JobTypeValueHandler function and the LbxJobs listbox populated as expected.
I do get "LbxJobType" when checking e.parameter.source. The listboxes were created in GUI builder.
var T200_JOB_TYPE = 1;
var T300_JOB_TYPE = 2;
function doGet() {
var app = UiApp.createApplication();
app.add(app.loadComponent("BasicCalculator"));
var Dischandler = app.createServerHandler('DiscClickHandler');
app.getElementById('chbxDiscl').addValueChangeHandler(Dischandler);
return app;
}
function DiscClickHandler(e) {
var app = UiApp.getActiveApplication();
var Discpanel = app.getElementById('FLpnlDisc');
BCalcSetup(app);
Discpanel.setVisible(false);
return app;
}
function BasicClickHandler(e) {
var app = UiApp.getActiveApplication();
return app;
}
function BCalcSetup(app){
var BCalcpanel = app.getElementById('APnlBCalc');
var lbxJobType = app.getElementById('LbxJobType');
var JobTpyehandler = app.createServerChangeHandler('JobTypeValueHandler');
var lbxJobs = app.getElementById('LbxJobs');
JobTpyehandler.addCallbackElement(lbxJobType);
lbxJobType.addChangeHandler(JobTpyehandler);
lbxJobType.addItem('Title 200');
lbxJobType.addItem('Title 300');
loadClassifications(lbxJobs,T200_JOB_TYPE);
BCalcpanel.setVisible(true);
}
function JobTypeValueHandler(e) {
var app = UiApp.getActiveApplication();
var JobType=T200_JOB_TYPE;
var lboxJobs=app.getElementById('LbxJobs');
if (e.parameter.LbxJobType=='Title 300'){JobType=T300_JOB_TYPE;}
loadClassifications(lboxJobs,JobType);
app.close();
return app;
}
function loadClassifications(lbox,JobType){
var spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID);
lbox.clear();
if (JobType==T300_JOB_TYPE){
var T3data =spreadsheet.getRangeByName('Title300Jobs').getValues();
for (var row1 = 1; row1 < T3data.length; row1++) {
lbox.addItem(T3data[row1]);
}
}else{
var T2data =spreadsheet.getRangeByName('Title200Jobs').getValues();
for (var row2 = 1; row2 < T2data.length; row2++) {
lbox.addItem(T2data[row2]);
}
}
}
I feel kind of silly but I figured this out. The problem I had was I did not fill in the Name property for these listboxes when I created the interface in GUI builder. I went back into GUI builder and filled in the name property for each box and and now it works like a champ. Live and learn
Related
I am very very very new to all this. I need help, I am trying to use script editor to get the date statically stamped in one column when something is entered in a different column. I figured how to do this for one tab but I need this to happen on multiple tabs in the same sheet and I'm struggling to get it to work. Is there one code that will work for this? This is the script I was using for one tab:
/**
* Creates a Date Stamp if a column is edited.
*/
//CORE VARIABLES
// The column you want to check if something is entered.
var COLUMNTOCHECK = 9;
// Where you want the date time stamp offset from the input location. [row, column]
var DATETIMELOCATION = [0,-8];
// Sheet you are working on
var SHEETNAME = 'Sheet 2'
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//checks that we're on the correct sheet.
if( sheet.getSheetName() == SHEETNAME ) {
var selectedCell = ss.getActiveCell();
//checks the column to ensure it is on the one we want to cause the date to appear.
if( selectedCell.getColumn() == COLUMNTOCHECK) {
var dateTimeCell = selectedCell.offset(DATETIMELOCATION[0],DATETIMELOCATION[1]);
dateTimeCell.setValue(new Date());
}
}
}
Thank you for your time in advance.
To proceed with the function on multiple sheets, you can check for the sheet name in an array of acceptable names.
function onEdit() {
var colToCheck = 9;
// Offset from the input [row, column]
var dateOffset = [0, -8];
// Sheets to proceed on
var sheetNames = ['Sheet 2', 'Sheet 3'];
var sheet = SpreadsheetApp.getActive().getActiveSheet();
var name = sheet.getName();
if (sheetNames.indexOf(name) > -1) {
var cell = sheet.getActiveCell();
var col = cell.getColumn();
if (col == colToCheck) {
var dateTimeCell = cell.offset(dateOffset[0], dateOffset[1]);
dateTimeCell.setValue(new Date());
}
}
}
References
Arrays
indexOf()
EDIT ONE
If you want multiple options, you could set them up in arrays. The order of the elements in the arrays must match.
This code assumes that the timestamp is always on the same row.
function onEdit() {
var sheetNames = ['Sheet 2', 'Sheet 3'];
var colsToCheck = [9, 15];
var colOffsets = [-8, -4];
var sheet = SpreadsheetApp.getActive().getActiveSheet();
var name = sheet.getSheetName();
var index = sheetNames.indexOf(name);
if (index > -1) {
var cell = sheet.getActiveCell();
var col = cell.getColumn();
if (col == colsToCheck[index]) {
var dateTimeCell = cell.offset(0, colOffsets[index]);
dateTimeCell.setValue(new Date());
}
}
}
EDIT TWO
For those of you who would prefer objects
function onEdit() {
var sheets = {
'Sheet 2': {
checkCol: 9,
offset: -8
},
'Sheet 3': {
checkCol: 15,
offset: -4
}
};
var sheet = SpreadsheetApp.getActive().getActiveSheet();
var name = sheet.getSheetName();
var settings = sheets[name];
if (settings) {
var cell = sheet.getActiveCell();
var col = cell.getColumn();
if (col == settings.checkCol) {
var dateTimeCell = cell.offset(0, settings.offset);
dateTimeCell.setValue(new Date());
}
}
}
So I'm currently using this one: http://jsfiddle.net/nawdpj5j/10/
Now what I need is that when I flip one card (doesn't matter which one) and then flip another one the first one resets/turnes back.
I think I need to add something in here:
var init = function() {
var flippers = document.getElementsByClassName("flip");
for(i = 0; i < flippers.length; i++){
flippers[i].addEventListener( 'click', function(){
var cardID = this.dataset.targetid;
var card = document.getElementById(cardID);
card.toggleClassName('flipped');
}, false);
}
};
Thank you in advance!
You can get an array of all flipped cards and flip them back whenever a card is flipped like so:
var init = function() {
var flippers = document.getElementsByClassName("flip");
for (i = 0; i < flippers.length; i++) {
flippers[i].addEventListener('click', function() {
var cardID = this.dataset.targetid;
var card = document.getElementById(cardID);
var flipped = document.getElementsByClassName('flipped');
for (i = 0; i < flipped.length; i++) {
if (card !== flipped[i]) {
flipped[i].toggleClassName('flipped');
}
}
card.toggleClassName('flipped');
}, false);
}
};
window.addEventListener('DOMContentLoaded', init, false);
Here is a link to a working demo JS FIDDLE
I'm new to JavaScript and Google Apps Script so this is by all means a 'beginner' question I'm sure.
I'm using Google Apps Script in a spreadsheet to format single cells using an onEdit trigger. The format of the cell is based on user input from a custom UI app containing 6 buttons. The problem I'm having is the onClickHandler function doesn't see the same active cell that triggered the onEdit trigger initially; rather, the getActiveCell method called in the Handler is returning the cell just below the cell that was edited that became active as a result of the user pressing 'Enter' and the active range moving down one cell.
How do I get the handler to focus on the same cell that initiated the onEdit trigger? I'm not sure if I should somehow be passing the active cell from the event that triggered the onEdit code to the Handler via button parameters or somehow getting a value returned to the onEdit code to make the changes to the edited cell there. Whichever way is correct, I'm not sure how to go about it.
function onEdit(event)
{
var sheet = event.source.getActiveSheet();
var cell = sheet.getActiveCell();
var cellR = cell.getRow();
var cellC = cell.getColumn();
var cellValue = cell.getValue();
var active_spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
if ((cellR >= 14 && cellR <= 21 && cellC >= 1 && cellC <= 7) ||
(cellR >= 34 && cellR <= 41 && cellC >= 1 && cellC <= 7)) {
displayUserOptions();
}
}
function displayUserOptions()
{
var app = UiApp.createApplication().setTitle('Choose Equipment Class').setHeight(40).setWidth(350);
var handler = app.createServerHandler('onClickHandler');
var button1 = app.createButton('War').setTabIndex(1).setId('war').addClickHandler(handler);
var button2 = app.createButton('Nature').setTabIndex(2).setId('nature').addClickHandler(handler);
var button3 = app.createButton('Balance').setTabIndex(3).setId('balance').addClickHandler(handler);
var button4 = app.createButton('Fortune').setTabIndex(4).setId('fortune').addClickHandler(handler);
var button5 = app.createButton('Chaos').setTabIndex(5).setId('chaos').addClickHandler(handler);
var button6 = app.createButton('Generic').setTabIndex(6).setId('generic').addClickHandler(handler);
var mypanel = app.createHorizontalPanel();
mypanel.add(button1); mypanel.add(button2); mypanel.add(button3);
mypanel.add(button4); mypanel.add(button5); mypanel.add(button6);
app.add(mypanel);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
function onClickHandler(e) {
var app = UiApp.getActiveApplication();
var sheet = SpreadsheetApp.getActiveSheet();
var cell = sheet.getActiveCell();
if (e.parameter.source == 'war') {
Logger.log("War button pressed");
Browser.msgBox(cell.getValue());
cell.setValue("War!"); // *This string is committing to the wrong cell.
}
app.close();
return app;
}
You could handle that in your handler function simply like this :
function onClickHandler(e) {
var app = UiApp.getActiveApplication();
var sheet = SpreadsheetApp.getActiveSheet();
var rowIndex = cell.getRowIndex()-1;
var colIndex = cell.getColumnIndex();
sheet.setActiveRange(sheet.getRange(rowIndex,colIndex));
var cell = sheet.getActiveCell();
...
or you can store the coordinates of the cell in your Ui like in the example below (see the hidden widget and the callBackElement)
This has the advantage that it works even if the user uses the TAB key (or a mouseClick on another cell) to validate his entry... so I would recommend this approach even if it's a bit more code to add ;-)
function onEdit(event){
var sheet = event.source.getActiveSheet();
var cell = sheet.getActiveCell();
var cellR = cell.getRow();
var cellC = cell.getColumn();
var cellValue = cell.getValue();
var active_spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
if ((cellR >= 14 && cellR <= 21 && cellC >= 1 && cellC <= 7) ||
(cellR >= 34 && cellR <= 41 && cellC >= 1 && cellC <= 7)) {
displayUserOptions(cellR,cellC);
}
}
function displayUserOptions(cellR,cellC){
var app = UiApp.createApplication().setTitle('Choose Equipment Class').setHeight(40).setWidth(350);
var mypanel = app.createHorizontalPanel();
var hidden = app.createHidden('coord').setValue(cellR+'|'+cellC);
mypanel.add(hidden);
var handler = app.createServerHandler('onClickHandler').addCallbackElement(mypanel);
var button1 = app.createButton('War').setTabIndex(1).setId('war').addClickHandler(handler);
var button2 = app.createButton('Nature').setTabIndex(2).setId('nature').addClickHandler(handler);
var button3 = app.createButton('Balance').setTabIndex(3).setId('balance').addClickHandler(handler);
var button4 = app.createButton('Fortune').setTabIndex(4).setId('fortune').addClickHandler(handler);
var button5 = app.createButton('Chaos').setTabIndex(5).setId('chaos').addClickHandler(handler);
var button6 = app.createButton('Generic').setTabIndex(6).setId('generic').addClickHandler(handler);
var mypanel = app.createHorizontalPanel();
mypanel.add(button1); mypanel.add(button2); mypanel.add(button3);
mypanel.add(button4); mypanel.add(button5); mypanel.add(button6);
app.add(mypanel);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
function onClickHandler(e) {
Logger.log(Utilities.jsonStringify(e));
var app = UiApp.getActiveApplication();
var sheet = SpreadsheetApp.getActiveSheet();
var rowIndex = Number(e.parameter.coord.split('|')[0]);
var colIndex = Number(e.parameter.coord.split('|')[1])
sheet.setActiveRange(sheet.getRange(rowIndex,colIndex));
var cell = sheet.getActiveCell();
if (e.parameter.source == 'war') {
Logger.log("War button pressed");
Browser.msgBox(cell.getValue());
cell.setValue("War!"); // *This string is committing to the wrong cell.
}else{
cell.setBackground('#ffffaa');// just for test to confirm that the right cell has been modified
}
app.close();
return app;
}
NOTE : if you prefer that the "active" cell is not changed but still want that the value comes in the right cell you can do it like this :
(change in the handler function)
...
var rowIndex = Number(e.parameter.coord.split('|')[0]);
var colIndex = Number(e.parameter.coord.split('|')[1])
var cell = sheet.getRange(rowIndex,colIndex);
...
Using google apps script & google site, I'm trying to write down a form and get the answers in a spreadsheet.
Here is my work for now on :
function doGet(){
var app = UiApp.createApplication().setTitle('Radio Button Demo');
var radio1 = app.createVerticalPanel();
var radio11 = app.createRadioButton('group1','Oui').setName('oui1').setId('oui1');
var radio12 = app.createRadioButton('group1','Non').setName('non1').setId('non1');
radio1.add(radio11).add(radio12);
app.add(radio1);
var radio2 = app.createVerticalPanel().setId('question2').setVisible(false);
var radio21 = app.createRadioButton('group2','Oui').setName('oui2').setId('oui2');
var radio22 = app.createRadioButton('group2','Non').setName('non2').setId('non2');
radio2.add(radio21).add(radio22);
app.add(radio2);
var radio3 = app.createVerticalPanel().setId('question3').setVisible(false);
var radio31 = app.createRadioButton('group3','Oui').setName('oui3').setId('oui3');
var radio32 = app.createRadioButton('group3','Non').setName('non3').setId('non3');
radio3.add(radio31).add(radio32);
app.add(radio3);
var radio4 = app.createVerticalPanel().setId('question4').setVisible(false);
var radio41 = app.createRadioButton('group4','Cool').setName('oui4').setId('oui4');
var radio42 = app.createRadioButton('group4','Or not').setName('non4').setId('non4');
radio4.add(radio41).add(radio42);
app.add(radio4);
// handler to make value of question 1 change
var handler11 = app.createServerValueChangeHandler('showstatus1_1');
handler11.addCallbackElement(radio1);
radio11.addValueChangeHandler(handler11);
var handler12 = app.createServerValueChangeHandler('showstatus1_2');
handler12.addCallbackElement(radio1);
radio12.addValueChangeHandler(handler12);
// handler to make value of question 2 change
var handler21 = app.createServerValueChangeHandler('showstatus2_1');
handler21.addCallbackElement(radio2);
radio21.addValueChangeHandler(handler21);
var handler22 = app.createServerValueChangeHandler('showstatus2_2');
handler22.addCallbackElement(radio2);
radio22.addValueChangeHandler(handler22);
// handler to make value of question 3 change
var handler31 = app.createServerValueChangeHandler('showstatus3_1');
handler31.addCallbackElement(radio3);
radio31.addValueChangeHandler(handler31);
var handler32 = app.createServerValueChangeHandler('showstatus3_2');
handler32.addCallbackElement(radio3);
radio32.addValueChangeHandler(handler32);
// handler to make value of question 4 change
var handler41 = app.createServerValueChangeHandler('showstatus4_1');
handler41.addCallbackElement(radio4);
radio41.addValueChangeHandler(handler41);
var handler42 = app.createServerValueChangeHandler('showstatus4_2');
handler42.addCallbackElement(radio4);
radio42.addValueChangeHandler(handler42);
// functions to change values of question 1
function showstatus1_1(e){
var app = UiApp.getActiveApplication();
var radioValue = e.parameter.oui1
app.getElementById('non1').setValue(false);
app.getElementById('question2').setVisible(true);
return app;
}
function showstatus1_2(e){
var app = UiApp.getActiveApplication();
var radioValue = e.parameter.non1;
app.getElementById('oui1').setValue(false);
app.getElementById('question2').setVisible(true);
return app;
}
// functions to change values of question 2
function showstatus2_1(e){
var app = UiApp.getActiveApplication();
var radioValue = e.parameter.oui2
app.getElementById('non2').setValue(false);
return app;
}
function showstatus2_2(e){
var app = UiApp.getActiveApplication();
var radioValue = e.parameter.non2;
app.getElementById('oui2').setValue(false);
return app;
}
// functions to change values of question 3
function showstatus3_1(e){
var app = UiApp.getActiveApplication();
var radioValue = e.parameter.oui3
app.getElementById('non3').setValue(false);
return app;
}
function showstatus3_2(e){
var app = UiApp.getActiveApplication();
var radioValue = e.parameter.non3;
app.getElementById('oui3').setValue(false);
return app;
}
// functions to change values of question 4
function showstatus4_1(e){
var app = UiApp.getActiveApplication();
var radioValue = e.parameter.oui4
app.getElementById('non4').setValue(false);
return app;
}
function showstatus4_2(e){
var app = UiApp.getActiveApplication();
var radioValue = e.parameter.non4;
app.getElementById('oui4').setValue(false);
return app;
}
My first question is How to make question 3 and 4 visible based on the answers of question 1 and 2. I have found how to do it based on the answer of 1 question but I'm stuck with multiple questions.
For example : Make question 3 visible if the answer is "Oui" and "Oui", else make question 4 visible !
My second question is : How to get the value of the different questions ?
I would like to write in an existing spreadsheet the answers oof the different users, and also the choice. But i'm stuck when I try to find a way of getting the answers of users.
Thanks for helping me if you have time,
Vincent
radioButtons are a bit tricky in GAS... to work as they should, they need to have the same name but if they have the same name they return a result in the handler function that can't be read, ie e.parameter.radioButtonName is not useable since they are not differentiated.
There are simple workarounds though. Here is an example to show how you could handle that using clientHandlers and a (visible or invisible) textBox. there is also a function that handles the "reverse process", ie set the radioButtons vale from data coming from another widget. That should help you so answer both of your questions.
function radiotest() {
var app = UiApp.createApplication();
var panel = app.createVerticalPanel();
var radioValue = app.createTextBox().setId('radioValue');
radioValue.setId("radioValue").setName("radioValue");
var listhandler = app.createServerHandler('listhandler').addCallbackElement(panel);
var list = app.createListBox().addChangeHandler(listhandler).setName('list');
for(var i = 1; i < 10; i++){
var name = 'choice '+i;
list.addItem('Activate '+name,name);
var handler = app.createClientHandler().forTargets(radioValue).setText(name);
panel.add(app.createRadioButton('radioButtonGroup',name).addValueChangeHandler(handler).setId(name));
}
panel.add(radioValue);
var getit=app.createButton("Valide").setId("val");
panel.add(getit).add(list);
var handler = app.createServerHandler("valide");
handler.addCallbackElement(panel);
getit.addClickHandler(handler);
app.add(panel);
SpreadsheetApp.getActiveSpreadsheet().show(app);// show app
}
//
function valide(e){ ;// This function is called when key "validate" is pressed
var sh = SpreadsheetApp.getActiveSheet();
var RadioButton = e.parameter.radioValue;
sh.getRange('A1').setValue(RadioButton);
var app = UiApp.getActiveApplication();
return app;
}
function listhandler(e){ ;// This function is called when listBox is changed
var sh = SpreadsheetApp.getActiveSheet();
var app = UiApp.getActiveApplication();
var listvalue = e.parameter.list;
var radioValue = app.getElementById('radioValue').setValue(listvalue);
sh.getRange('A2').setValue(listvalue);
var radiobutton = app.getElementById(listvalue);
radiobutton.setValue(true);
return app;
}
Run this test from a spreadsheet and you'll get something like this :
EDIT :
following your comment, here is an efficient way to build such a multiple choices questionary, here is the test app
function doGet() {
var app = UiApp.createApplication().setTitle('test Questionnaire');
var panel = app.createVerticalPanel();
var sHdlr = app.createServerHandler('react').addCallbackElement(panel);
var questions = ['<b>Question Numéro 1 :</b><br>Faites votre choix parmis les 4 possibilités suivantes','<b>Question 2</b><br>Encore un fois, faites votre choix','<b>Question 3</b><br>encore un effort...','<b>Question 4</b><br>vous y êtes presque...'];
var Qitems = [['choix1 de Q1','choix2 de Q1','choix3 de Q1','choix4 de Q1'],['choix1 de Q2','choix2 de Q2','choix3 de Q2','choix4 de Q2'],
['choix1 de Q3','choix2 de Q3','choix3 de Q3','choix4 de Q3'],['choix1 de Q4','choix2 de Q4','choix3 de Q4','choix4 de Q4']];
var Qpanel = [];
for (var n=0 ; n<questions.length ; ++n){
var Qval = app.createTextBox().setId('Qvalue'+n).setName('Qvalue'+n).setVisible(false);
Qpanel[n] = app.createVerticalPanel().setId('QP'+n).setVisible(false).add(app.createHTML(questions[n])).add(Qval).setStyleAttribute('padding','10px');
panel.add(Qpanel[n]);
for(var q=0;q<Qitems[n].length;++q){
var name = Qitems[n][q]
var handler = app.createClientHandler().forTargets(Qval).setText(name);
Qpanel[n].add(app.createRadioButton('radioButtonQ'+n,name).addClickHandler(handler).setId(name).addClickHandler(sHdlr));
}
}
app.add(panel);
Qpanel[0].setVisible(true);
return app;
}
function react(e){
var app = UiApp.getActiveApplication();
var source = e.parameter.source;
var answer = [];
for(var n = 0; n < 4 ; ++n){
answer[n] = e.parameter['Qvalue'+n];
Logger.log('answer '+ (n+1) + ' = '+answer[n]+' source = '+source)
}
if(answer[0]=='choix1 de Q1'){app.getElementById('QP'+1).setVisible(true)}
if(answer[1]=='choix1 de Q2'||answer[1]=='choix3 de Q2'){app.getElementById('QP'+2).setVisible(true)}
if(answer[2]=='choix1 de Q3'||answer[2]=='choix3 de Q3'){app.getElementById('QP'+3).setVisible(true)}
if(answer[3]=='choix1 de Q4'){
app.add(app.createHTML('YESSSSSSSSS ... !!<br>Vous avez réussi !<br> vos réponses sont les suivantes : '+answer.join(' + ')).setStyleAttribute('padding','20px'))
}
return app;
}
I think I'm beginning to like this coding stuff. Anyway in my current Shooting Gallery project I have a JavaScript question. I'm building in Unity3d and I get a "transform" is not a member of "Object" error on the code inserted below.
var newball;
static var tempBasketBall :Rigidbody;
private var canFire = true;
var pos :Transform[];
var ball1 :Rigidbody;
var canControl1 = true;
var destroyTime :int = 6;
var player1 :GameObject;
var b1Parent :Transform;
var yVel :float;
var zVel :float;
function Start()
{
ball1 = Instantiate (tempBasketBall, pos[0].position, pos[0].rotation);
ball1.transform.parent = b1Parent;
}
function Update() {
if(Input.GetButton("Fire1"))
animation.PlayQueued("fire", QueueMode.PlayNow);
}
function TapFunction() {
animation.PlayQueued("fire", QueueMode.PlayNow);
player1.animation.PlayQueued("fire");
ball1.transform.parent = null;
ball1.useGravity = true;
ball1.velocity = transform.TransformDirection(0, yVel, zVel);
MakeBall1(pos[0]);
canControl1 = false;
player1.animation.PlayQueued("idle");
}
function MakeBall1(pos)
{
yield new WaitForSeconds(1);
ball1 = Instantiate(tempBasketBall, pos.transform.position, pos.transform.rotation);
ball1.transform.parent = b1Parent;
canControl1 = true;
}
The error is in the MakeBall function at the end. To my untrained mind, it seems I established the
transform in the start function. As usual any assistance and shared knowledge will be tremendously appreciated.
Transform(you are passing as argument an onject of this tipe) does not have a "transform" member,you should use pos.position