Sheet.updateChart resets series color - google-apps-script

I have the following chart:
And a script attached to the button:
function updateChart() {
const sheet = SpreadsheetApp.getActiveSheet()
const chart = sheet.getCharts()[0];
SpreadsheetApp.getUi().alert(String(chart.getOptions().get('title')));
SpreadsheetApp.getUi().alert(String(chart.getOptions().get('series.0.color')));
sheet.updateChart(chart.modify().build());
}
The first time I'm pressing this button it does nothing (as expected). The second time it resets line color to blue.
series.0.color is always null, although title is there, so I'm not even sure where to get that color to preserve it in between .modify() and .build() calls.
How do I prevent updateChart from resetting the color?
I've tried to inspect options in the published chart as suggested in comments (thanks #TheMaster), unfortunately it still doesn't help with the color issue.
The options are:
{
"hAxis": {
"title": "x"
},
"vAxes": {
"0": {
"title": "10x"
}
},
"series": {
"0": {
"color": "#008000"
}
},
"useFirstColumnAsDomain": true,
"width": 600,
"title": "10x vs \"x\"",
"height": 371
}
And I'm using the following code to get them:
function printOption(opts, name) {
console.log(`${name}: ${opts.get(name)}`)
}
function inspectChart(chart) {
const options = chart.getOptions();
printOption(options, 'title');
printOption(options, 'hAxis.title');
printOption(options, 'vAxes.0.title');
printOption(options, 'series.0.color');
}
Output is:
title: 10x vs "x"
hAxis.title: x
vAxes.0.title: 10x
series.0.color: null
As you can see all properties (including nested within array) are there except color
Another interesting point is that once you try to update the color:
sheet.updateChart(sheet.getCharts()[0].modify().setOption('series', {0: {color: 'green'}}).build());
It applies, but from now you're unable to read that property at all:
sheet.getCharts()[0].getOptions().get('series.0.color')
The line above fails with Unexpected error while getting the method or property get on object Charts.ChartOptions.
Also it looks like no matter what color I choose it is always #008000 in the published chart, which makes me think I should look for the color somewhere else, but I don't know where

Related

In Google Slides, trying to set AutofitType to 'Shrink text on overflow' ('TEXT_AUTOFIT')

I have tried the following code but discovered that although the AutofitTypes are enumerated, only "NONE" works.
requests = [(
{ updateShapeProperties: {
objectId: shape.getObjectId(),
shapeProperties: {
autofit: {
autofitType: "NONE" // vs. "TEXT_AUTOFIT"
}
},
fields: "autofit.autofitType"
}
}
)]
response = Slides.Presentations.batchUpdate({requests: requests}, deck.getId());
So I changed my logic and created the TEXT_BOX in Slides with the desired AutofitType. To my chagrin, when I issued my first shape.getText().replaceAllText('text placeholder','new text'), the Autofit option has been reset to NONE.
Any thoughts on how I can script the setting of AutofitType?

Vega-Lite: "1 in X" custom legend labels

I'm working on a choropleth map that shows the share of the population that has confirmed positive case of Covid-19 in each political jurisdiction. Similar to this example in the per capita Mapbox graphic on this page of the The New York Times.
I figured out just about every detail expect how to customize the legend. Currently, the labels display the shareOfPop as a number. Though, I want to prefix each label with "1 in ${shareOfPop}", and to add a suffix to the final label "1 in ${shareOfPop} or more".
enter image description here.
I've created this map in an Observable Notebook.
Things I've tried so far...
Making us of the custom legend encodings
To specify label text:
vl.color()
.fieldQ('shareOfPop')
.scale(
{
scheme: "yelloworangered",
domain: [250, 10],
clamp: true,
}
)
.legend({
title: "Share of Pop.",
encode: {
labels: {text: "1 in ${datum.value}"}
}
})
Register a custom formatter
Which I doubt I've accomplished correctly.
Here's what my configuration looks like (which is based on the config in the Introduction to Vega-Lite notebook).
vl = {
const [vega, vegalite, api, tooltip] = await Promise.all([
'vega#5.13.0',
'vega-lite#4.14.1',
'vega-lite-api#0.11.0',
'vega-tooltip#0.22.1'
].map(module => require(module)));
const options = {
config: {
// allow custom format types
customFormatTypes: true,
config: {
view: {continuousWidth: 400, continuousHeight: 300},
mark: {tooltip: null}
}
},
init: view => {
// initialize tooltip handler
view.tooltip(new tooltip.Handler().call);
// enable horizontal scrolling for large plots
if (view.container()) view.container().style['overflow-x'] = 'auto';
// register a custom expression function...am I doing this right???
vega.expressionFunction('1inX', function(datum) {
return `1 in ${datum}`
})
},
view: {
// view constructor options
loader: vega.loader({baseURL: 'https://cdn.jsdelivr.net/npm/vega-datasets#1/'}),
renderer: 'canvas'
}
};
return api.register(vega, vegalite, options);
}
Then I specify this custom formatType when defining the mark:
vl.color()
.fieldQ('shareOfPop')
.scale(
{
scheme: "yelloworangered",
domain: [250, 10],
clamp: true,
}
)
.legend({
title: "Share of Pop.",
formatType: "1inX",
})
)
Neither of these approaches produced any noticeable change.
Gonna answer my own question here.
Turns out Legend has a general labelExpr property that allows you to specify a Vega expression for customizing the label.
In my case, I wanted to always prepend the string "1 in ", and also append "+" when over may domain limit. Here's how I did it using the join() and if() functions.
...
vl.color()
.legend(
{
labelExpr: "join(['1 in ', datum.value, if(datum.value >= 250, '+', '')], '')"
}
)
This property isn't documented for Legend, though it is for for Axis).

