Displaying PopupPanel - google-apps-script

THREE QUESTIONS:
Why does my popupPanel not display correctly?
How can I only get it to appear once if clicked multiple times?
How can I add a Close button to the popupPanel?
function showPassword(e){
var app = UiApp.getActiveApplication();
var vrtPanel = app.getElementById("vrtPanel");
//Create Spreadsheet Source
var spSheet = SpreadsheetApp.openById('0Aur3owCpuUY-dF92dGp3c2RORGNkY011dGFnMjBXbXc');
var spTeacherList = spSheet.getSheetByName('TeacherList');
//Create the form elements
var hdlTeacherName = app.createServerHandler('getTeacherName').addCallbackElement(vrtPanel);
var lbxTeacherName = app.createListBox().setId('lbxTeacherName').setName('lbxTeacherName').addChangeHandler(hdlTeacherName);
var lstTeacherNames = spTeacherList.getRange(1,1,spTeacherList.getLastRow(),1).getValues();
lstTeacherNames.sort();
for (var l = 0; l < lstTeacherNames.length; l++) {
lbxTeacherName.addItem(lstTeacherNames[l],l);
}
var lblTeacherName = app.createLabel('Teacher Name:');
var txtTeacherName = app.createTextBox().setName('txtTeacherName').setId('txtTeacherName').setVisible(false);
var lblExt = app.createLabel('Ext:');
var txtExt = app.createTextBox().setName('txtExt').setId('txtExt');
var lblEmail = app.createLabel('Email:');
var txtEmail = app.createTextBox().setName('txtEmail').setId('txtEmail');
var lblSchool = app.createLabel('School:');
var txtSchool = app.createTextBox().setName('txtSchool').setId('txtSchool');
var btnCreate = app.createButton('Create Event');
//Create validation handler
var valSubmit = app.createServerClickHandler('valSubmit');
valSubmit.addCallbackElement(vrtPanel);
//Add this handler to the button
btnCreate.addClickHandler(valSubmit);
//Add all the elemnts to the panel
var formTable = app.createFlexTable().setCellPadding(3);
vrtPanel.add(formTable);
formTable
.setWidget(0,0,lbxTeacherName)
.setWidget(0,1,txtExt)
.setWidget(0,2,txtTeacherName)
.setWidget(1,0,txtEmail)
.setWidget(2,0,btnCreate);
//Add all the panel to the popup
var popPassword = app.createDecoratedPopupPanel(false, true).setId("popPassword");
popPassword.add(vrtPanel);
app.add(vrtPanel);
app.add(popPassword);
return app;
}

There is some disorder in the way you use the popupPanel, you have to add it to your main panel and add the table you want to show in it to the popup itself.
You should also decide where you want to show it.
Here is the relevant part of your code working :
//Add all the elemnts to the panel
var formTable = app.createFlexTable().setCellPadding(3);
formTable
.setWidget(0,0,lbxTeacherName)
.setWidget(0,1,txtExt)
.setWidget(0,2,txtTeacherName)
.setWidget(1,0,txtEmail)
.setWidget(2,0,btnCreate);
var popPassword = app.createDecoratedPopupPanel(false, true).setPopupPosition(150,300).setId("popPassword");
vrtPanel.add(popPassword.add(formTable));
popPassword.show();
return app;
}
To answer the second point : il won't show up multiple time, just once.
point 3 : if you want to close it with a button you will have to add a button and a server handler to close it (by getting it with an ID just as any other widget) but it would be easier and userfriendly to take advantage of the autohide feature, just change the definition parameters like this :
var popPassword = app.createDecoratedPopupPanel(true).setPopupPosition(150,300).setId("popPassword");
edit : in the example above you can also use
app.getElementById('popPassword').hide()
in your 'valSubmit' function (called by the button) even without the autohide so the popup will hide when the handler function executes.

Related

LimeJs HTML5 Sound on Chrome breaks my file

