Fonto Editor iframe CMS connector

The Fonto Editor iframe CMS connector may be used to communicate with Fonto Editor using an iframe. This may be necessary when it is technically infeasible to implement the endpoints in a CMS.

The Fonto Editor iframe CMS Connector is an optional add-on for Fonto Editor. It can be used in implementations where it is technically impossible to implement the endpoints needed for the Fonto Editor standard CMS contracts. Please use the preferred Fonto Editor standard CMS contracts if possible.

In Fonto Editor 7.13 we changed some of our behavior in regards to managing focus. This causes the editor to no longer aggressively steal the focus from the host page. As a side effect this causes the editor to no longer be automatically focused when loaded into an iframe. Adding window.focus() in the CMS code will enable the focus on the Fonto Editor frame and scroll the cursor to the previously expected position.

The needed endpoints which are used by Fonto Editor to communicate with the CMS are normally called using HTTP API calls. The Fonto Editor iframe CMS connector instead uses iframe communication for these calls.

The Fonto Editor iframe CMS connector is an add-on for Fonto Editor which caters to the need of implementation partners which are unable to implement the Fonto Editor standard CMS contracts. For example, because there are technical limitations in the CMS which prevent the implementation of the needed HTTP API endpoints.

The Fonto Editor iframe CMS connector are wrappers around the same request and response models used by the Fonto Editor standard CMS contracts as described in the CMS connectors API documentation and in the Integrate with a CMS. The wrappers are encapsulated in a message sent using postMessage. The message follows the same standard as other Fonto Editor iframe communication, like fontoxml-execute-operation, with the exception that event.data is not a JSON string but an actual object.

Also see the example in the use cases.

Usage

The Fonto Editor iframe CMS connector can be added to Fonto Editor as an add-on.

When using the Fonto development server, you can use the /iframe route for testing by adding the following code to the dev-cms/configureDevCms.js file in your editor repository.

JavaScript

'use strict';

const routes = [
	require('../platform/fontoxml-connectors-iframe/dev-cms/routes')
];

module.exports = (router, config) => {
	return {
		routes: routes.map(route => route(router, config))
	};
};

Embedding Fonto Editor

Fonto Editor must be hosted within its own Window. The reason for this requirement is isolation; in the current state of HTML5, CSS and JS it is not possible to introduce a well-defined isolation between the host application and the editor. Consider global event handlers and the cascading part of CSS for example.

There are two ways to effectively isolate Fonto Editor in its own Window:

  1. Load the editor in an iframe.

  2. Embed the editor in a new window via window.open.

    When opening Fonto Editor in a new window, you should still embed the editor in an iframe inside the newly opened window. The reason being, when you would open an editor instance in a new window, and the user closes the CMS window, the editor can no longer make requests to it’s parent window and thus will generate errors.

When running Fonto Editor in an iframe, please make sure that this frame has focus when the editor loads. This will allow the editor to correctly respond to input and (if documents are loaded) place the cursor and allow users to start editing immediately. To focus the iframe, obtain a reference to its DOM element and call the focus method. For example:

Other

document.getElementById('fonto-iframe').focus();

Communicating with a Fonto Editor instance

The following section describes the API which allows the host application to communicate with a Fonto Editor instance.

The low-level API

The low-level API works by sending a request message from the Fonto Editor instance to the host application. These requests would otherwise have been sent by the Fonto Editor standard CMS contracts using a HTTP request. The receiving host application must process the message, perform the actual CMS logic and send a response message back to the editor instance.

Because of the way postMessage works, the order of request messages and response messages cannot be guaranteed. The messages contain a correlationId field which is used to identify which response belongs to which request.

HTML5 Web Messaging

The messages are passed back and forth between the host application and the Fonto Editor instance using HTML5 Web Messaging. See window.postMessage for additional details about this API.

Message data is passed along a normal JavaScript object using the the structured clone algorithm. The structured clone algorithm allows for JavaScript objects to be communicated, as well as File, Blob, RegExp, ImageData and other native JavaScript objects. Please refer to other sources for more information on these types.

Browser support

Fonto Editor has certain client requirements. The supported browsers all support the postMessage API.

Security

The current implementation does not implement additional security features, because the Fonto Editor instance should only run in a controlled environment.

Message format and serialization

