---
sidebar_position: 0
---

# offline

Web-based applications often require additional assets to function, but downloading them every time is undesirable. The JS Applet SDK offers a wide range of APIs for storing different kinds of assets.

Generally, there are four types of assets:
- CSS & JavaScript files
- Fonts
- Audio-visual content (image, video, and audio files)
- Arbitrary data (e.g., JSON files, plain text, binary data)

And the SDK also provides two different APIs:
- `sos.offline` & `sos.offline.cache`: A file system abstraction for caching files that are removed when the applet configuration is changed or the applet is reloaded. This method is usually preferred if the files can be re-downloaded.
- `sos.fileSystem`: Direct access to the file system. All files are stored permanently and are not removed when the applet configuration changes.

Using the `sos.offline` and `sos.offline.cache` APIs allows you to ship an applet without content, including only basic bootstrapping code, and load the content dynamically. The content will then be available even when the device is offline.

:::warning
Emulator has certain limitations while handling offline files. [Read more here](https://docs.signageos.io/hc/en-us/articles/4405238997138)
:::

## Methods

### addFile()

The `addFile()` method downloads the specified file and stores it locally.

CSS and JavaScript files are specific because they must be loaded with an HTML tag. The `sos.offline` API methods download, save, and append the resource to the web page. When adding a file, choose a unique identifier (`uid`) that should not change for the resource. The file will be overwritten if another file is added with the same `uid`.

:::info
The file URL must point to a file. If your URI leads to a redirect (e.g. from http to https), the API will not work.
:::

```ts expandable
addFile(file: ISaveFile): Promise<void>;
// show-more
/**
 * Interface represents a file that can be saved to cache and loaded into applet resources.
 */
interface ISaveFile {
    uid: string;
    uri: string;
    type: IFileType;
    headers?: {
        [key: string]: string;
    };
    flags?: IFlag[];
}

type IFileType = 'javascript' | 'css' | 'video';

interface IFlag {
    type: 'append';
    element: IElement;
}

interface IElement {
    uid: string;
}

```

#### Params

| Name           | Type                         | Required         | Description                                                                                   |
|----------------|------------------------------|------------------|-----------------------------------------------------------------------------------------------|
| `file`         | `ISaveFile`                  |  <div>Yes</div>  | URI of the file to be downloaded.                                                             |
| `file.uid`     | `string`                     |  <div>Yes</div>  | Unique file identifier is used for later file retrieval, must contain a-z,A-Z,0-9 characters. |
| `file.type`    | `IFileType`                  |  <div>Yes</div>  | Type of the file, e.g. 'javascript', 'css', etc.                                              |
| `file.headers` | `{ [key: string]: string; }` |  <div>No</div>   | HTTP headers to be sent with the request for the file.                                        |
| `file.flags`   | `IFlag[]`                    |  <div>No</div>   | Additional flags for appending stored files to the DOM or other operations                    |

#### Return value

Resolves when the file is added and the file is appended to the document when flags are used.

#### Possible errors


- If the `file` parameter is not an object.
- If the `file` parameter does not contain a valid parameters.

#### Example

```ts
await sos.offline.addFile({
	uri: 'https://code.jquery.com/jquery-3.7.1.slim.min.js',
	uid: 'jquery-3.7.1.slim.min.js',
	type: sos.offline.types.javascript,
	flags: [sos.offline.flags.append(document.body)],
});
```

<Separator />

### addFiles()

The `addFiles()` method downloads the specified files and stores them locally.
The order in which the files are downloaded and stored is **not** guaranteed.

CSS and JavaScript files are specific because they must be loaded with an HTML tag. The `sos.offline` API methods download, save, and append the resource to the web page. When adding a file, choose a unique identifier (`uid`) that should not change for the resource. The file will be overwritten if another file is added with the same `uid`.

```ts expandable
addFiles(files: ISaveFile[]): Promise<Awaited<void>[]>;
// show-more
/**
 * Interface represents a file that can be saved to cache and loaded into applet resources.
 */
interface ISaveFile {
    uid: string;
    uri: string;
    type: IFileType;
    headers?: {
        [key: string]: string;
    };
    flags?: IFlag[];
}

type IFileType = 'javascript' | 'css' | 'video';

interface IFlag {
    type: 'append';
    element: IElement;
}

interface IElement {
    uid: string;
}

```

#### Params

| Name    | Type          | Required         | Description                                         |
|---------|---------------|------------------|-----------------------------------------------------|
| `files` | `ISaveFile[]` |  <div>Yes</div>  | Array of files to be downloaded and stored locally. |

#### Return value

Resolves when all files are added.

#### Possible errors

If the `files` parameter is not an array of objects.

#### Example

```ts
await sos.offline.addFile([{
	uri: 'https://unpkg.com/normalize.css@8.0.1/normalize.css',
	uid: 'normalize.css',
	type: sos.offline.types.css,
	flags: [sos.offline.flags.append(document.head)],
}, {
	uri: 'https://code.jquery.com/jquery-3.7.1.slim.min.js',
	uid: 'jquery-3.7.1.slim.min.js',
	type: sos.offline.types.javascript,
	flags: [sos.offline.flags.append(document.body)],
}]);
```

:::note[GitHub Example]

- [ Example of Applet that save files and load them in one file](https://github.com/signageos/applet-examples/blob/master/examples/content-js-api/offline-resources)

:::

<Separator />

### addFilesSync()

Method `addFile()` will allow you to load single resource into applet. If you want to load more resource, use `addFiles()`.

The order in which the files are downloaded and stored **is** guaranteed.

```ts expandable
addFilesSync(files: ISaveFile[]): Promise<void>;
// show-more
/**
 * Interface represents a file that can be saved to cache and loaded into applet resources.
 */
interface ISaveFile {
    uid: string;
    uri: string;
    type: IFileType;
    headers?: {
        [key: string]: string;
    };
    flags?: IFlag[];
}

type IFileType = 'javascript' | 'css' | 'video';

interface IFlag {
    type: 'append';
    element: IElement;
}

interface IElement {
    uid: string;
}

```

#### Params

| Name    | Type          | Required         | Description                                         |
|---------|---------------|------------------|-----------------------------------------------------|
| `files` | `ISaveFile[]` |  <div>Yes</div>  | Array of files to be downloaded and stored locally. |

#### Return value

Resolves when all files are added and the files are appended to the document when flags are used.

#### Possible errors

If the `files` parameter is not an array of objects

#### Example

```ts
const file = { // File that will be loaded into an applet
    "uri": "https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js",
    "uid": "jquery-2.2.4.min.js",
    "type": sos.offline.types.javascript,
    "flags": [sos.offline.flags.append(document.body)]
}

await sos.offline.addFile(file); // And finally load file
```

<Separator />

### addFont()

The `addFont()` method downloads the specified file and stores it locally. You should use this method for loading fonts instead of
using `addFile()`, because it also generates appropriate font-face definition.

```ts expandable
addFont(font: IAddFont): Promise<void>;
// show-more
interface IAddFont extends IFontFaceProperties {
    uid: string;
    append: HTMLElement;
    formats: IFontFormats;
}

interface IFontFormats {
    woff2: string;
    eot?: string;
    woff?: string;
    ttf?: string;
    svg?: string;
}

interface IFontFaceProperties {
    fontFamily: string;
    fontStretch?: string;
    fontStyle?: IFontStyle;
    fontWeight?: string;
    unicodeRange?: string;
}

type IFontStyle = `normal` | `italic` | `oblique` | `initial` | `inherit` | AnyString;

type AnyString = string & {};

```

#### Params

| Name                | Type           | Required         | Description                                                                                         |
|---------------------|----------------|------------------|-----------------------------------------------------------------------------------------------------|
| `font.uid`          | `string`       |  <div>Yes</div>  | Unique file identifier is used for later file retrieval, must contain a-z,A-Z,0-9 and . characters. |
| `font.append`       | `HTMLElement`  |  <div>Yes</div>  | Reference to HTMLElement where the generated font-face will resist.                                 |
| `font.fontFamily`   | `string`       |  <div>Yes</div>  | Font family that can be referenced from your CSS.                                                   |
| `font.formats`      | `IFontFormats` |  <div>Yes</div>  | URI where these formats will be downloaded from.                                                    |
| `font.fontStretch`  | `string`       |  <div>No</div>   | Allows you to make text wider or narrower.                                                          |
| `font.fontStyle`    | `IFontStyle`   |  <div>No</div>   | Specifies the font style for a text. (Either `normal`, `italic`, `oblique`, `initial` or `inherit`) |
| `font.fontWeight`   | `string`       |  <div>No</div>   | Sets how thick or thin characters in text should be displayed                                       |
| `font.unicodeRange` | `string`       |  <div>No</div>   | Defines the range of Unicode characters the font supports, default value is "U+0-10FFFF"            |
| `font.formats`      | `IFontFormats` |  <div>Yes</div>  | Dictionary of supported formats with its files                                                      |

#### Return value

Resolves when the font is added and the style element is appended to the document.

#### Possible errors

If the `font` parameter is not an object.

:::note[GitHub Example]

- [ Example of Applet that loads custom font](https://github.com/signageos/applet-examples/tree/master/examples/content-js-api/fonts)

:::