DesignEditor Tutorial
====================

You may be already familiar with the [IFrame API](https://customerscanvas.com/docs/cc/IframeApi-introduction.htm) which allows for integrating the Customer's Canvas editor to a page. It exposes a JavaScript API that enables you to extend the functionality of the editor. However, it requires additional JavaScript programming which may be challenging.

To reduce the amount of work, you need to do to implement the typical scenarios, we have created a UI Framework. It helps you to define the behavior of the editor by modifying a JSON config + writing a few of one-liner JavaScripts instead of diving into a full-fledged JS development.

In this tutorial, we will show you how you can use the UI Framework to create an editor with the following functionality:

- Edit product designs.
- Change a design, e.g. by selecting a product option.
- Set a background, e.g. by selecting a thumbnail in an image list.
- When the user changes a background, you don't want to lose the progress the user made.


## Prerequisites

This tutorial assumes that you have already [installed the UI Framework](getting-started.md) and have a general idea of [parametrized configs](creating-parametrized-configs.md) and [dynamic expressions](dynamic-configs.md).

You can use examples of this tutorial in the **config** constant in the sample.

## DesignEditor widget

As you might learn by using the demo, to manipulate the Customer's Canvas editor content, you need to configure the editor and use so-called _commands_ in a widget config. Commands are the first-level elements of a widget's **params**, for example, for [`design-editor`](widgets/design-editor.md), this config looks as follows: 

```
{
    "widgets": [{
		"type": "design-editor",
		"name": "my-editor",
		"params": {
			"command1": { ... /* command1 params */ ... },
			"command2": { ... /* command2 params */ ... },
			// ... other commands.
		}
	}]
}
```

A command is triggered when the UI Framework detects changes in the config, i.e. if you refer to some option in one of its parameters. Other commands where no changes are detected are not triggered. If changes in several commands are detected, they are called in the same order as they go in the config.

## Initializing the editor

To load and initialize the editor, you must use the  [`initial`](widgets/design-editor-commands/initial.md) command. In this command, you specify a product design through the name of a state file, or an IDML/PSD file if you prefer to work with them directly. You can open the `bbq-invitation.psd` design and enable a simple editor mode as follows:

```
{
    "type": "design-editor",
    "name": "my-editor",
    "params": {
        "initial": {
            "productDefinition": {
                "surfaces": [{
                    "printAreas": [{
                        "designFile": "bbq-invitation"
                    }]
                }]
            },
            "editorConfig": {
                "initialMode": "SimpleOnly"
            }
        }
    }
}
```

Now, try to load the editor using this config. If everything is done correctly, you will see your design in the editor.

Let's take a look at other commands that you need to achieve the goal described above.

## Replacing a product page

You may want to not only edit the template but also allow your users to change it, for example, by switching the orientation using the radio buttons in the **Tool Panel**.

To implement this, you need to prepare your templates for different product orientation. They should have a similar structure and the same elements with the same names. This will allow the editor to save the user changes when switching the templates.

Now, let's add an [`option`](widgets/option.md) button, which will switch the templates.

```
{
	"type": "option",
	"name": "orientation",
	"title": "orientation",
	"params": {
		"type": "radio",
		"title": "Orientation",
		"values": [
			{ "title": "vertical" },
			{ "title": "horizontal" }
		]
	}
}
```

To change a template, you can use the [`setPrintArea` command](widgets/design-editor-commands/set-print-area.md). This command is an equivalent of IFrame API's [`setPrintAreas`](https://customerscanvas.com/docs/cc/customerscanvas.iframeapi.objectmodel.surface.setprintareas.htm) method. It takes the same input structure as you pass to the `initial` command to describe a design (e.g. another state ID name or an IDML/PSD file name) and loads it to the current or specified page (surface) without updating other surfaces.

In the editor's config, you can refer to the value of this option through its name (`orientation` in our case) as follows:

```
{
	"type": "design-editor",
	"name": "my-editor",
	"params": {
		"initial": { ... }, 
		"setPrintArea": {
			"data": {
				"designFile": "{{'cards/' + $['orientation']._.title}}"
			},
			"options": {
				"preserveUserChanges": true
			}
		}
	}
}
```

This command has `options` defining whether you want Customer's Canvas to merge new designs with the changes the user made or discard them. If you want to keep changes, then it runs some code under the hood that copies all new items to the new design, and if it detects items with the same names, it will copy their values to the appropriate items. You can refer to the description of [options here](https://customerscanvas.com/docs/cc/customerscanvas.iframeapi.objectmodel.surface.setprintareas.htm).

The `setPrintArea` command allows you to either change a single product page or replace the entire product in the editor. When you need to change a single page, use the `surfaceIndex` parameter. _**Note!** The `0` index corresponds to the first page._

```
{
	"type": "design-editor",
	"name": "my-editor",
	"params": {
		"initial": { ... }, 
		"setPrintArea": {
			"data": {
				"designFile": "{{'menu/' + $['weekday']._.title}}"
			},
			"surfaceIndex": 2,
			"options": {
				"preserveUserChanges": true
			}
		}
	}
}
```

This way, you can reload the template and transfer all changes made by the user.

The `setPrintArea` command transfers all layers, including the background. When you only need to change an image in the background, you can use the following command.

## Changing a background image

Unlike the previous command, instead of changing the entire design, `setBackground` receives a single image (JPEG, PDF, PNG) as an input. Under the hood, this command runs a code that finds a Background Container on a surface, removes the original image item from it, and replaces it with the specified image. It automatically enlarges it to fill the entire design. 

```
{
	"type": "design-editor",
	"name": "my-editor",
	"params": {
		"initial": { ... },
		"setBackground": 
			"url": "{{ $['bg']._.url }}"
		}
	}
}
```

The `url` property can be either a URL to the image or a path in the Customer's Canvas gallery. In the latter case, use the **public:** prefix as explained in [Customer's Canvas docs](https://customerscanvas.com/docs/cc/working-with-user-data.htm#setUserInfo). You can also use the `autoResize` or `toTile` properties to make the background image fill the entire design.

```
{
	"type": "design-editor",
	"name": "my-editor",
	"params": {
		"initial": { ... },
		"setBackground": 
			"url": "{{ 'public:' + 'themes/' + $['colors']._.props.themeName + '.pdf' }}",
			"autoResize": true
		}
	}
}
```

Since this command only affects the background item, no other elements are affected and the user's progress remains intact.

For more details, you can refer to the [`DesignEditor`](widgets/design-editor.md) topic.