I have just start learning LimeJS, but i have a problem with the sound, when i open it in firefox i have not problem but when i open it in chrome the game stop working and doesnt show, i dont know why, i try to fix it and now i can see the objects but i cant drag them, is like it stop . here is the code, I hope you can help me
//set main namespace
goog.provide('bichos');
//get requirements
goog.require('lime');
goog.require('lime.Director');
goog.require('lime.Scene');
goog.require('lime.fill.LinearGradient');
goog.require('lime.Sprite');
goog.require('goog.math');
goog.require('lime.GlossyButton');
goog.require('lime.audio.Audio');
goog.require('lime.Layer');
goog.require('bichos.Bug');
goog.require('lime.Label');
// entrypoint
bichos.start = function(){
var director = new lime.Director(document.body,480,320);
director.makeMobileWebAppCapable();
director.setDisplayFPS(false);
var scene = new lime.Scene().setRenderer(lime.Renderer.DOM);
var initialscene = new lime.Scene().setRenderer(lime.Renderer.DOM);
//InitialScene
var initialLayer = new lime.Layer().setPosition(0,0).setAnchorPoint(0,0);
var initialContainer = new lime.Sprite().setAnchorPoint(0,0).setPosition(0,0).setFill('#EEE0E5').setSize(480,320);
var initialTitle = new lime.Label().setText('Welcome').setFontFamily('Arial').setFontColor('#000000').setFontSize(20).setPosition(240,60);
var startButton = new lime.GlossyButton().setSize(200,60).setPosition(240,150).setText('Start').setColor('#00cD00');
initialscene.appendChild(initialLayer);
initialLayer.appendChild(initialContainer);
initialLayer.appendChild(initialTitle);
initialLayer.appendChild(startButton);
//director
director.replaceScene(initialscene);
//evento inicial
goog.events.listen(startButton,['mousedown','touchstart'],function(e){
e.event.stopPropagation();
director.replaceScene(scene);
});
//Grass
var grass_gradient = new lime.fill.LinearGradient().setDirection(0,0,1,-1).addColorStop(0,'#7CCD7C').addColorStop(1,'#00FF00');
var grass = new lime.Sprite().setSize(480,320).setPosition(0.0).setAnchorPoint(0,0).setFill(grass_gradient);
//caja
var box = new lime.Sprite().setAnchorPoint(0,0).setPosition(390,230).setFill('img/Box01.png').setSize(80,80);
//contar
var num_bugs_catched = 0;
var bug_count = new lime.Label().setText('Bug Count: '+num_bugs_catched).setFontFamily('Arial').setFontColor('#000000').setFontSize(20).setPosition(100,300);
scene.appendChild(grass);
scene.appendChild(box);
//Insectos
var num_bugs =goog.math.randomInt(10)+1;
var x,y,bug;
for(var i = 0; i < num_bugs; i++){
bug = new bichos.Bug();
bug.crawl();
scene.appendChild(bug);
//sound
var bugSound = new lime.audio.Audio('audio/bug.ogg');
//eventos
goog.events.listen(bug,['mousedown','touchstart'],function(e){
var drag = e.startDrag();
drag.addDropTarget(box);
e.event.stopPropagation();
bug = this;
goog.events.listen(drag,lime.events.Drag.Event.DROP, function(e){
//play sound
bugSound.stop();
bugSound.play();
num_bugs_catched++;
bug_count.setText('Bug Count: '+num_bugs_catched);
//Desaparecer bichos
bug.setHidden(true);
delete bug;
//Tambien se puede usar window.location='';
if(num_bugs_catched == num_bugs){
alert('Has Ganado!');
bichos.start();
}
})
})
}
scene.appendChild(bug_count);
// set current scene active
}
//this is required for outside access after code is compiled in ADVANCED_COMPILATIONS mode
goog.exportSymbol('bichos.start', bichos.start);

Trigger UiApp-builder callback within another routine