Libgdx Missing LabelStyle font for ImageTextButton

I've been creating Button(s) just using the Button class, but figured I'd try the ImageTextButton. However, even with just the Button class, I'm not quite following the docs on how a .pack (atlas) file with a .json file should be working together.
Using the Button class, I can 'name' my button whatever I like in code, and have it named in the json accordingly (see examples below), but for 'Image's, I have to 'name' everything the same, from the construction in code, through the pack and json files. Example of what works:
code:
// note the 'Constants' just point to the json and atlas files, respectively.
skinShops = new Skin(Gdx.files.internal(Constants.SKIN_SHOPS), new
TextureAtlas(Constants.TEXTURE_ATLAS_SHOPS));
// for this next line, note the json definition for Button$ButtonStyle:
Button buttonBuy = new Button(skinShops, "Button-Buy");
// for Images, it seems I cannot have a 'unique' name first, then the drawable name, which I thought refers to the json
Image imgItemsBackground = new Image(skinShops, "shop-items-background");
If you look at the 'scene2d.ui.Image:' definitions, everything is named the same. While its working this way, I'm not clear why.
This could be 2 questions I guess, the previous concern about nomenclature of naming between all these elements, but my current issue I cannot get past is trying to construct an ImageTextButton. In code, I'm building them dynamically depending on where the player is: different shops have different items to sell, and those are read into the items[] array.
ImageTextButton buttonPurchase = new ImageTextButton(items[j], skinShops, "shop_item-button-background");
Stack trace:
Exception in thread "LWJGL Application" java.lang.IllegalArgumentException: Missing LabelStyle font.
at com.badlogic.gdx.scenes.scene2d.ui.Label.setStyle(Label.java:78)
at com.badlogic.gdx.scenes.scene2d.ui.Label.<init>(Label.java:72)
at com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton.<init>(ImageTextButton.java:57)
at com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton.<init>(ImageTextButton.java:44)
at com.uv.screen.InteriorScreen.buildItemButtons(InteriorScreen.java:134)
Where should I be creating / setting the font for these buttons?
json file:
{
com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {
Button-Exit: { down: Button_Exit_112x60, up: Button_Exit_112x60 },
Button-Buy: { down: Button_Buy_112x60, up: Button_Buy_112x60 },
Button-Sell: { down: Button_Sell_112x60, up: Button_Sell_112x60 }
},
com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton$ImageTextButtonStyle: {
shop_item-button-background: { down: shop_item-button-background, up: shop_item-button-background }
},
com..badlogic.gdx.scenes.scene2d.ui.Image: {
background: { drawable: background },
shop-items-background: { drawable: shop-items-background },
shop-menu-background: { drawable: shop-menu-background },
shop-talk-text-background: { drawable: shop-talk-text-background },
weapon-shop-portrait_world1: { drawable: weapon-shop-portrait_world1 },
armor-shop-portrait_world1: { drawable: armor-shop-portrait_world1 },
item-shop-portrait_world1: { drawable: item-shop-portrait_world1 },
inn-shop-portrait_world1: { drawable: inn-shop-portrait_world1 }
}
atlas file:
shops-pack.png
format: RGBA8888
filter: Nearest,Nearest
repeat: none
background
rotate: false
xy: 0, 504
size: 800, 480
orig: 800, 480
offset: 0, 0
index: -1
shop-items-background
rotate: false
xy: 0, 248
size: 608, 256
orig: 608, 256
offset: 0, 0
index: -1
shop_item-button-background
rotate: false
xy: 0, 60
size: 256, 60
orig: 256, 60
offset: 0, 0
index: -1
...
There's no reason your Images in your json have to have the same names as the drawables in them. You don't even need to put Images in your skin. Look at the documentation of ImageTextButtonStyle...its parameters are Drawables, not Images. And so that's why it seems like you need to use the exact texture region names.
Skin automatically creates a TextureRegionDrawable or NinePatchDrawable out of a texture region with that name if you haven't created one in the Skin. But you can create all kinds of Drawables (such as TiledDrawable or TintedDrawable, or a TextureRegionDrawable with custom padding) and specify those as your button's image if you want to.
Also note in the documentation that ImageTextButtonStyle inherits a member named font from TextButtonStyle, which is not marked as optional in the documentation. So you're getting an exception for using an ImageTextButtonStyle that did not specify a font.
There are a couple ways you can put a font into your skin. If you have generated a bitmap font with a tool such as BMFont or Heiro, you can pack it into your texture atlas. Simply put the .fnt file and its image into the same directory with your other images that you are packing. And put another copy of the .fnt file into your assets directory, next to your atlas file. Then specify the font in your skin json by using its file name:
com.badlogic.gdx.graphics.g2d.BitmapFont: { myfont: { file: myfont.fnt } },
If you are using FreeTypeFontGenerator, this is more complicated. Let me know if that's what you're doing.

Push JSON File to Firebase

I've got a large JSON file that I'd like to push to my Firebase. It's currently in a specific format that I'd like to slightly change when pushed.
My current JSON file looks a bit like this:
"item": [
{
"title": "Hernia Repair",
"dc:creator": "realph",
"content:encoded": "A hernia occurs when an internal part of the body pushes through a weakness in the muscle or surrounding tissue wall. Your muscles are usually strong and tight enough to keep your intestines and organs in place, but a hernia can develop if there are any weak spots.",
},
...
]
While my Firebase items look like this:
"services" : {
"-JfTLQsxlZr6W2JWwMMd" : {
"description" : "Hernia repair refers to a surgical operation for the correction of a hernia (a bulging of internal organs or tissues through the wall that contains itself.",
"title" : "Hernia Repair",
},
...
}
I'm trying to push each one of these items to the services object that's already set up in my Firebase. But I'd like to push each item to a new unique id (i.e. -JfTLQsxlZr6W2JWwMMd), just like it is in my Firebase object (above). I also want push the title to title and push content:encoded to description.
Is this even possible? Doing this would potentially save me a lot of time going forward.
Any help from someone that is familiar with this sort of thing would be appreciated. Thanks in advance!
Update
This is what I was thinking to do, but I don't believe it's wired up correctly. I'm getting back a unique key with the console.log, but no item is being added to the services object:
$scope.convertItems = function() {
for(var i=0; i < $scope.items.length; i++) {
var newService = {
title: title,
description: 'content:encoded'
};
}
var promise = ServiceService.add(newService);
promise.then(function(data) {
console.log(data.name());
});
};

Invalid or unexpected MouseEvent object

I am trying to send Mouse Event to my Offscreen Tab and I received following error:
Error during experimental.offscreenTabs.sendMouseEvent:
Invalid or unexpected MouseEvent object
My Code:
chrome.experimental.offscreenTabs.sendMouseEvent(tab.id, {
"type": "click",
"altKey": false,
"ctrlKey": false,
"shiftKey": false
}, {
"x": 10,
"y": 10
}, function () {
console.log("Mouse Event Sent");
});
Any Suggestions?
You need to add a button key as well if you use a mouse event.
{
"type": "click",
"button": 1, // 0 = left, 1 = middle, 2 = right
"altKey": false,
"ctrlKey": false,
"shiftKey": false
}
Since the API is experimental, and the documentation is not quite complete, I looked in the source code:
chromium/src/chrome/browser/extensions/api/offscreen_tabs/offscreen_tabs_api.cc (implementation of the offscreenTabs API)
chromium/src/third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h (for definitions of the "button" constants).
PS. I managed to get a Developer tools instance when I used button: 2. Quite useful for debugging interaction with an offscreen tab!