Linking shapes to slides using text search in Google Slides script - google-slides-api

Trying to link shapes to slides the same way it's done with images.
.
.
Reason for this request is linking images seems much harder in terms of locating the exact one to be linked.
Have realized it might be best to link shapes through match/search text then insert the images after.
Codes attempted though please ignore if completely irrelevent.
function myFunction(){
var searchText = "IMAGE1";
var presentation = SlidesApp.getActivePresentation();
var slide = presentation.getSlides()[4];
// 2. Replace the shape which has the text of "searchText" with the image of "imageUrl".
slide.getShapes().forEach(s => {
if (s.getText().asString().toLocaleUpperCase().includes(searchText.toLocaleUpperCase())) {
s.setLinkSlide('INSERT_SLIDE_LINK');
}
}
)
}
Slides Example
Thank you

I believe your goal is as follows.
You want to link the shape to a slide by searching the text in the shape on Google Slides.
You want to achieve this using Google Apps Script.
setLinkSlide can use Slides Object. I thought that this might be able to be used.
Sample script:
function myFunction() {
const obj = { text1: 3, text2: 3, text3: 4, text4: 5, text5: 4, text6: 3 }; // This is from your showing sample image.
const slides = SlidesApp.getActivePresentation().getSlides();
slides.forEach(s => {
s.getShapes().forEach(shape => {
const t = obj[shape.getText().asString().toLowerCase().trim()];
if (t) {
shape.setLinkSlide(slides[t - 1]);
}
});
});
}
Note:
This sample script is for your provided sample Google Slides. When you change this, please modify obj. Please be careful about this.
Reference:
setLinkSlide(slide)

SUGGESTION
If I've understood your post correctly, these are your goals:
Check the text on each of the shapes in your slides
See if the current text shape matches the current searchText value
If true, link a dedicated slide to the current shape.
Sample Tweaked Script
function sample() {
var presentation = SlidesApp.getActivePresentation();
var slide = presentation.getSlides();
//Define the 'searchText' value & it's dedicated slide to be linked
var find = {
search: [["Text1", slide[1]],
["Text2", slide[2]],
["Text3", slide[3]]]
};
find.search.forEach(d => {
let searchText = d[0];
let linkSlide = d[1];
slide[0].getShapes().forEach(s => {
s.getText().asString().trim().toLowerCase() === searchText.toLowerCase() ? s.setLinkSlide(linkSlide) : null;
});
})
}

Related

How to build an adaptive layout in Jetpack Compose

So I am trying to Follow this documentation to achieve something similar to this documentation, this is where the CardTitle moves and image; but the Title and Description on this documentation do not seem to be available on Cards now? I can not access that when I try to create a Card. Biggest issue Card does not have Description anymore, maybe this needs to be updated or how can I achieve this. I am trying to something similar to the image shown.
Code from the Documentation.
#Composable
fun Card(
imageUrl: String,
title: String,
description: String
) {
var showMore by remember { mutableStateOf(false) }
BoxWithConstraints {
if (maxWidth < 400.dp) {
Column {
Image(imageUrl)
Title(title)
}
} else {
Row {
Column {
Title(title)
Description(
description = description,
showMore = showMore,
onShowMoreToggled = { newValue ->
showMore = newValue
}
)
}
Image(imageUrl)
}
}
}
}
Biggest issue Card does not have Description anymore, maybe this needs
to be updated or how can I achieve this. I am trying to something
similar to the image shown.
This is not an issue because the sample above is for demonstrating flexible layout based on screen size using BoxWithConstraints. When you build your layouts you don't have follow this exact pattern.
You can do it in many ways including
Column {
Image(imageUrl)
Title(title)
// You can add a description that is one line with ellipsis overflow for instance. Or it's font size can be smaller than title
}
In your example demonstrator preferred to not show when screen size is less than 400.dp.
BoxWithConstraints is suitable for building a selective layouts based on max or min width/height from its Constraints

Select only specific polygon of the feature, OpenLayers