Serge's solution here seemed like the way to go about this, but I'm a bit afraid that my circumstances may be too different...
I have a button where users can add a new set of rows with controls to a FlexTable, in order to allow them to insert a new member into a record set. After designing and building the app to do this (and despite assurances to the contrary), a requirement was then added for the users to be able to edit the record sets at a later date.
I've finally managed to get the data retrieved and correctly displayed on the Ui - for single member record sets. As a final stage, I am now attempting to extend this to accommodate record sets having more than one member. Obviously this requires determining how many members there are in the record set, and then adding the new rows/control group to the FlexTable, before loading the member into each control group.
So within this routine, (depending on how many members there are) I may need to trigger the same callback, which the user normally does with a button. However, the difference with Serge's fine example, is that his code triggers the checkbox callback at the end of his routine once all the Ui components are in place. My situation needs to do this on the fly - and so far I'm getting 'Unexpected error', which suggests to me that the Ui is not able to update with the added FlexTable controls before my code attempts to assign values to them.
Does anyone have any insight into this problem? Is my only recourse to completely re-build a fixed Ui and dispense with the dynamic rowset model?
Code follows -
1. event for adding controls:
var app = UiApp.getActiveApplication();
var oFlexGrid = app.getElementById('ExpenseDetail');
var oRowCount = app.getElementById('rowCount');
var oScriptDBId = app.getElementById('scriptDBId');
var iRows = parseInt(e.parameter.rowCount);
var sVId = e.parameter.scriptDBId;
var vGridDefs = loadArrayById(sVId); //retrieve upload definition array from ScriptDB
var vControlNames = [];
if (isOdd(iRows)){
var sColour = 'AliceBlue';
} else {
var sColour = 'LavenderBlush';
};
oFlexGrid.insertRow(0);
oFlexGrid.insertRow(0);
oFlexGrid.insertRow(0);
oFlexGrid.insertRow(0);
oFlexGrid.setRowStyleAttributes(0,{'backgroundColor':sColour});
oFlexGrid.setRowStyleAttributes(1,{'backgroundColor':sColour});
oFlexGrid.setRowStyleAttributes(2,{'backgroundColor':sColour});
oFlexGrid.setRowStyleAttributes(3,{'backgroundColor':sColour});
var vExpenseDef = Get_NamedRangeValues_(CONST_SSKEY_APP,'UIAPP_GridExpense');
iRows = iRows+1;
vControlNames = CreateGrid_MixedSet_(iRows, vExpenseDef, oFlexGrid, app);
oRowCount.setText(iRows.toString()).setValue(iRows.toString());
//SOME INCONSEQUENTIAL CODE REMOVED HERE, LET ME KNOW IF YOU NEED IT
vGridDefs = vGridDefs.concat(vControlNames); // unify grid definition arrays
var sAryId = saveArray('expenseFieldDef', vGridDefs);
oScriptDBId.setText(sAryId).setValue(sAryId); //store array and save ScriptDB ID
if (e.parameter.source == 'btnExpenseAdd'){
hideDialog(); //IGNORE CHEKCBOX-DRIVEN CALLS
};
return app;
2. routine that calls the event
var app = UiApp.getActiveApplication();
var oPanelExpense = app.getElementById('mainPanelExpense');
var oPanelIncome = app.getElementById('mainPanelIncome');
var oPanelEdit = app.getElementById('mainPanelEdit');
var chkExpenseAdd= app.getElementById('chkExpenseAdd');
var bExpenseTrigger = e.parameter.chkExpenseAdd;
var sVoucherId = nnGenericFuncLib.cacheLoadObject(CACHE_EDIT_VOUCHERID);
var sVoucher = e.parameter.ListSearch1Vouchers;
var aryVoucherInfo = getVoucherEditDetail(sVoucherId);
//SAVE FOR RECORD MARKING CALLBACK
nnGenericFuncLib.cacheSaveObject(CACHE_EDIT_OLDRECORDS, JSON.stringify(aryVoucherInfo), CACHE_TIMEOUT);
sVoucher = nnGenericFuncLib.textPad(sVoucher, '0', 7);
var bExp = (sVoucher.substring(0,2) == '03')
var oRowCount = app.getElementById('rowCount');
var iRowCount = parseInt(e.parameter.rowCount);
var sControlName = '';
var vControlVal = '';
var iExpIdx = 0;
var sControlType = '';
var oControl = '';
var vSummaryTotal = 0;
for (var iVal in aryVoucherInfo){
sControlName = aryVoucherInfo[iVal][2];
vControlVal = aryVoucherInfo[iVal][3];
switch (sControlName){
case 'ESUM60':
vSummaryTotal = vControlVal;
break;
case 'EXUSRN':
continue; //DON'T OVERWRITE CURRENT USERNAME
break;
};
if (sControlName.indexOf('_')!=-1){ //TEST FOR CONTROL SET MEMBER
var aryControlSet = sControlName.split('_');
if (parseInt(aryControlSet[1])>iRowCount){//*** TRIGGER THE EVENT ***
Logger.log(bExpenseTrigger + ' - ' + !bExpenseTrigger);
chkExpenseAdd.setValue(!bExpenseTrigger, true);
iRowCount = iRowCount +1;
};
};
oControl = app.getElementById(sControlName);
var vCache = cacheSaveReturn(CACHE_UIEX_LISTS,sControlName);
if (typeof vCache == 'undefined'){
oControl.setValue(vControlVal);
oControl.setText(vControlVal);
//controlSetTextBox(oControl,vControlVal);
//controlSetDateBox(oControl,vControlVal);
} else {
if (!(nnGenericFuncLib.arrayIsReal(vCache))){
vCache = JSON.parse(vCache);
};
vCache = vCache.indexOf(vControlVal);
if (vCache != -1){
oControl.setSelectedIndex(vCache);
} else {
controlSetListBox(oControl,vControlVal);
};
};
};
//SOME CODE REMOVED HERE
hideDialog();
return app;
Mogsdad to the rescue!
The answer (see above) for those at the back of the class (with me) is to simply pass the app instance parameter (e) to the event function, calling it directly from the main routine, thus keeping the chronology in step for when it returns the app to complete the routine. No need for the checkbox in this situation.
This only took me all day, but thanks Mogsdad! :)
Snippet below taken from 1/2 way down code sample 2 in the OP:
if (sControlName.indexOf('_')!=-1){ //TEST FOR CONTROL SET MEMBER
var aryControlSet = sControlName.split('_');
if (parseInt(aryControlSet[1])>iRowCount){
eventAddExpense(e); //THAT'S ALL IT TAKES
iRowCount = iRowCount +1;
};
};

