Add crosshair to embedded chart - google-apps-script

I want to update one of my Google Spreadsheet embedded chart with crosshairs. After reading the doc, I've come to the conclusion that this code should work :
function ChartLine()
{
var sheet = SpreadsheetApp.openById("someId").getSheetByName("someSheet");
var chartBuilder = sheet.getCharts()[0].modify().asLineChart();
chartBuilder.setOption("crosshair", { trigger: 'both' });
sheet.updateChart(chartBuilder.build());
}
Unfortunately, this does not add crosshairs. I've been able to modify the chart's title using similar code. So, I'm left wondering why it is not working.
Thank you.

According to this Crosshair Documentation you can use this small snippet below to try and see if it works for you:
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('number');
data.addColumn('number');
for (var i = 0; i < 100; i++)
data.addRow([Math.floor(Math.random()*100),
Math.floor(Math.random()*100)]);
var options = {
legend: 'none',
crosshair: { trigger: 'both' } // Display crosshairs on focus and selection.
};
var chart = new google.visualization.ScatterChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
Play with it until you get the necessary results you need.

Related

How to build dynamic dropdowns in configuration setup?

I'm new to Google Data Studio and looking into building a community connector for our Saas service.
For the configuration section, I need to use the Stepped Configuration process. Basically, I nested set of drop-down lists.
However, I need the data to populate those lists to come from my API. I have the REST service endpoints defined, but I cannot find any documenation/examples of how I'd configure this in the getConfig section of the community connector.
Does anyone have a working example I could use as reference?
In reviewing the documentation, there is a section on stepped configurations, which is what I am looking for. You can find that example here: https://developers.google.com/datastudio/connector/stepped-configuration#dynamic_dropdowns
In this example, they show the following for defining the dropdown values.
Notice for the states, they have hard-coded the values for "Illinois" and "California".
My question is, how can I dynamically call API to retrieve values to populate this list? I have 3 nested dropdowns, each with a separate API call, using the answer from previous dropdown to drive the next.
For example first API might be http://myapi.com/countries which returns list of countries.
When they select country, next API call might be http://myapi.com/states?country=US
etc.
config.newSelectSingle()
.setId("state")
.setName("State")
// Set isDynamic to true so any changes to State will clear the city
// selections.
.setIsDynamic(true)
.addOption(config.newOptionBuilder().setLabel("Illinois").setValue("IL"))
.addOption(config.newOptionBuilder().setLabel("California").setValue("CA"));
if (!isFirstRequest) {
var city = config.newSelectSingle()
.setId("city")
.setName("City");
var cityOptions = optionsForState(configParams.state);
cityOptions.forEach(function(labelAndValue) {
var cityLabel = labelAndValue[0];
var cityValue = labelAndValue[1];
city.addOption(config.newOptionBuilder().setLabel(cityLabel).setValue(cityValue));
});
}
return config.build();
}
Worked through the issues I was having. For others who might have hit similiar issues, here's my working getConfig() method.
function getConfig(request) {
var config = cc.getConfig();
var configParams = request.configParams;
var isFirstRequest = configParams === undefined;
if (configParams ===undefined || configParams.tab ===undefined) {
config.setIsSteppedConfig(true);
}
var url ='https://<yourAPIURL>';
var userProperties = PropertiesService.getUserProperties();
var key = userProperties.getProperty('dscc.key');
var mykey ="Bearer " + key
var options = {
"method" : "GET",
"headers" : {
"AUTHORIZATION" : mykey,
"cache-control": "no-cache"
}
};
var response = UrlFetchApp.fetch(url,options);
var parsedResponse = JSON.parse(response);
var zoneControl = config.newSelectSingle()
.setId("zone")
.setName("Zone")
.setIsDynamic(true);
parsedResponse.map(function(itm) {
zoneControl.addOption(config.newOptionBuilder().setLabel(itm.name).setValue(itm.id))
});
if(configParams !==undefined && configParams.zone !==undefined){
var blockurl ='https://<yourAPIURL>?zoneid='+ configParams.zone;
var blockResponse = UrlFetchApp.fetch(blockurl,options);
var parsedBlockResponse = JSON.parse(blockResponse);
var blockControl = config.newSelectSingle()
.setId("block")
.setName("Block")
.setIsDynamic(true);
parsedBlockResponse.map(function(itm) {
blockControl.addOption(config.newOptionBuilder().setLabel(itm.name).setValue(itm.blockKey))
});
}
if(configParams !==undefined && configParams.block !==undefined){
var taburl =''https://<yourAPIURL>?blockKey='+ configParams.block;
var tabResponse = UrlFetchApp.fetch(taburl,options);
var parsedTabResponse = JSON.parse(tabResponse);
var tabControl = config.newSelectSingle()
.setId("tab")
.setName("Tab")
parsedTabResponse.map(function(itm) {
tabControl.addOption(config.newOptionBuilder().setLabel(itm.name).setValue(itm.internalname))
});
}
return config.build();
}
without testing the code:
function getConfig(request) {
var configParams = request.configParams;
var isFirstRequest = configParams === undefined;
var lst=["A","B","C"]; // your values obtained from REST
var tmp=config.newSelectSingle(); //add element to side
var element=tmp.setId("state").setName("State").setIsDynamic(true); // set name and id
for(var i in lst) // set all the values:
{
element = element.addOption(config.newOptionBuilder().setLabel(lst[i]).setValue(lst[i]))
}
if(isFirstRequest || configParams.state==undefined) // no state selected yet
{
config.setIsSteppedConfig(true); // stop here
}
else
{
// next dropdown element,
// Rest API with element set to: configParams.state
var lst2= ["x","y","z"]
var tmp2=config.newSelectSingle(); //add element to side
var element2=tmp2.setId("element2").setName("Element 2 depends on "+configParams.state).setIsDynamic(true); // set name and id
for(var i in lst2) // set all the values:
{
element2 = element2.addOption(config.newOptionBuilder().setLabel(lst2[i]).setValue(lst2[i]))
}
// code for 3rd
}
}
If the user changes the first dropdown value alle other drop downs have to be reset. This may be a bit tricky.

