Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c10de71
Started with the barest of possibly workable content ➕
triplingual Oct 24, 2025
251105e
Switched to use IIIF icon for tractable CORS troubleshooting 🔀🖼️
triplingual Oct 24, 2025
9359dbe
Added drag-and-drop recipe to links and ToC 📝
triplingual Oct 31, 2025
c2872dd
Extremely rough draft of a use case 📝
triplingual Oct 31, 2025
4d30998
Started restrictions, rolled back draggable image 📝🖼️
triplingual Oct 31, 2025
c474dce
Added `JSON.stringify()` per @glenrobson ✨
triplingual Oct 31, 2025
b3bf320
Moved restriction text ➡️ implementation and drafted new restriction …
triplingual Oct 31, 2025
770f280
Edited use case for readability 📝
triplingual Nov 6, 2025
dbd7185
Swapped test content for copy of content from JavaScript 🔀
triplingual Nov 6, 2025
9558b95
Significant edits to flesh out the text 📝
triplingual Nov 6, 2025
aa83cc5
Expanded implementation notes, added new example 📝➕
triplingual Nov 14, 2025
7f6046d
Corrected type for content per authors' call 🛠️
triplingual Nov 18, 2025
6099f5a
Added text about lack of support per authors' call 📝
triplingual Nov 18, 2025
e1ee0ef
Made Example section text accurate, added visible markup for logo 📝
triplingual Nov 18, 2025
1a0de93
Finished the incomplete thought of one graf, flowed through consequen…
triplingual Nov 18, 2025
1d17da3
Explained why JSON in this example 📝
triplingual Nov 18, 2025
5fe3e30
Expanded notes to viewer developers in Implementation and Restrictions 📝
triplingual Nov 18, 2025
59ea17f
Added logo image used in recipe ➕🖼️
triplingual Nov 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions _includes/links.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@

[0560]: {{ site.cookbook_url | absolute_url }}/recipe/0560-resources-on-a-timeline/ "Rendering Resources Sequentially on a Timeline"
[0561]: {{ site.cookbook_url | absolute_url }}/recipe/0561-text-on-image/ "Visible Text Resource on a Canvas"
[0599]: {{ site.cookbook_url | absolute_url }}/recipe/0599-drag-and-drop/ "Drag and Drop"

[cookbook-process]: {{site.cookbook_url | absolute_url }}/recipe

