Skip to content

Commit 8dc6e7c

Browse files
committed
feat: Migrates the Place Photos sample.
1 parent b2bd7cf commit 8dc6e7c

File tree

6 files changed

+287
-0
lines changed

6 files changed

+287
-0
lines changed

samples/place-photos/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Google Maps JavaScript Sample
2+
3+
## place-photos
4+
5+
This sample demonstrates the use of the Places API to display photos of a place.
6+
7+
## Setup
8+
9+
### Before starting run:
10+
11+
`npm i`
12+
13+
### Run an example on a local web server
14+
15+
`cd samples/place-photos`
16+
`npm start`
17+
18+
### Build an individual example
19+
20+
`cd samples/place-photos`
21+
`npm run build`
22+
23+
From 'samples':
24+
25+
`npm run build --workspace=place-photos/`
26+
27+
### Build all of the examples.
28+
29+
From 'samples':
30+
31+
`npm run build-all`
32+
33+
### Run lint to check for problems
34+
35+
`cd samples/place-photos`
36+
`npx eslint index.ts`
37+
38+
## Feedback
39+
40+
For feedback related to this sample, please open a new issue on
41+
[GitHub](https://github.com/googlemaps-samples/js-api-samples/issues).

samples/place-photos/index.html

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<!doctype html>
2+
<!--
3+
@license
4+
Copyright 2026 Google LLC. All Rights Reserved.
5+
SPDX-License-Identifier: Apache-2.0
6+
-->
7+
<!-- [START maps_place_photos] -->
8+
<html lang="en">
9+
<head>
10+
<title>Place Photos</title>
11+
12+
<link rel="stylesheet" type="text/css" href="./style.css" />
13+
<script type="module" src="./index.js"></script>
14+
<!-- prettier-ignore -->
15+
<script>(g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })
16+
({ key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly" });</script>
17+
</head>
18+
<body>
19+
<div id="container">
20+
<div class="place-overview">
21+
<div id="info">
22+
<h1 id="heading"></h1>
23+
<div id="summary"></div>
24+
</div>
25+
<div id="gallery"></div>
26+
</div>
27+
<div id="expanded-image"></div>
28+
</div>
29+
</body>
30+
</html>
31+
<!-- [END maps_place_photos] -->

samples/place-photos/index.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC. All Rights Reserved.
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
// [START maps_place_photos]
8+
async function init() {
9+
const { Place } = (await google.maps.importLibrary(
10+
'places'
11+
)) as google.maps.PlacesLibrary;
12+
13+
// Use a place ID to create a new Place instance.
14+
const place = new Place({
15+
id: 'ChIJydSuSkkUkFQRsqhB-cEtYnw', // Woodland Park Zoo, Seattle WA
16+
});
17+
18+
// Call fetchFields, passing the desired data fields.
19+
await place.fetchFields({
20+
fields: ['displayName', 'photos', 'editorialSummary'],
21+
});
22+
23+
// Get the various HTML elements.
24+
let heading = document.getElementById('heading') as HTMLElement;
25+
let summary = document.getElementById('summary') as HTMLElement;
26+
let gallery = document.getElementById('gallery') as HTMLElement;
27+
let expandedImageDiv = document.getElementById(
28+
'expanded-image'
29+
) as HTMLElement;
30+
let attributionLabel;
31+
32+
// Show the display name and summary for the place.
33+
heading.textContent = place.displayName as string;
34+
summary.textContent = place.editorialSummary as string;
35+
36+
// Add photos to the gallery.
37+
if (place.photos) {
38+
place.photos?.forEach((photo) => {
39+
const altText = 'Photo of ' + place.displayName;
40+
const img = document.createElement('img');
41+
const imgButton = document.createElement('button');
42+
const expandedImage = document.createElement('img');
43+
img.src = photo?.getURI({ maxHeight: 380 });
44+
img.alt = altText;
45+
imgButton.addEventListener('click', (event) => {
46+
event.preventDefault();
47+
expandedImage.src = img.src;
48+
expandedImage.alt = altText;
49+
expandedImageDiv.innerHTML = '';
50+
expandedImageDiv.appendChild(expandedImage);
51+
attributionLabel = createAttribution(photo.authorAttributions);
52+
expandedImageDiv.appendChild(attributionLabel);
53+
});
54+
55+
imgButton.appendChild(img);
56+
gallery.appendChild(imgButton);
57+
});
58+
}
59+
60+
// Display the first photo.
61+
if (place.photos && place.photos.length > 0) {
62+
const img = document.createElement('img');
63+
img.alt = 'Photo of ' + place.displayName;
64+
img.src = place.photos![0].getURI();
65+
expandedImageDiv.appendChild(img);
66+
attributionLabel = createAttribution(place.photos![0].authorAttributions);
67+
expandedImageDiv.appendChild(attributionLabel);
68+
}
69+
70+
// Helper function to create attribution DIV.
71+
function createAttribution(attribution) {
72+
const attributionLabel = document.createElement('a');
73+
attributionLabel.classList.add('attribution-label');
74+
if (attribution && attribution[0]) {
75+
attributionLabel.textContent = attribution[0].displayName;
76+
attributionLabel.href = attribution[0].uri;
77+
attributionLabel.target = '_blank';
78+
attributionLabel.rel = 'noopener noreferrer';
79+
return attributionLabel;
80+
}
81+
}
82+
}
83+
84+
init();
85+
// [END maps_place_photos]

samples/place-photos/package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "@js-api-samples/place-photos",
3+
"version": "1.0.0",
4+
"scripts": {
5+
"build": "tsc && bash ../jsfiddle.sh place-photos && bash ../app.sh place-photos && bash ../docs.sh place-photos && npm run build:vite --workspace=. && bash ../dist.sh place-photos",
6+
"test": "tsc && npm run build:vite --workspace=.",
7+
"start": "tsc && vite build --base './' && vite",
8+
"build:vite": "vite build --base './'",
9+
"preview": "vite preview"
10+
},
11+
"dependencies": {
12+
13+
}
14+
}

samples/place-photos/style.css

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC. All Rights Reserved.
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
/* [START maps_place_photos] */
7+
/*
8+
* Optional: Makes the sample page fill the window.
9+
*/
10+
html,
11+
body {
12+
height: 100%;
13+
margin: 0;
14+
padding: 0;
15+
}
16+
17+
#container {
18+
display: flex;
19+
border: 2px solid black;
20+
border-radius: 10px;
21+
padding: 10px;
22+
max-width: 950px;
23+
height: 100%;
24+
max-height: 400px;
25+
box-sizing: border-box;
26+
}
27+
28+
.place-overview {
29+
width: 400px;
30+
height: 380px;
31+
overflow-x: auto;
32+
position: relative;
33+
margin-right: 20px;
34+
}
35+
36+
#info {
37+
font-family: sans-serif;
38+
position: sticky;
39+
position: -webkit-sticky;
40+
left: 0;
41+
padding-bottom: 10px;
42+
}
43+
44+
#heading {
45+
width: 500px;
46+
font-size: x-large;
47+
margin-bottom: 20px;
48+
}
49+
50+
#summary {
51+
width: 100%;
52+
}
53+
54+
#gallery {
55+
display: flex;
56+
padding-top: 10px;
57+
}
58+
59+
#gallery img {
60+
width: 200px;
61+
height: 200px;
62+
margin: 10px;
63+
border-radius: 10px;
64+
cursor: pointer;
65+
object-fit: cover; /* fill the area without distorting the image */
66+
}
67+
68+
#expanded-image {
69+
display: flex;
70+
height: 370px;
71+
overflow: hidden;
72+
background-color: #000;
73+
border-radius: 10px;
74+
margin: 0 auto;
75+
}
76+
77+
.attribution-label {
78+
background-color: rgba(255, 255, 255, 0.7);
79+
font-size: 10px;
80+
font-family: sans-serif;
81+
margin: 2px;
82+
position: absolute;
83+
}
84+
85+
button {
86+
display: flex;
87+
outline: none;
88+
border: none;
89+
padding: 0;
90+
background: none;
91+
cursor: pointer;
92+
}
93+
94+
button:focus {
95+
background-color: rgb(222, 222, 222);
96+
border-radius: 10px;
97+
}
98+
99+
/* [END maps_place_photos] */

samples/place-photos/tsconfig.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"compilerOptions": {
3+
"module": "esnext",
4+
"target": "esnext",
5+
"strict": true,
6+
"noImplicitAny": false,
7+
"lib": [
8+
"es2015",
9+
"esnext",
10+
"es6",
11+
"dom",
12+
"dom.iterable"
13+
],
14+
"moduleResolution": "Node",
15+
"jsx": "preserve"
16+
}
17+
}

0 commit comments

Comments
 (0)