Creating a Web Component

A web component is an ECMAScript (ES) module. It contains:

  • A class extending HTMLElement. The class can use the shadowRoot to define local CSS styles. These styles are only applied to HTML elements inside that shadowRoot – they will not affect any elements in documents where the web component is displayed.

  • A statement to register the class as a custom element. The custom element name must contain a -.

Here is a skeleton web component that you can use as a basis for your own web components:

/**
 * Creating the web component
 */
class MyComponent extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
      <style>
        :host { width: 100%; display: block; } /* Styles the web component tag */
      </style>

      <!-- Add your web component HTML here -->
    `;
  }

  connectedCallback() {
    console.log('The CUE interface of the web component:', this.cueInterface);
    // The web component is now attached.
    // Add your logic here.
  }
}
customElements.define('my-component', MyComponent);

/**
 * Creating the icon (if required)
 */
class MyComponentIcon extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `<!-- Add your web component icon HTML here -->`;
  }

  connectedCallback() {
    console.log('The CUE interface of the icon:', this.cueInterface);
    // The icon is now attached.
    // Add your logic here.
  }
}

customElements.define('my-component-icon', MyComponentIcon);

Field editor web components have no use for an icon, so in this case the icon class can be omitted.

The cueInterface object

CUE always passes a cueInterface object to the web component. cueInterface always has the following basic properties:

escenic.endpoint

The URI of the Content Engine web service as defined with the endpoints/escenic setting in the CUE configuration file (see Configuring CUE).

escenic.credentials

The authorization token needed to access the escenic.endpoint URI. This value must be included as the Authorization header in requests sent to the escenic.endpoint URI.

currentUser.userName

The user name of the current user.

currentUser.realName

The real name of the current user.

currentUser.email

The email address of the current user.

newsgate

An object providing various functions for interacting with the Newsgate server.

selection

An object for manipulating the current rich text selection (if any). This object exposes the following functions:

getCurrentSelection()

Returns the current rich text selection.

replaceSelection(newContent: string, selection: Selection)

Replaces selection with newContent. newContent must be a valid HTML fragment.

forEachBlockInSelection(range: Range, forEachBlock: Function)

Loops through every top-level node in the selection and applies the forEachBlock function. This is particularly useful for text selections that cross paragraph boundaries.

replaceElement(element: Element, elementName: string, className: string)

Replaces element with a new element of type elementName and class className. All the children of element are preserved. In other words, after the function has executed, the children of element will be the children a new element of type elementName.

replaceBlockElement(element: Element, elementName: string, className: string)

Replaces the closest <p> or <div> ancestor of element with a new element of type elementName and class className. All the children of the ancestor element are preserved. In other words, after the function has executed, all the children of the ancestor element will be the children of a new element of type elementName.

addSelectionWatcher(watcher: Function)

Adds a watcher that will be notified when the current rich text selection changes. The watcher will be invoked with the new selection.

removeSelectionWatcher(watcher: Function)

Removes a previously added watcher.

For an example of how to use these functions, see Selection API Example.

For content items, the cueInterface object's properties will also include article URL, article ID and content type. For sections it will also include section URL, section ID, and section name.

In addition, the cueInterface object has other context-dependent properties that vary according to the type of web component created. These properties are described along with the different web component types.

Drag and drop from web components

You can drag objects from all web components except rich text field extensions to drop zones in CUE. Anywhere in the CUE interface that you can drop an uploaded file, you can also drop an object that has been dragged from a web component, as long the object is correctly constructed. A correctly constructed draggable object is a JSON object with a single property, files. This property is an array of objects, each object being composed of three properties:

name

The file name of this object

mimeType

The mime type of this object

dataURL OR url

For external objects, the third property is called dataURL, and holds the content of the object, encoded as a data URL. The dropped object may, however, in some cases be an existing Escenic content item, in which case the third property is called url and holds the URL of the content item.

The entire JSON object must be supplied as the drag event's dragData property and be assigned the mime type application/x-web-component-data.

See Editor Side Panel Example for an example of how to construct a draggable object.