Skip to content

Commit 6ebc41d

Browse files
authored
Merge branch 'master' into 0489-multimedia-canvas
2 parents 4e5b468 + d18d523 commit 6ebc41d

File tree

7 files changed

+152
-1
lines changed

7 files changed

+152
-1
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{% if include.viewers %}
2+
{% assign viewers = include.viewers | split: "," %}
3+
{% else %}
4+
{% assign viewers = page.viewers %}
5+
{% endif %}
6+
[JSON-LD]({{ include.iiif-content }}) {% for viewerTxt in viewers %}{% assign viewer = viewerTxt | strip %}| {% include viewer_link.html type=viewer manifest=include.iiif-content class="content-state" %}{% endfor %}
7+
8+
{% if page.code %}
9+
{% include code_links.html %}
10+
{% endif %}
11+
12+
<script>
13+
function encodeContentState(plainContentState) {
14+
let uriEncoded = encodeURIComponent(plainContentState); // using built in function
15+
let base64 = btoa(uriEncoded); // using built in function
16+
let base64url = base64.replace(/\+/g, "-").replace(/\//g, "_");
17+
let base64urlNoPadding = base64url.replace(/=/g, "");
18+
return base64urlNoPadding;
19+
}
20+
21+
const links = document.getElementsByClassName("content-state");
22+
23+
Array.from(links).forEach(link => {
24+
link.title = "Generating iiif-content link...."
25+
fetch(link.dataset.iiifContent).then(response=> {
26+
response.json().then (anno => {
27+
const encoded = encodeContentState(JSON.stringify(anno));
28+
29+
if (/iiif-content=.*&/.test(link.href)){
30+
link.href = link.href.replace(/iiif-content=.*&/, "iiif-content=" + encoded + '&');
31+
} else {
32+
link.href = link.href.replace(/iiif-content=.*$/, "iiif-content=" + encoded);
33+
}
34+
link.title = "";
35+
})
36+
37+
});
38+
});
39+
</script>

_includes/links.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@
7474

7575
[0466]: {{ site.cookbook_url | absolute_url }}/recipe/0466-link-for-loading-manifest/ "Loading a manifest with a viewer using a link"
7676

77+
[0485]: {{ site.cookbook_url | absolute_url }}/recipe/0485-contentstate-canvas-region/ "Open a specific region of a canvas in a viewer"
78+
7779
[0434]: {{ site.cookbook_url | absolute_url }}/recipe/0434-choice-av/ "Multiple Choice of Audio Formats in a Single View (Canvas)"
7880
[0489]: {{ site.cookbook_url | absolute_url }}/recipe/0489-multimedia-canvas/ "Rendering Multiple Media Types on a Time-Based Canvas"
7981

_includes/viewer_link.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,4 @@
6464
{% else %}
6565
{% capture default_text %}Unknown Viewer type '{{ include.type}}'{% endcapture %}
6666
{% capture viewer_url %}{{manifest_url |strip}}{% endcapture %}
67-
{% endif %}<a href="{{ viewer_url | strip }}" target="_blank">{{ include.text | default: default_text }}</a>
67+
{% endif %}<a href="{{ viewer_url | strip }}" class="{{ include.class }}" data-iiif-content="{{manifest_url |strip}}" target="_blank">{{ include.text | default: default_text }}</a>

index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ _(leading on to segmentation examples later)_
141141
Recipes using [Content State API](https://iiif.io/api/content-state/1.0/)
142142

143143
* [Loading a manifest with a viewer using a link][0466]
144+
* [Open a specific region of a canvas in a viewer][0485]
144145

145146

146147
## Technical
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"@context": "http://iiif.io/api/presentation/3/context.json",
3+
"id": "https://example.org/import/1",
4+
"type": "Annotation",
5+
"motivation": ["contentState"],
6+
"target": {
7+
"id": "https://iiif.io/api/cookbook/recipe/0009-book-1/canvas/p2#xywh=1528,3024,344,408",
8+
"type": "Canvas",
9+
"partOf": [{
10+
"id": "https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json",
11+
"type": "Manifest"
12+
}]
13+
}
14+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
title: Open a specific region of a Canvas in a viewer
3+
id: 485
4+
layout: recipe
5+
tags: [annotation, content-state]
6+
summary: "Allows users to use Content State API to open a specific region of a Canvas by means of supported viewers."
7+
viewers:
8+
topic:
9+
- content-state
10+
---
11+
12+
## Use Case
13+
14+
I want to share a link to highlight a detail in a specific region of an image to share a portion of a digitized manuscript text, allowing the user easy access to the rest of the manuscript.
15+
16+
Institutions might want to use this recipe to share portions of their object through social media, allowing a direct link to the viewer to improve the user's interaction with the digitized content. A scholar who finds a relevant passage in a manuscript might want to share the precise location with other colleagues, allowing them to check the original source.
17+
18+
## Implementation Notes
19+
20+
This request can be implemented in a standardized manner using the [IIIF Content State API](https://iiif.io/api/content-state), providing the data as values of the `iiif-content` query string parameter as explained in the [API section](https://iiif.io/api/content-state/1.0/#initialization-mechanisms-link).
21+
22+
We can use the [Web Annotation Data Model](https://www.w3.org/TR/annotation-model/) to encode the information necessary, as shown in ["A Region of a Canvas in a Manifest"](https://iiif.io/api/content-state/1.0/#51-a-region-of-a-canvas-in-a-manifest) section of the standard.
23+
24+
However, before passing the data as a query parameter, we must encode it as explained in the [Content State encoding guidelines](https://iiif.io/api/content-state/1.0/#6-content-state-encoding).
25+
26+
In this example, we want to highlight a portion of an image contained in a book. We will use the following manifest shown in the Simple Manifest Book recipe, which is available at the following link: [https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json](https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json)
27+
28+
We want to open the viewport to a specific Canvas region using a viewer available on the following page `https://example.org/viewer`.
29+
30+
First, we create an Annotation:
31+
32+
```json
33+
{
34+
"@context": "http://iiif.io/api/presentation/3/context.json",
35+
"id": "https://example.org/import/1",
36+
"type": "Annotation",
37+
"motivation": ["contentState"],
38+
"target": {
39+
"id": "https://iiif.io/api/cookbook/recipe/0009-book-1/canvas/p2#xywh=1528,3024,344,408",
40+
"type": "Canvas",
41+
"partOf": [{
42+
"id": "https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json",
43+
"type": "Manifest"
44+
}]
45+
}
46+
}
47+
```
48+
49+
We can create an Annotation with `motivation` set to `contentState` and a target `type` set to Canvas. The `id` of the target will contain a fragment selector (`#xywh=1528,3024,344,408`) with the coordinates of the Canvas we want to share, while the `partOf` element has the `id` of the Manifest containing the Canvas.
50+
51+
We can now use one of the methods listed in the [examples of Content State encoding section](https://iiif.io/api/content-state/1.0/#63-examples-of-content-state-encoding) to generate a base64url string (**note: for brevity, we removed new line characters and white space before computing the base64url**).
52+
53+
We can pass the encoded value, using the `iiif-content` query parameter of the viewer landing page:
54+
[https://example.org/viewer?iiif-content=JTdCJTIyJTQwY29udGV4dCUyMiUzQSUyMmh0dHAlM0ElMkYlMkZpaWlmLmlvJTJGYXBpJTJGcHJlc2VudGF0aW9uJTJGMyUyRmNvbnRleHQuanNvbiUyMiUyQyUyMmlkJTIyJTNBJTIyaHR0cHMlM0ElMkYlMkZleGFtcGxlLm9yZyUyRmltcG9ydCUyRjElMjIlMkMlMjJ0eXBlJTIyJTNBJTIyQW5ub3RhdGlvbiUyMiUyQyUyMm1vdGl2YXRpb24lMjIlM0ElNUIlMjJjb250ZW50U3RhdGUlMjIlNUQlMkMlMjJ0YXJnZXQlMjIlM0ElN0IlMjJpZCUyMiUzQSUyMmh0dHBzJTNBJTJGJTJGaWlpZi5pbyUyRmFwaSUyRmNvb2tib29rJTJGcmVjaXBlJTJGMDAwOS1ib29rLTElMkZjYW52YXMlMkZwMiUyM3h5d2glM0QxNTI4JTJDMzAyNCUyQzM0NCUyQzQwOCUyMiUyQyUyMnR5cGUlMjIlM0ElMjJDYW52YXMlMjIlMkMlMjJwYXJ0T2YlMjIlM0ElNUIlN0IlMjJpZCUyMiUzQSUyMmh0dHBzJTNBJTJGJTJGaWlpZi5pbyUyRmFwaSUyRmNvb2tib29rJTJGcmVjaXBlJTJGMDAwOS1ib29rLTElMkZtYW5pZmVzdC5qc29uJTIyJTJDJTIydHlwZSUyMiUzQSUyMk1hbmlmZXN0JTIyJTdEJTVEJTdEJTdE](https://example.org/)
55+
56+
We can also create an anchor tag with the link as the `href` attribute for use in a web page:
57+
58+
```html
59+
<a href="https://example.org/viewer?iiif-content=JTdCJTIyJTQwY29udGV4dCUyMiUzQSUyMmh0dHAlM0ElMkYlMkZpaWlmLmlvJTJGYXBpJTJGcHJlc2VudGF0aW9uJTJGMyUyRmNvbnRleHQuanNvbiUyMiUyQyUyMmlkJTIyJTNBJTIyaHR0cHMlM0ElMkYlMkZleGFtcGxlLm9yZyUyRmltcG9ydCUyRjElMjIlMkMlMjJ0eXBlJTIyJTNBJTIyQW5ub3RhdGlvbiUyMiUyQyUyMm1vdGl2YXRpb24lMjIlM0ElNUIlMjJjb250ZW50U3RhdGUlMjIlNUQlMkMlMjJ0YXJnZXQlMjIlM0ElN0IlMjJpZCUyMiUzQSUyMmh0dHBzJTNBJTJGJTJGaWlpZi5pbyUyRmFwaSUyRmNvb2tib29rJTJGcmVjaXBlJTJGMDAwOS1ib29rLTElMkZjYW52YXMlMkZwMiUyM3h5d2glM0QxNTI4JTJDMzAyNCUyQzM0NCUyQzQwOCUyMiUyQyUyMnR5cGUlMjIlM0ElMjJDYW52YXMlMjIlMkMlMjJwYXJ0T2YlMjIlM0ElNUIlN0IlMjJpZCUyMiUzQSUyMmh0dHBzJTNBJTJGJTJGaWlpZi5pbyUyRmFwaSUyRmNvb2tib29rJTJGcmVjaXBlJTJGMDAwOS1ib29rLTElMkZtYW5pZmVzdC5qc29uJTIyJTJDJTIydHlwZSUyMiUzQSUyMk1hbmlmZXN0JTIyJTdEJTVEJTdEJTdE">Link for visualizing the region of a Canvas using a viewer.</a>
60+
```
61+
62+
An alternative way of sharing a region of an image is to use the [Image API](https://iiif.io/api/image/3.0/#41-region). However, the context from which the region is extracted is not easily accessible. Instead, sharing a link to open the specific region with a viewer allows the users to explore another part of the image or related content and metadata in the Manifest.
63+
64+
## Restrictions
65+
66+
Note Content State does not define how the viewer should bring the regions of the Canvas to the attention of the user. It only mentions:
67+
68+
"This data structure can be used by clients to load the resource required, present a particular part of the resource to the user." https://iiif.io/api/content-state/1.0/#content-state
69+
70+
Viewers may set the viewport to the region or highlight the region with an annotation.
71+
72+
## Example
73+
74+
In this example we are aiming to highlight the bug that is on the second page of the [Book in recipe][0009]. The part of the image we are highlighting is as follows:
75+
76+
![Image of a bug](https://iiif.io/api/image/3.0/example/reference/59d09e6773341f28ea166e9f3c1e674f-gallica_ark_12148_bpt6k1526005v_f19/1528,3024,344,408/pct:50/0/default.jpg)
77+
78+
and this is located in the following region of the second image:
79+
80+
![Location of the region to be highlighted.](page.jpg)
81+
82+
{% include content-state-viewers.html iiif-content="annotation.json" viewers="" %}
83+
84+
{% include jsonviewer.html src="annotation.json" %}
85+
86+
## Related Recipes
87+
88+
* [Simplest Manifest - Image][0001] shows the basic structure of a IIIF Manifest using Presentation API 3.0.
89+
* [A simple book][0009] shows the manifest structure.
90+
* [Link for loading a manifest][0466] another example of Content State API.
91+
* [Addressing a Spatial Region][0299] an example of sharing a region of a Canvas creating a new Manifest.
92+
93+
{% include acronyms.md %}
94+
{% include links.md %}
95+
104 KB
Loading

0 commit comments

Comments
 (0)