Expand Down
2 changes: 1 addition & 1 deletion index.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Recipes using [Content State API](https://iiif.io/api/content-state/1.0/)
* [Loading a manifest with a viewer using a link][0466]
* [Open a specific region of a canvas in a viewer][0485]
* [Sharing a link for opening two or more Canvases][0540]

* [Drag and drop][0599]


## Technical
Expand Down
110 changes: 110 additions & 0 deletions recipe/0599-drag-and-drop/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
title: Name of Recipe
id: -1
layout: recipe
tags: [tbc]
summary: "tbc"
viewers:
topic:
- basic
---

## Use Case

As a person wanting to annotate a IIIF resource, you would like to open a manifest in a viewer not available in the web interface where you first find the resource.

Alternately, as a viewer developer, you would like to allow your viewer to receive dragged-over items.

## Implementation Notes

Implementing this recipe requires a resource provider and a viewer each to implement their part.

### For Resource Providers

The resource provider must have a draggable item — such as an image — that makes use of the DataTransfer object. It will have a [`dataTransfer.setData` method](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer) attached to the item's `dragstart` event.

A script implementing such a method for a Manifest could look like the below.
```
<script>
function drag(ev) {
ev.dataTransfer.setData("text/plain", JSON.stringify({
"@context": "http://iiif.io/api/presentation/3/context.json",
"id": "https://iiif.io/api/cookbook/recipe/0599-drag-and-drop/dnd-manifest",
"type": "Annotation",
"motivation": ["contentState"],
"target": {
"id": "https://iiif.io/api/cookbook/recipe/0006-text-language/manifest.json",
"type": "Manifest"
}
}));
}
</script>
```

Note that the script represents the manifest content as JSON to parallel other cookbook resource content, but converts it to a string to match the content type parameter. While [the `setData` method of Web Assembly can use other content types](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setData), the spec for [IIIF Content State](https://iiif.io/api/content-state/1.0/#initialization-mechanisms-dragdrop) requires a content type of `text/plain` for maximum compatibility.

The content does not have to be a full Manifest. A script implementing this same method for a single Canvas of a Manifest could look like the below. (Noting that there would be no likely practical difference from the above since this manifest contains but one Canvas.)
```
<script>
function drag(ev) {
ev.dataTransfer.setData("text/plain", JSON.stringify({
"@context": "http://iiif.io/api/presentation/3/context.json",
"id": "https://iiif.io/api/cookbook/recipe/0599-drag-and-drop/dnd-manifest",
"type": "Annotation",
"motivation": ["contentState"],
"target": {
"id": "https://iiif.io/api/cookbook/recipe/0006-text-language/canvas/p1",
"type": "Canvas",
"partOf": [{
"id": "https://iiif.io/api/cookbook/recipe/0006-text-language/manifest.json",
"type": "Manifest"
}]
}
}));
}
</script>
```

### For Viewer Developers

A supporting viewer must have an interface capable of handling the DataTransfer object's data carried by the draggable item in its `drop` event. Somewhat as for resource providers, [the `getData` method of Web Assembly can specify other content types](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/getData) but the spec for [IIIF Content State](https://iiif.io/api/content-state/1.0/#initialization-mechanisms-dragdrop) requires a content type of `text/plain` for maximum compatibility. See the immediately following section for cautions about receiving content.

## Restrictions

Because implementation is two-part, you may only have control over one half of the ability to drag and drop. Consequently, and since this action is only in a GUI environment, you will need to consider whether visitors to your IIIF interface would benefit from some kind of support text.

Viewer developers will have a special need to consider security when implementing a droppable interface. This recipe cannot cover all of data transfer security, but will note that all content provided to a site should be sanitized.

## Example

Below is an image of the IIIF logo, decorated with the appropriate JavaScript event handler attributes, and a visible version of the markup for that image, showing the connection to the page script for the `drag` event. For a supporting viewer, the IIIF logo image below could be dragged onto its viewing area and dropped, which would result in the viewer retrieving the manifest for the IIIF Cookbook recipe titled ["Internationalization and Multi-language Values"][0006].

No viewers currently support this approach to dragging and dropping a manifest.

<img src="logo-sm.png" draggable="true" ondragstart="drag(event)" alt="IIIF logo; drag and drop onto a supporting viewer to see this resource in that viewer">

```
<img src="logo-sm.png" draggable="true" ondragstart="drag(event)" alt="IIIF logo; drag and drop onto a supporting viewer to see this resource in that viewer">
```

<script>
function drag(ev) {
ev.dataTransfer.setData("text/plain", JSON.stringify({
"@context": "http://iiif.io/api/presentation/3/context.json",
"id": "https://iiif.io/api/cookbook/recipe/0599-drag-and-drop/dnd-manifest",
"type": "Annotation",
"motivation": ["contentState"],
"target": {
"id": "https://iiif.io/api/cookbook/recipe/0006-text-language/manifest.json",
"type": "Manifest"
}
}));
}
</script>

## Related Recipes

Provide a bulleted list of related recipes and why they are relevant.

{% include acronyms.md %}
{% include links.md %}
Binary file added recipe/0599-drag-and-drop/logo-sm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions recipe/0599-drag-and-drop/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"@context": "http://iiif.io/api/presentation/3/context.json",
"id": "https://iiif.io/api/cookbook/recipe/0599-drag-and-drop/dnd-manifest.json",
"type": "Annotation",
"motivation": ["contentState"],
"target": {
"id": "https://iiif.io/api/cookbook/recipe/0006-text-language/manifest.json",
"type": "Manifest"
}
}
Loading