The message parameter of each postMessage, also called data, should be an object containing the relevant properties.

Request message

This describes the request object, after JSON deserialization, as sent by the Fonto Editor instance to the host application.

RequestMessage

type

required

string

The type of the message. Must be of value ‘fontoxml-connectors-iframe’.

Example value: "fontoxml-connectors-iframe".

correlationId

required

string

A unique identifier that is used to identify which response message belongs to which request message.

Example value: "3896C13C-C63D-4F57-8438-06D3EEB616A9".

scope

required

string

The scope object as passed along to the Fonto Editor instance by the host application. This contains, among others, the editSessionToken.

See Invocation of Fonto Editor.

metadata

required

RequestMetadata

The wrapper object around the Fonto Editor standard CMS contracts request.

See Response metadata.

Response message

This describes the response object, before JSON deserialization, as send by the host application to the Fonto Editor instance.

ResponseMessage

type

required

string

The type of the message. Must be of value ‘fontoxml-connectors-iframe’.

Example value: "fontoxml-connectors-iframe"

correlationId

required

string

A unique identifier that is used to identify which response message belongs to which request message. This should match the correlationId as send in the request message.

Example value: "3896C13C-C63D-4F57-8438-06D3EEB616A9"

metadata

required

ResponseMetadata

The wrapper object around the Fonto Editor standard CMS contracts response.

See Request metadata.

Request metadata (a.k.a. Standard CMS request wrapper)

RequestMetadata

method

required

string

The HTTP method for the request.

Example value: "GET.

url

required

string

The url for the HTTP API endpoint as defined by the Fonto Editor standard CMS contracts.

Example value: "/document.

header

required

Object

A key value pair of the HTTP request headers. This might contain headers like accept, content-type or etag.

Example value

JavaScript

{
	"accept": "application/json"
}

query

optional

Object

A key value pair of the HTTP query parameters.

See CMS connectors API.

body

optional

mixed

The data, also known as the HTTP POST data.

See CMS connectors API.

Usually this is an object containing key/value pairs. For some implementations this can also include other types like Blob, FormData or a string.

multiparts

optional

array[string|File|Blob]

Optional. Some requests use multipart requests, for example file upload. This array contains all the parts. For example request data and binary file data. The filename property is optional, and is only set when the part is a file upload. The value property can be a string or a File or Blob object.

See CMS connectors API.

Example value

JavaScript

[
	{
		"name": "request",
		"value": { "json": "data" }
	},
	{
		"name": "file",
		"filename": "image.png",
		"value": <File>
	}
]

Response metadata (a.k.a. Standard CMS response wrapper)

ResponseMetadata

header

required

Object

A key value pair of the HTTP request headers. This might contain headers like accept, content-type or etag.

Example value

JavaScript

{
	"content-type": "application/json"
}

status

required

number

A HTTP response code as defined by the Fonto Editor standard CMS contracts.

Example value: 200.

body

optional

Object

The data, also known as the HTTP response body.

See CMS connectors API.

Additional endpoints

There are also some unique endpoints for the Fonto Editor iframe CMS connector. These endpoints are used to retrieve URLs for asset download, asset preview and document preview.

GET /document/preview/url

Request query parameters

Request query parameters

context

required

Object

The context for the request.

See CMS connectors API.

documentId

required

string

The unique identifier of the document to get the preview for.

Example value: "74257961-EDE3-4180-AF17-0A435EE8FB7B".

Response body

Status: 200 (You can also return a 400, 403 or 404 status)

JavaScript

{
	"url": "<documentPreviewUrl>"
}

GET /asset/url

Request query parameters

Request query parameters

context

required

Object

The context for the request.

See CMS connectors API.

id

required

string

The unique identifier of the asset to download.

Example value: "007E87C5-C05F-495B-AC08-E880D5AB9FDA".

Response body

Status: 200 (You can also return a 400, 403 or 404 status)

JavaScript

{
	"url": "<assetDownloadUrl>"
}

GET /asset/preview/url

Request query parameters

Request query parameters

context

required

Object

The context for the request.

See CMS connectors API.

variant

required

string

The preferred preview variant to retrieve.

Example value: "web".

id

required

string

The unique identifier of the asset to download.

Example value: "007E87C5-C05F-495B-AC08-E880D5AB9FDA".