How do I set the initial day for a DatePicker

I have two DatePicker objects on a Web UI.
Initially the first should display a day in the past (like january 1st 2010), the second should display the current day (and it does).
I use
var oldDatePicker = myApp.createDatePicker();
var oldDate = new Date(2010, 1, 1);
oldDatePicker.setValue(oldDate);
but that doesn't work
How can I initialize my oldDatePicker?
EDIT 1 --> example
The lines
var zoekBeginDatum = new Date(2012, 8, 15);
pickerBeginDatum.setValue(zoekBeginDatum);
do not provide the desired result
The full (demo) code of the not working example is:
// Global CONSTANTS to be used for initialization
var globalBeginDatum = '2010/04/24';
var globalEindDatum = '';
var globalUseDatums = 'false';
function doGet()
{ // A script with a user interface that is published as a web app
// must contain a doGet(e) function.
// Create 'global' variables, accesible only by this script
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('globalBeginDatum', globalBeginDatum);
userProperties.setProperty('globalEindDatum', globalEindDatum);
userProperties.setProperty('globalUseDatums', globalUseDatums);
// Create the UiInstance object myApp and set the title text
var myApp = UiApp.createApplication()
.setTitle('Test datePicker initialvalue')
.setHeight(50)
.setWidth(100);
var breedteTextBox = 600;
var gridTexts = myApp.createGrid(3, 2);
var labelBeginDatum = myApp.createLabel('Begindatum').setId('labelBeginDatum');
var labelEindDatum = myApp.createLabel('Einddatum').setId('labelEindDatum');
var pickerBeginDatum = myApp.createDatePicker().setId('pickerBeginDatum').setName('pickerBeginDatum');
var zoekBeginDatum = new Date(2012, 8, 15); // Initial date for searching ---> does NOT work
pickerBeginDatum.setValue(zoekBeginDatum);
var pickerEindDatum = myApp.createDatePicker().setId('pickerEindDatum').setName('pickerEindDatum');
var zoekEindDatum = new Date(); // Current date
pickerEindDatum.setValue(zoekEindDatum);
var gridDatum = myApp.createGrid(2, 3);
gridDatum.setWidget(0, 1, labelBeginDatum);
gridDatum.setWidget(0, 2, labelEindDatum);
gridDatum.setWidget(1, 1, pickerBeginDatum);
gridDatum.setWidget(1, 2, pickerEindDatum);
var gridOptions = myApp.createGrid(9, 1);
var onClickChkDatums = myApp.createServerHandler('onClickChkDatums');
var chkDatums = myApp.createCheckBox('Gebruik de begindatum en de einddatum bij het zoeken')
.setId('chkDatums').setName('chkDatums')
.addClickHandler(onClickChkDatums);
gridOptions.setWidget(4, 0, chkDatums);
// Create a vertical panel called verPanel and add it to myApp
var verPanel = myApp.createVerticalPanel().setWidth('60%').setBorderWidth(2).setStyleAttribute('background', 'lightyellow');;
var horPanel = myApp.createHorizontalPanel().setWidth('100%').setStyleAttribute('background', 'lightcyan');
horPanel.add(gridOptions);
horPanel.add(gridDatum);
verPanel.add(horPanel);
labelBeginDatum.setVisible(globalUseDatums == 'true');
labelEindDatum.setVisible(globalUseDatums == 'true');
pickerBeginDatum.setVisible(globalUseDatums == 'true');
pickerEindDatum.setVisible(globalUseDatums == 'true');
// Center verPanel by adding it to another panel occupying whole browser window
var fullPanel = myApp.createVerticalPanel().setStyleAttribute('background', 'beige');
fullPanel.setHeight('100%');
fullPanel.setWidth('100%');
fullPanel.setHorizontalAlignment(UiApp.HorizontalAlignment.CENTER);
fullPanel.setVerticalAlignment(UiApp.VerticalAlignment.MIDDLE);
fullPanel.add(verPanel);
myApp.add(fullPanel); // Now verPanel will be centered
return myApp;
}
// *************** Eventhandlers
function onClickChkDatums(e)
{ // Eventhandler for chkDatums
var app = UiApp.getActiveApplication();
var chkDatums = app.getElementById('chkDatums');
var status = (e.parameter.chkDatums == 'true');
var labelBeginDatum = app.getElementById('labelBeginDatum');
var labelEindDatum = app.getElementById('labelEindDatum');
labelBeginDatum.setVisible(status);
labelEindDatum.setVisible(status);
var pickerBeginDatum = app.getElementById('pickerBeginDatum');
var pickerEindDatum = app.getElementById('pickerEindDatum');
pickerBeginDatum.setVisible(status);
pickerEindDatum.setVisible(status);
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('globalUseDatums', status);
return app;
}
I don't want to make it a habit answering my own questions, but this one might be useful for others as well.
Using BOTH setCurrentMonth() and setValue() shows the right dates in the datePicker
pickerBeginDatum.setCurrentMonth(zoekBeginDatum); // Needed !!
pickerEindDatum.setCurrentMonth(zoekEindDatum); // Needed !!
pickerEindDatum.setValue(zoekEindDatum); // Does ONLY work in combination with setCurrentMonth
pickerBeginDatum.setValue(zoekBeginDatum); // Does ONLY work in combination with setCurrentMonth