Google forms API : how to add custom css via code edit?

I need to custom a google form, want to hide google logo and back button on second section
i tried a function like this :
function myFunctioncss() {
function onOpen() {
var myLogoDeGoogle = document.querySelector(".freebirdFormviewerViewFooterImageContainer.freebirdFormviewerViewFooterPageBreak");
myLogoDeGoogle.style.display = "none";
var myBoutonRetour = document.querySelector(".quantumWizButtonPaperbuttonEl.quantumWizButtonPaperbuttonFlat.quantumWizButtonPaperbutton2El2.freebirdFormviewerViewNavigationNoSubmitButton");
myBoutonRetour.style.display = "none";
var myTitreTest = document.querySelector(".freebirdFormviewerViewItemsItemItemTitle.freebirdCustomFont");
myTitreTest.style.color = "red";
var myFond = document.querySelector(".freebirdFormviewerViewFormContent");
myFond.style.background = "green";
}
}
With a trigger on form open.
Not Errors but it does not change anything on the form.
All ideas will be welcome..

Modify CKEditor Advanced tab contents

I'm using CKEditor and would like to modify the content of the Advanced tab
I'd only like the Style input to appear, any ideas on how to do this?
Thanks for any and all help!
I solved it!
Here's some code to help you other guys out:
CKEDITOR.on('dialogDefinition', function (ev) {
// Take the dialog window name and its definition from the event data.
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if (dialogName == 'link') {
var advancedTab = dialogDefinition.getContents('advanced');
var infoTab = dialogDefinition.getContents('info');
var styleField = advancedTab.get('advStyle');
advancedTab.remove();
advancedTab.remove('advTitle');
advancedTab.remove('advContentType');
advancedTab.remove('advCSSClasses');
advancedTab.remove('advCharset');
advancedTab.remove('advRel');
//var urlField = infoTab.get('url');
//urlField['default'] = 'www.ireadhome.com'; //set default value for the url field
}
});
Paste this code into your config.js. Hope it helps you out!

dc.js : how to wait for complete barchart redraw?

Hy everybody,
I'm working with dc.js and I think it's a genious tool ! However I have a issue I can't solve.
I'm using a dc.barchart and I want to launch a function of mine after a click on one bar, but I need to wait the end of the redraw of the barchart.
Order :
- my barchart is displayed
- I click on one bar
-> the barchart is redraw
-> only after the complete redraw, my function is launched
Where can I put my callback ? I can't find the corresponding code.
_chart.onClick = function (d) {
var filter = _chart.keyAccessor()(d);
dc.events.trigger(function () {
_chart.filter(filter);
_chart.redrawGroup();
alert("here is not working");
});
};
(...)
dc.redrawAll = function(group) {
var charts = dc.chartRegistry.list(group);
for (var i = 0; i < charts.length; ++i) {
charts[i].redraw();
}
alert("neither here");
if(dc._renderlet !== null)
dc._renderlet(group);
};
dc.events.trigger = function(closure, delay) {
if (!delay){
closure();
alert("neither neither here");
return;
}
dc.events.current = closure;
setTimeout(function() {
if (closure == dc.events.current)
closure();
}, delay);
};
Any idea ? I'm completely blocked right now :(
Thanks a lot for your help,
vanessa
If _chart is the name of your chart and you want to execute some function named my_function after finishing drawing, use the following piece of code after the declaration of the chart itself:
_chart.on("postRedraw", my_function);
Hope this is what you were looking for.

Google Apps Script, HTML addClickHandler ServerHandler does NOT work

Can anyone confirm that HTML widgets accept ClickHandlers on the Server side ? I can't get my below code to work.
I create a serverHandler (and for good measure I have even added a useless callback element). Subsequently, I add it to a HTML.addClickHander (for good measure I have even added it to .addMouseUpHandler as well). The function is NOT executed.
var mouseclick = app.createServerHandler("handleTrainingClick_").addCallbackElement(lstFilter);
var params = [ "fromOrg", "trainingTitle", "dueDate", "medical", "status" ];
var resultSet = blSelectActiveTrainings_();
while (resultSet.hasNext()) {
var training = resultSet.next();
var html = TRAINING_ROW;
for (var pI in params) {
html = html.replace("$"+params[pI], training[params[pI]]);
}
pnlList.add(app.createHTML(html).setId(training.id).addClickHandler(mouseclick).addMouseUpHandler(mouseclick)
.addMouseMoveHandler(mousemove).addMouseOutHandler(mouseout).addMouseOverHandler(mouseover));
}
function handleTrainingClick_(e) {
Logger.log(e.source);
var app = UiApp.getActiveApplication();
return app;
}
HTML widgets server side handlers work just fine. It was an incorrect reference in my code. Thanks all.