A Feature is made of several parts, how do i select just one of them on mouse click in openLayers?
By default the whole feature gets selected.
I think you would need to create a new source containing features with single polygon geometry. Give them a parent property if you need to access the original feature. For example
mainSource.on('addfeature', function(event) {
var geometry = event.feature.getGeometry();
if (geometry.getType() == 'MultiPolygon') {
geometry.getPolygons().forEach(function(polygon) {
splitSource.addFeature(new Feature({
geometry: polygon,
parent: event.feature
});
} else {
splitSource.addFeature(event.feature);
}
});

How to find style text that was previosly set on a feature - OL3

Using OL3, I set the text on a style dynamically:
var myLayer = new ol.layer.Vector({
source: mySource,
style: function (feature, resolution) {
var style = new ol.style.Style({
text: new ol.style.Text({
text: setText(feature)
})
});
return [style];
}
});
I am trying to later read what is stored in text:
text: setText(feature)
I am trying to retrieve the text on a click event but not sure how to access that property under the feature style (feature is the variable from the event containing the clicked feature):
// Get current display text
var currentFeatureStyle = feature.getStyle();
But when I do that, I get a null currentFeatureStyle.
Also tried looping through the feature:
for (var fid in feature)
{
//what to look for to extract the feature text?
But not sure what to look for to extract the feature text. Any help getting back the feature text from a feature would be appreciated.
Thanks
If someone can come up with a more correct answer please by all means post below. I have created a "workaround" since I could not retrieve the text from the feature. The workaround involves the following:
Inside the method the text is originally set, add the following:
function setText(feature)
{
// First do your normal stuff (set the text of the feature)
var output = "myFeatureText";
// Here is the workaround step 1:
// Create a property and set it to the text
feature.displayText = output;
// Return back value for the setting of the style text
return output;
}
Now the text is also saved in a property called displayText. Note: displayText is a made up property, it does not exist in openlayers.
Step 2 is to retrieve the property you created in step 1 to get the display text. In this example we are retrieving the feature from singleclick but it can be from anywhere else you are using the feature:
map.on('singleclick', function (evt) {
var feature = map.forEachFeatureAtPixel(evt.pixel,
function (feature, layer) {
return feature;
});
// Here is the workaround step 2:
// Get "display text" custom field for this feature
var displayText = feature.displayText;
.
And thats all there is to it. There must be a "correct" way to retrieve the text from the style of the feature but I am not aware of it. If someone know how to by all means post your answer.

Highcharts - programmatically draw a line or graphic between two related points

I often have charts that require a design element like a curly brace to call attention to call attention to a range or comparison in a graph, such as the y-difference in two points at the end of a graph.
My first take is that this would be a job for Highcharts Renderer API. Load the graph, and run a callback that adds an image (or line, shape, whatever) via chart.renderer.image(...) or similar.
That's the approach I have started down, but I'm just missing how to get the coordinates for chart data points within the callback. Here's a working codepen of the code below. What doesn't work is that there's no logic to give it proper placement on the canvas (suppose I want the bracket to go from the final top point to the final bottom point)
$('#container').highcharts({
data: { table: document.getElementById('datatable') },
chart: { type: 'line' },
title: { text: 'Data extracted from a HTML table in the page'
}
}, function(chart){
var img = 'http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Curly_bracket_right.svg/30px-Curly_bracket_right.svg.png';
// How can I populate these values?
var x = 0; // should programmatically get x-position of last point
var y = 0; // should programmatically get y-position of last point
var h = 100; // should programmatically get distance between y-position of top and bottom points
var w = 50;
chart.renderer.image( img, x, y, w, h ).add();
});
Is there a straightforward way to populate those values? Or is there a better way to do this entirely?
to get the position you want you can use few methods provided by highcharts in their API.
methods like toPixels(), toValue() will help you to alter your required position as per the chart demogrphics.
please refer their api
toPixels() : http://api.highcharts.com/highcharts#Axis.toPixels()
toValue() : http://api.highcharts.com/highcharts#Axis.toValue()
hope using this will solve your requirement of positioning

Google Maps and ASP .NET MVC - Center the map at a marker

I'm building a page with a Google MAP that has a side bar with dynamically created divs linked to positions of markers in the map.
I'm using ASP.NET MVC with JQuery and Google Maps API v3.
Here is a look of it.
This page is loaded in a splash window and is generated dynamically.
In the background page the user types a state or city in an input field and in my controller action I search for all people that are located in that area and return a JSON.
I get the JSON and populate the map with markers and then I make the list of divs in the side bar.
I'd like to add a function to those divs that when they are clicked the map will center at the marker.
I came up with an idea for this solution which I could not finish.
I added class="clickable" and the attributes "Lat" and "Lng" with the values equal to the ones in the markers they are related to, and I tried to get their click event with JQuery and then set the map center with its Lat and Lng like this:
$(".clickable div").click(function(){
$('map_canvas').panTo($(this).attr('lat'), $(this).attr('lng'));
}
I had 2 problems with this approach.
- First, I didn't know how to get the map with JQuery.
I found 2 ways using like $('map_canvas').gMap but it didn't work. Tried a couple more things that I've found here in Stackoverflow but also didn't work.
Second - The JQuery would not catch the event click from the DIVs.
I tested on Google Chrome console the JQuery code and It worked but then my code would not trigger the click.
I tried something like $(".clickable div").click(function(){ alert("test"); } on Google Chrome and it worked, but in my script it did not.
I also tried to add listeners using addDomListener in my code but couldn't get around that either.
Could anyone please give me a light what would be a good way to do this without having to recreate the map when a div is clicked.
I also don't like the idea of adding Lat and Lng attributes to the divs, I don't know if that would work in any browser or if its good practice. I'm just out of solutions to this.
Here is the code I'm using. (I removed some of it to make it shorter and easier to read)
$(document).ready(function () {
//Google Maps API V3 - Prepares the ajaxForm options.
var options = {
beforeSubmit: showRequestPesquisaAdvogados,
success: showResponsePesquisaAdvogados,
type: 'post',
resetForm: false
};
$('#form-pesquisaAdvogado').ajaxForm(options);
//$(".clickable").click(function () { alert($(this).attr('lat')) });
});
function showRequestPesquisaAdvogados(formData, jqForm, options) {
$("#modal-processing-background").show(); //Shows processing splash window
}
function showResponsePesquisaAdvogados(responseText, statusText, xhr, $form) {
$("#modal-processing-background").hide();
//Hide processing window
loadSplashWindow();
CreateMap(responseText);
CreateSideBar(responseText);
}
}
function CreateMap(json) {
var mapOptions = {
center: new google.maps.LatLng(json[0].Endereco.Lat, json[0].Endereco.Lng),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
// marker:true
};
var infoWindow = new google.maps.InfoWindow();
var map = new google.maps.Map(document.getElementById("map-result"), mapOptions);
for (i = 0; i < json.length; i++) {
var data = json[i]
var myLatlng = new google.maps.LatLng(data.Endereco.Lat, data.Endereco.Lng);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: data.Endereco.Logradouro
});
(function (marker, data) {
// Attaching a click event to the current marker
google.maps.event.addListener(marker, "click", function (e) {
// Prepare the infoWindows content.
var contentString = //my content;
infoWindow.setContent(contentString);
infoWindow.open(map, marker);
});
//here I tried to add the listener to the div.
google.maps.event.addDomListener($(".clickable")[i], 'click',
function () {
map.panTo(new google.maps.LatLng($(this).attr('lat'),
$(this).attr('lng')));
});
})(marker, data);
}
}
function CreateSideBar(json) {
$(".sideBarConteiner").empty();
for (i = 0; i < json.length; i++) {
var contentString =
"<div class='clickable' lat='" + data.Endereco.Lat +
"' lng='" + data.Endereco.Lng + "' >" +
//...div's content here
"</div>";
$(".sideBarConteiner").append(contentString);
}
}
If you have any suggestions to make the code better or better practices, since I have only 3 months of experience with programming I might be going in the wrong direction without knowing, so please, feel free to change something if you think it'd be a better way.
I know my post is a bit lenghty, I just wanted to make it clear.
Thank you for your support in advance.
Regards,
Cesar.
I've found a way to do this by creating a global variable in javascript and keeping the map information in order to call it again later.
To to this I just added a var "map" right at the top of the .
<script type="text/javascript">
$.ajaxSetup({ cache: false }); //Forces IE to renew the cash for ajax.
var zoom = 8;
var mapOptions, map;
And then call a method to pan to the right point.
I added the properties Lat and Lng to the div and then pass the div in the javascript function and get the attributes from it.
function CreateSideBar(json) {
$(".sideBarConteiner").empty();
for (i = 0; i < json.length; i++) {
var contentString =
"<div class='clickable' data-lat='" + data.Endereco.Lat +
"' data-lng='" + data.Endereco.Lng + "' onclick='MarkerFocus(this)'>" +
//...div's content here
"</div>";
$(".sideBarConteiner").append(contentString);
}
}
And in my function:
function MarkerFocus(obj) {
var myLatlng =
new google.maps.LatLng($(obj).attr('data-lat'), $(obj).attr('data-lng'));
map.panTo(myLatlng);
}
It worked for me. I hope it helps you too.
Thanks to all for the help and support.
Cesar

Resources