Google Apps Script: how to make suggest box library to work? - autocomplete

I'm trying to add an autocomplete feature in my Google Spreadsheet using this Google Apps Script suggest box library from Romain Vialard and James Ferreira's book:
function doGet() {
// Get a list of all my Contacts
var contacts = ContactsApp.getContacts();
var list = [];
for(var i = 0; i < contacts.length; i++){
var emails = contacts[i].getEmails();
if(emails[0] != undefined){
list.push(emails[0].getAddress());
}
}
var app = UiApp.createApplication();
var suggestBox = SuggestBoxCreator.createSuggestBox(app, 'contactPicker', 200, list);
app.add(suggestBox);
return app;
}
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "my_sheet_name" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() == 1) {
doGet();
}
}
}
But when I start editing the column 1 of "my_sheet_name" nothing hapens (if I replace doGet() for other function, this other function runs Ok). I've already installed the Suggest Box library. So, why the doGet() function doesn't work?

small confusion here...
The doGet() ..... return app; structure that you are using here is for standalone webapps that need to be deployed and run with their own url in a browser window.
What you are trying to do is to show a Ui in a popup window in a spreadsheet, the mechanism is different : see example below and have a look at the documentation here.
function doGet_or_any_other_name_preferably_something_more_specific() {
var contacts = ContactsApp.getContacts();
var list = [];
for(var i = 0; i < contacts.length; i++){
var emails = contacts[i].getEmails();
if(emails[0] != undefined){
list.push(emails[0].getAddress());
}
}
var app = UiApp.createApplication();
var suggestBox = SuggestBoxCreator.createSuggestBox(app, 'contactPicker', 200, list);
app.add(suggestBox);
SpreadsheetApp.getActive().show(app);
}
Note that this code will allow the Ui to show up but that's about all.... no data will be written in the spreadsheet since you didn't implement any handler to handle the data return. For details about that step read the aforementioned documentation and the examples shown on Romain's website.
EDIT following your comment : tested with this exact code (copied/pasted) and working, see capture below.

Related

How to add and edit a short answer in multiple google forms

So I have multiple google forms (around 20 forms), that I need to do 2 things to them:
1- These 20 forms are placed in a folder in my google drive. I need to add more like an "Access code" where users will have to insert in order to continue the solving the quiz.
The way I did that was to add a "short answer" question to "section 1" of the quiz asking "Enter your Access Code", add "response validation", "Regular expression" and "Pattern". Also making this a "required question". This should look something like the below picture
Example of google form
So is it possible to have a scriptto add this question to all 20 forms
2- The "access code" in these google forms will have to be updated frequently, so I don' want to be updating the "Pattern" manually for each form, is t possible to have a google script to edit the value of the pattern for each form
Thanks in advance guys :)
I managed to solve this issue that I was having, through looking for different codes and here are the codes that I used.
N.B. The codes might not be very clean as I was copying them from other parts/projects, but they have worked for me
1- Update the 20 forms with adding the access code question, I figured it was not possible to add a question at a certain position in the google form, however I can add a question at the end of the form and then move this item to the position I want:
function AddAccesscodeQ() {
var filess = DriveApp.getFolderById("Drive id>").getFiles();
while (filess.hasNext()) {
var file = filess.next();
var form = FormApp.openById(file.getId());
var sectionIndex= 0; // Please set the index you want to insert.
//I added a "sample item" to be moved and edited later
var newItemQ = form.addTextItem().setTitle("New sample item").getIndex(); // New sample item
// I added a Pagebreak that also should be moved after the questions "Enter Your Access Code"
var newItemPB = form.addPageBreakItem().getIndex();
var items = form.getItems(FormApp.ItemType.PAGE_BREAK);
var sections = [0];
for (var i = 0; i < items.length; i++) {
// I pushed the items in the google form twice downwards, to be able to move the "sample item" and "Page break" to the top of the form
sections.push(items[i].getIndex());
sections.push(items[i].getIndex());
}
var insertIndex = sections[sectionIndex + 1] || null;
if (insertIndex) {
// Here I moved the 2 new items to the desired positions
form.moveItem(newItemQ, 0);
form.moveItem(newItemPB, 1);
}
// Here I am going to edit the "Sample Question" to be as desired
var itemss = form.getItems();
var itemID = itemss[0].getId();
var itemse = form.getItemById(itemID).asTextItem()
.setTitle('Enter Your Access Code').setRequired(true);
//Create validation rule
var validation = FormApp.createTextValidation()
.setHelpText('Invalid Code')
.requireTextMatchesPattern("<Access Code>")
.build();
itemse.setValidation(validation);
}
}
2- The second problem was that I later might need to change this access code to a new one for the 20 forms
function UpdateAccessCode() {
var filesPhCH = DriveApp.getFolderById("<Drive ID>").getFiles();
while (filesPhCH.hasNext()) {
var file = filesPhCH.next();
var form = FormApp.openById(file.getId());
var items = form.getItems();
//Loop through the items and list them
for (var i = 0;i<items.length;i++){
var item = items[i];
var itemID = item.getId();
var itemtitle = item.getTitle();
var itemindex = item.getIndex();
// I found no need to continue the for loop since the items that need modification are at the top of the form
if (itemindex == 0){
break;
}
}
//Select the question you want to update
var itemse = form.getItemById(itemID).asTextItem()
.setTitle('Enter Your Access Code');
//Create validation rule
var validation = FormApp.createTextValidation()
//.setTitle('Enter Your Access Code');
.setHelpText('Invalid Code')
.requireTextMatchesPattern("<Enter the new Access Code>")
.build();
itemse.setValidation(validation);
}
}
I hope this might help someone as it has saved a lot of time for me ;)