How to move a popup window from a client handler?

I have a code that simulates a popup window (thanks to Waqar Ahmad) that is triggered by a client handler.
I would like to get this popup appear near the button that triggered it but with the script I have I see no way to move the window.
The code is below and the app is viewable here, if ever someone has an idea about how I should re-organise or change the script so that the popup window shows up near the button that fired the process ?
var choice = ['-','Choice 1','Choice 2','Choice 3','Choice 4']; // var definition
function doGet(){
var app = UiApp.createApplication().setStyleAttribute("background", "beige");
app.add(createMaskPanel_());//this is used to make popup panel modal
var mainPanel = app.createVerticalPanel().setStyleAttributes({'padding' : '15'});
app.add(mainPanel);
// idx holds the index value of the button that is pressed
var idx = app.createTextBox().setId('idx').setName('idx').setVisible(false);
mainPanel.add(idx);
//Make a panel for popup and add your popup elements
var popup = app.createVerticalPanel().setId('popup').setVisible(false)
.setStyleAttributes(
{'position': 'fixed',
'border' : '1px solid brown',
'padding' : '15',
'background' : 'beige',
'top' : '150PX',
'left' : '300PX',
'width' : '200',
'height':'120',
'zIndex' : '2'});
popup.add(app.createLabel('Select your choice').setId('label'));
var list = app.createListBox().setId('ppValue').setName('ppValue').setWidth('200')
.addItem(choice[0], '0').addItem(choice[1], '1').addItem(choice[2], '2').addItem(choice[3], '3').addItem(choice[4], '4');
popup.add(list);
var valHandler = app.createServerHandler('showVal').addCallbackElement(mainPanel).addCallbackElement(popup);;
popup.add(app.createButton('✖ Close / confirm').addClickHandler(valHandler));
app.add(popup);
var mask = app.getElementById('mask')
var ppHandler = app.createClientHandler().forTargets([popup,mask]).setVisible(true)
var flex = app.createFlexTable()
for(nn=1;nn<11;++nn){
flex.setText(nn,0,'Item nr '+nn)
var text = app.createTextBox().setHeight('26').setWidth('150').setId('val'+nn).setName('val'+nn)
flex.setWidget(nn,1,text);
var handler = app.createClientHandler().forTargets(idx).setText(nn).forTargets(text).setText('suggestion = ?');
flex.setWidget(nn,2,app.createButton('✐').setHeight('26').setId('btn'+nn).addClickHandler(handler).addClickHandler(ppHandler))
}
mainPanel.add(flex);
return app;
}
function createMaskPanel_(){ //Called when UI loads, initially it will be invisble. it needs to be made visible
var app = UiApp.getActiveApplication();
var mask = app.createVerticalPanel().setId('mask').setSize('100%', '100%') //maskPanel to mask the ui
.setStyleAttributes({
'backgroundColor' : '#F0F0F0',
'position' : 'fixed',
'top' : '0',
'left' : '0',
'zIndex' : '1',
'opacity' : '0.4'}).setVisible(false);
mask.add(app.createLabel('POPUP')
.setStyleAttribute('color', '#F0F0F0')
.setStyleAttribute('opacity', '0.6'));
return mask;
}
function showVal(e){
var app = UiApp.getActiveApplication();
var source = e.parameter.idx
var value = app.getElementById('val'+source)
value.setText('choice value = '+choice[e.parameter.ppValue])
var popup = app.getElementById('popup')
var mask = app.getElementById('mask')
popup.setVisible(false)
mask.setVisible(false)
return app
}
EDIT : Since the server handler seems to be the only way I gave it a try, the app is viewable here and the (final ?) code is below for info.
var choice = ['-','Choice 1','Choice 2','Choice 3','Choice 4','Choice 5','Choice 6','Last choice !'];//var definition
function doGet(){
var app = UiApp.createApplication().setStyleAttribute("background", "beige");
app.add(createMaskPanel_());//this is used to make popup panel modal
var top = '100PX'
var left = '265PX'
var mainPanel = app.createVerticalPanel().setStyleAttributes({'padding' : '15'});
app.add(mainPanel);
// item definitions
var idx = app.createTextBox().setId('idx').setName('idx').setVisible(false);
mainPanel.add(idx);
//Make a panel for popup and add your popup elements
var popup = app.createVerticalPanel().setId('popup').setVisible(false)
.setStyleAttributes(
{'position': 'fixed',
'border' : '1px solid brown',
'padding' : '10',
'background' : 'beige',
'top' : top,
'left' : left,
'width' : '200',
'height':'110',
'zIndex' : '2'});
popup.add(app.createLabel('Select your choice').setId('label'));
var list = app.createListBox().setId('ppValue').setName('ppValue').setWidth('160')
for(c in choice){list.addItem(choice[c], c)}
popup.add(list);
var valHandler = app.createServerHandler('showVal').addCallbackElement(mainPanel).addCallbackElement(popup);;
popup.add(app.createButton('✖ Close / confirm').addClickHandler(valHandler));
app.add(popup);
var idxHandler = app.createServerHandler('setidx').addCallbackElement(mainPanel)
var flex = app.createFlexTable()
for(nn=1;nn<11;++nn){
flex.setText(nn,0,'Item nr '+nn)
flex.setWidget(nn,1,app.createTextBox().setPixelSize(180,26).setId('val'+nn).setName('val'+nn));
flex.setWidget(nn,2,app.createButton('✐').setHeight('26').setId('btn'+nn).addClickHandler(idxHandler))
}
mainPanel.add(flex);
return app;
}
function setidx(e){
var app = UiApp.getActiveApplication();
var idx = app.getElementById('idx')
var idxval = Number(e.parameter.source.replace(/[a-z]/g,''))
idx.setValue(idxval);
var top = -30+38*idxval+'PX'
var left = '265PX'
var popup = app.getElementById('popup')
var mask = app.getElementById('mask')
var label = app.getElementById('label').setText('Select your choice (item '+idxval+')')
var value = app.getElementById('val'+idxval)
value.setText('suggestion = ?')
popup.setVisible(true)
mask.setVisible(true)
popup.setStyleAttributes(
{'top' : top,
'left' : left});
return app
}
function createMaskPanel_(){ //Called when UI loads, initially it will be invisble. it needs to be made visible
var app = UiApp.getActiveApplication();
var mask = app.createVerticalPanel().setId('mask').setSize('100%', '100%') //maskPanel to mask the ui
.setStyleAttributes({
'backgroundColor' : '#F0F0F0',
'position' : 'fixed',
'top' : '0',
'left' : '0',
'zIndex' : '1',
'opacity' : '0.6'}).setVisible(false);
mask.add(app.createLabel('POPUP')
.setStyleAttribute('color', '#F0F0F0')
.setStyleAttribute('opacity', '0.6'));
return mask;
}
function showVal(e){
var app = UiApp.getActiveApplication();
var source = e.parameter.idx
var value = app.getElementById('val'+source)
value.setText('choice value = '+e.parameter.ppValue+' ('+choice[Number(e.parameter.ppValue)]+')')
var popup = app.getElementById('popup')
var mask = app.getElementById('mask')
popup.setVisible(false)
mask.setVisible(false)
return app
}
Serge I did something simular using a dialogbox to get this kind of functionality.
In the proper function that shows the dialogbox I decide the position of the dialogbox.
I used it to enlarge a image so I just put the (entire) code I used for the dialogbox.
function showimg(e){
var app = UiApp.getActiveApplication();
//
// Style
//
var _showimg =
{
"position":"fixed",
"width":"200px", // here you can change size
"top":"100px", // and horizontal position maybe you can use your
"left":"100px", // your setidx function .
"opacity":"0.95",
"border":"none",
}
var _container =
{
"width":"90%",
"border":"none",
}
var _img= {
"background-color":"none",
"width":"90%",
"border":"4px solid f2f2f2",
}
var _btn= {
"background-color":"none",
"background":"none",
"width":"80px",
"height":"24px",
"border":"None",
"font-family":"hobo std",
"font-size":"0.9em",
"color":"3f3f3f",
"opacity":"1",
}
//
// aplication
//
var f = DocsList.find("YOURSPREADSHEET");
var id = f[0].getId();
var ss = SpreadsheetApp.openById(id);
var sheet = ss.getSheetByName("YOURSHEET");
var rows= sheet.getLastRow();
var cols = sheet.getLastColumn();
var dialogBox = app.createDialogBox(true, true).setId("dialogBox");
applyCSS(dialogBox, _showimg);
var cont = app.createAbsolutePanel().setId("cont").setVisible(true);
applyCSS(cont, _container);
var source = e.parameter.source;
for (var i = 1; i < rows ; i++) {
for (var j = 1; j <6 ; j++) {
if (source == "imgb"+[j]+[i]) {
if (j == 1) {
var img = app.createImage().setId('img').setUrl(sheet.getRange(i+1,[5]).getValue()).setVisible(true);
dialogBox.setText(sheet.getRange(i+1,[6]).getValue());
}
if (j == 2) {
var img = app.createImage().setId('img').setUrl(sheet.getRange(i+1,[7]).getValue()).setVisible(true);
dialogBox.setText(sheet.getRange(i+1,[8]).getValue());
}
}
app.getElementById( "imgb"+[j]+[i]).setEnabled(false);
//}
}
}
applyCSS(img,_img)
app.createImage().setId('img').setUrl("https://lh6.googleusercontent.com/-PTl6c-pfHoc/TzFvp1dteaI/AAAAAAAACTI/Mmx-7RU4i8g/s640/xxxxxxx.jpg").setVisible(true);
// applyCSS(img,_img)
var closeb = app.createButton("Close").setId("closeb").setTitle("close");
applyCSS(closeb,_btn);
var closeH = app.createServerClickHandler("closediag");
closeb.addClickHandler(closeH);
closeH.addCallbackElement(cont);
cont.add(img);
cont.add(closeb);
dialogBox.add(cont);
app.add(dialogBox);
return app;
}
The applyCss from James
function applyCSS(element, style){
for (var key in style){
element.setStyleAttribute(key, style[key]);
}
}
From what I've discovered so far using what I see in these replies, this methodology is positioning my widgets accordingly, but not the actual form itself. Unless, of course, I'm missing something, which is entirely possible. Thanks for the replies so far.