Response body

Status: 200 (You can also return a 400, 403 or 404 status)

JavaScript

{
		"url": "<assetPreviewUrl>"
}

Examples

GET /document

Request message

JavaScript

{
	"type": "fontoxml-connectors-iframe",
	"correlationId": "f9f908a8-f1aa-4e55-a96e-f1806595bea9",
	"scope": {
		"documentIds": [ "74257961-EDE3-4180-AF17-0A435EE8FB7B" ]
	},
	"metadata": {
		"method": "GET",
		"url": "/document",
		"header": {
			"cache-control": "no-cache",
			"pragma": "no-cache",
			"accept": "application/json"
		},
		"query": {
			"context": "{\"editSessionToken\":\"EF091CD9-DC7A-4F91-9964-21CAF0DC3DCE\"}",
			"documentId": "74257961-EDE3-4180-AF17-0A435EE8FB7B"
		}
	}
}

Response message

JavaScript

{
	"type": "fontoxml-connectors-iframe",
	"correlationId": "f9f908a8-f1aa-4e55-a96e-f1806595bea9",
	"metadata": {
		"header": {
			"content-type": "application/json; charset=utf-8"
		},
		"status": 200,
		"body": {
			"documentId": "74257961-EDE3-4180-AF17-0A435EE8FB7B",
			"revisionId": "206D7015-B824-4054-BC13-ABAE54D175DF",
			"content": "<xml />",
			"lock": {
				"isLockAcquired": true,
				"isLockAvailable": true
			},
			"metadata": {}
		}
	}
}

PUT /document

Request message

JavaScript

{
	"type": "fontoxml-connectors-iframe",
	"correlationId": "1e91f838-946f-4309-abca-1fbd21b5d827",
	"scope": {
		"documentIds": [ "74257961-EDE3-4180-AF17-0A435EE8FB7B" ]
	},
	"metadata": {
		"method": "PUT",
		"url": "/document",
		"header": {
			"accept": "application/json",
			"content-type": "application/json"
		},
		"data": {
			"context": {
				"editSessionToken": "EF091CD9-DC7A-4F91-9964-21CAF0DC3DCE"
			},
			"documentId": "74257961-EDE3-4180-AF17-0A435EE8FB7B",
			"revisionId": "206D7015-B824-4054-BC13-ABAE54D175DF",
			"content": "<xml />",
			"metadata": {},
			"autosave": true
		}
	}
}

Response message

JavaScript

{
	"type": "fontoxml-connectors-iframe",
	"correlationId": "1e91f838-946f-4309-abca-1fbd21b5d827",
	"metadata": {
		"header": {},
		"status": 200,
		"data": {
			"revisionId": "547C0CC5-3C3B-4C78-B7A2-B3C9BEF36A61"
		}
	}
}

POST /asset

Request message

JavaScript

{
	"type": "fontoxml-connectors-iframe",
	"correlationId": "3f381c42-a2c6-4fca-d657-c0f4032ca7b4",
	"scope": {
		"documentIds": [ "74257961-EDE3-4180-AF17-0A435EE8FB7B" ]
	},
	"metadata": {
		"method": "POST",
		"url": "/asset",
		"header": {
			"accept": "application/json"
		},
		"multiparts": [
			{
				"name": "request",
				"value": "{\"context\":{\"editSessionToken\":\"EF091CD9-DC7A-4F91-9964-21CAF0DC3DCE\",\"documentId\":\"74257961-EDE3-4180-AF17-0A435EE8FB7B\"},\"type\":\"image\",\"folderId\":null,\"metadata\":{}}"
			},
			{
				"name": "file",
				"filename": "image.png",
				"value": <File>
			}
		]
	}
}

Response message

JavaScript

{
	"type": "fontoxml-connectors-iframe",
	"correlationId": "3f381c42-a2c6-4fca-d657-c0f4032ca7b4",
	"metadata": {
		"header": {
			"etag": "W/\"6b-+qq6vLWSXbjAstzmhjPrqg\"",
			"content-length": "107",
			"content-type": "application/json; charset=utf-8"
		},
		"status": 201,
		"body": {
			"id": "image.jpg",
			"type": "image",
			"label": "Image",
			"metadata": {}
		}
	}
}