How to create reusable components using page objects

I have a text box spinner control and some validations against it.
This text box spinner control is used in n number of pages where I need to check for same validations.
So I would like to create a page spinnertextbox.js and call this in other pages.
So my confusion is how to I access this spinnertextbox.js from test spec files.
Test spec - > Pages -> spinnertextbox.js
Do I call the spinnertextbox.js directly from Testspec (which I feel is wrong).
I tried the following to follow the flow of Test spec to Pages and from Pages to spinnertextbox.js
Below is what I have implemented.
Spinnertextbox.js`
var txtbox = function () {
this.Up = function (upArrow) {
upArrow.click();
};
this.Down = function (downArrow) {
downArrow.click();
};
};
module.exports = txtbox;
Homepage.js ā€“ which is going to call the spinnertextbox.js
var spinner = require('../pages/ spinnertextbox.js');
var home = function () {
var upArrow = element(by.xpath('ā€™));
var downArrow = element(by.xpath(''));
this.spinfn = function (fun) {
var spin = new spinner();
switch (fun) {
case 'uparrowclick':
spin.Up(upArrowt);
break;
case 'downarrowclick':
spin.Down(downArrow);
break;
}
};
};
module.exports = home;
And finally my test spec
Home.spec.js
var home = require('../pages/HomePage.js');
describe('reusability functionality : ', function () {
it('reusability: ', function () {
var hm = new home ();
//call to some other function in home page then
hm.spinfn('txtclick');
d hm isplaySrc.spinfn('uparrowclick');
hm.spinfn('downarrowclick');
});
});
Is this approach acceptable or Iā€™m totally in the wrong direction.

Calling a plug-in via an add-on

Scenario:
I have developed an firefox add-on. I want my add-on to call another plug-in present in firefox.
Problem:
I am not able to figure it out how the plug-in can be called. In chrome, extensions can call plug-in by message passing. Can message passing can be used for firefox add-on.If it can be done can anyone provide guidance.
Following is the code:
Here is main.js file:
var {data} = require("sdk/self");
var pageMod = require("sdk/page-mod");
pageMod.PageMod({
include: "*",
attachTo: ["top"],
contentScriptFile: [data.url("jquery-2.1.0.js"),data.url("cwic.js"), data.url("my- script.js")]
});
and Here is the my_script.js file:
//MAIN REGEX
var regex = /\+?\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}/g;
var text = $("body:first").html();
var textNodes = $("body:first").find('*').contents().filter(function(){
if(this.nodeType == 3 && regex.test(this.nodeValue) && this.parentElement.tagName !== "A"){
var anchor = document.createElement('a');
//alert(this.nodeValue.match(regex)[0]);
//anchor.setAttribute('href', this.nodeValue);
anchor.setAttribute('href', this.nodeValue.match(regex)[0]);
anchor.appendChild(document.createTextNode(this.nodeValue.match(regex)[0]));
//alert(this.nodeValue.match(regex));
if(this.nextSibling)
this.parentElement.insertBefore(anchor, this.nextSibling);
else
this.parentElement.appendChild(anchor);
this.nodeValue = this.nodeValue.replace(regex, '');
}
return this.nodeType === 3;
});
$('a').click(function() {
// When user clicks on the number it should call another plug-in to initiate communication
});
grab the window and use chromeWindow.gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject.$
the wrappedJSObject gives you access to all the js in that window

Google Apps upload from spreadsheet: cannot reference active cell

I have this google app script which should
show file upload dialog
store file in google drive
write the url of the file into the current cell
All goes well except step 3, where the cell updated is always cell A1 in the first sheet. But the cursor is on sheet #3 on another cell.
function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var menuEntries = [];
menuEntries.push({name: "File...", functionName: "doGet"});
ss.addMenu("Attach ...", menuEntries);
}
function doGet(e) {
var app = UiApp.createApplication().setTitle("Attach file to sheet");
var form = app.createFormPanel().setId('frm').setEncoding('multipart/form-data');
var formContent = app.createVerticalPanel();
form.add(formContent);
formContent.add(app.createFileUpload().setName('thefile'));
formContent.add(app.createSubmitButton('Submit'));
app.add(form);
SpreadsheetApp.getActiveSpreadsheet().show(app);
return app;
}
function doPost(e) {
var fileBlob = e.parameter.thefile;
var doc = DocsList.getFolderById('0B0uw1JCogWHuc29FWFJMWmc3Z1k').createFile(fileBlob);
var app = UiApp.getActiveApplication();
var label = app.createLabel('file uploaded successfully');
var value = '=hyperlink("' + doc.getUrl() + '","' + doc.getName() + '")'
app.add(label);
app.close();
SpreadsheetApp.getActiveSheet().getActiveCell().setValue(value);
return app;
}
I tried SpreadsheetApp.getActiveSheet().getActiveCell().setValue(value); outside of the doPost() function and this works when called in a normal context. What am I missing here?
judging from this answer, it is not possible to get the current spreadsheet/cell from the doPost function, the way I got it working is to get it in the doGet function via hidden fields and pass it via the form. Full blown working example here.

Update OpenLayers popup

I am trying to update some popups in my map but I am not able to do that.
Firstly I create some markers, and with the next code, I create a popup associated to them. One popup for each marker:
popFeature = new OpenLayers.Feature(markers, location);
popFeature.closeBox = true;
popFeature.popupClass = OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
'autoSize': true
});
popFeature.data.popupContentHTML = "hello";
popFeature.data.overflow = (false) ? "auto" : "hidden";
var markerClick = function (evt) {
if (this.popup == null) {
this.popup = this.createPopup(this.closeBox);
map.addPopup(this.popup);
this.popup.show();
} else {
this.popup.toggle();
}
currentPopup = this.popup;
OpenLayers.Event.stop(evt);
};
mark.events.register("mousedown", popFeature, markerClick);
After that, I add the new marker to my marker layer.
Everything is fine until here, but, I want to update the popupcontentHTML some time later and I don't know how I can access to that value.
I read OL API but I don't understand how to get it. I am lost about features, events, extensions...
I want to know if I can access to that property and write other word.
I answer myself, maybe it helps other people in future:
for(i = 0; i < map.popups.length; i++){
if(map.popups[i].lonlat.lon == marker.lonlat.lon){
map.popups[i].setContentHTML("new content");
}
}
Content will be refreshed at the moment.