Should a grid.setVisible(false) have height?

I'm trying to duplicate this example by Serge Insas without the gui.
var vPanel = app.createVerticalPanel();
vPanel.add(createGrid(1,1).setId(grid1);
vPanel.add(createGrid(1,1).setId(grid2);
var handler0 = app.createClientHandler()
.forTargets(grid1).setVisible(true)
.forTargets(grid2).setVisible(false);
var handler1 = app.createClientHandler()
.forTargets(grid1).setVisible(false)
.forTargets(grid2).setVisible(true);
The handlers properly set visibility.
Unlike the example, grid2 does not justify to the top, instead it sits below an invisible grid1. How do i justify to the top?
Note: this is only true in chrome, firefox and explorer justify to top.
thanks,
scott
EDIT: complete code added
function doGet(e) {
//create app
var app = UiApp.createApplication().setTitle('testCrawl');
// create components
var searchPanel = app.createVerticalPanel().setId('searchPanel').setWidth('100%');
var searchMenu = app.createMenuBar().setId('searchMenu').setWidth('100%');
var searchGrid = app.createVerticalPanel().setId('searchGrid').setWidth('100%')
.setHeight('100px').setVisible(false)
.setStyleAttribute("border","2px solid #C0C0C0")
var basicGrid = app.createGrid(1,1).setId('basicGrid').setWidth('100%').setVisible(false)
basicGrid.setWidget(0,0, app.createLabel('Basic'));
var advancedGrid = app.createGrid(1,1).setId('advancedGrid').setWidth('100%').setVisible(false);
advancedGrid.setWidget(0,0, app.createLabel('Advanced'));
var mapGrid = app.createGrid(1,1).setId('mapGrid').setWidth('100%').setVisible(false);
mapGrid.setWidget(0,0, app.createLabel('Map'));
var archiveGrid = app.createGrid(1,1).setId('archiveGrid').setWidth('100%').setVisible(false);
archiveGrid.setWidget(0,0, app.createLabel('Archive'));
var emailCartGrid = app.createGrid(1,1).setId('emailCartGrid').setWidth('100%').setVisible(false);
emailCartGrid.setWidget(0,0, app.createLabel('EmailCart'));
var hideGrid = app.createGrid(1,1).setId('hideGrid').setWidth('100%').setVisible(false);
// add menu and grid
app.add(searchPanel);
searchPanel.add(searchMenu);
searchPanel.add(searchGrid);
searchGrid.add(basicGrid)
.add(advancedGrid)
.add(mapGrid)
.add(archiveGrid)
.add(emailCartGrid)
.add(hideGrid);
// client handler
var handler0 = app.createClientHandler()
.forTargets(searchGrid, basicGrid).setVisible(true)
.forTargets(advancedGrid, mapGrid, archiveGrid, emailCartGrid,hideGrid).setVisible(false);
var hanlder1 = app.createClientHandler()
.forTargets(searchGrid, advancedGrid).setVisible(true)
.forTargets(basicGrid, mapGrid, archiveGrid, emailCartGrid,hideGrid).setVisible(false);
var handler2 = app.createClientHandler()
.forTargets(searchGrid, mapGrid).setVisible(true)
.forTargets(basicGrid, advancedGrid, archiveGrid, emailCartGrid,hideGrid).setVisible(false);
var handler3 = app.createClientHandler()
.forTargets(searchGrid, archiveGrid).setVisible(true)
.forTargets(basicGrid, advancedGrid, mapGrid, emailCartGrid,hideGrid).setVisible(false);
var handler4 = app.createClientHandler()
.forTargets(searchGrid, emailCartGrid).setVisible(true)
.forTargets(basicGrid, advancedGrid, mapGrid, archiveGrid,hideGrid).setVisible(false);
var handler5 = app.createClientHandler()
.forTargets(searchGrid).setVisible(false);
// Create Menu Items
var menuItem0 = app.createMenuItem('Search', handler0);
var menuItem1 = app.createMenuItem('Advanced', hanlder1);
var menuItem2 = app.createMenuItem('Map', handler2);
var menuItem3 = app.createMenuItem('Archive', handler3);
var menuItem4 = app.createMenuItem('Email Cart', handler4);
var menuItem5 = app.createMenuItem('Hide', handler5).setId('hide');
//create menuItem separators
var separator0 = app.createMenuItemSeparator();
var separator1 = app.createMenuItemSeparator();
var separator2 = app.createMenuItemSeparator();
var separator3 = app.createMenuItemSeparator();
var separator4 = app.createMenuItemSeparator();
var separator5 = app.createMenuItemSeparator();
var separator6 = app.createMenuItemSeparator();
//Add the menu item separators and menuItem to the MenuBar
searchMenu.addSeparator(separator0).addItem(menuItem0).addSeparator(separator1)
.addItem(menuItem1).addSeparator(separator2)
.addItem(menuItem2).addSeparator(separator3)
.addItem(menuItem3).addSeparator(separator4)
.addItem(menuItem4).addSeparator(separator5)
.addItem(menuItem5).addSeparator(separator6);
return app;
}
I tried your code - a developpment of it to make it testable - and I don't see the issue you mention...(tested on Chrome) could you post your entire test code please ?
Meanwhile here is the test code I used (deployed here) with two grids in a vertical panel:
function doGet() {
var app = UiApp.createApplication()
var vPanel = app.createVerticalPanel().setStyleAttribute('background', 'beige');
var grid1 = app.createGrid(1,1).setId('grid1');
var grid2 = app.createGrid(1,1).setId('grid2').setVisible(false);
vPanel.add(grid1.setText(0, 0, 'grid1'));
vPanel.add(grid2.setText(0, 0, 'grid2'));
var handler0 = app.createClientHandler()
.forTargets(grid1).setVisible(true)
.forTargets(grid2).setVisible(false);
var handler1 = app.createClientHandler()
.forTargets(grid1).setVisible(false)
.forTargets(grid2).setVisible(true);
grid2.addClickHandler(handler0)
grid1.addClickHandler(handler1)
app.add(vPanel)
return app
}
EDIT : if you set the border and height parameters on the vertical panel instead then you don't have alignment changes anymore.
But the grid uses by default the whole height so with the value you chooses (1) the label comes in the middle...
I suppose it will be populated with more cells in the grid so the issue will disappear by itself. Here is the part of the script that I changed :
function doGet(e) {
//create app
var app = UiApp.createApplication().setTitle('testCrawl');
// create components
var searchPanel = app.createVerticalPanel().setId('searchPanel').setWidth('100%').setHeight('100px')
.setStyleAttribute("border","2px solid #C0C0C0")
var searchMenu = app.createMenuBar().setId('searchMenu').setWidth('100%');
var searchGrid = app.createVerticalPanel().setId('searchGrid').setWidth('100%')
.setVisible(false)