DesignEditor
=====

A widget that integrates Design Editor 6 or Design Editor 5 into the multi-step editor. As usual, it is the key widget of the editor and it is heavily parametrized by using the [dynamic configs](../dynamic-configs.md).

_**Note!** If you use an earlier version of Customer's Canvas, you need to integrate the [canvas](canvas.md) widget._

To use this widget, you should be familiar with the [Customer's Canvas IFrame API](https://customerscanvas.com/docs/cc/IframeApi-introduction.htm) and the [basics of its configuration](https://customerscanvas.com/docs/cc/client-config.htm).

## General info

- **type**: `design-editor`

## DesignEditor vs Canvas

The parameters of **DesignEditor** are as compatible as possible with the **Canvas**. When you need to transfer the old config to the new editor, you can just change the widget type from `canvas` to `design-editor`. However, these widgets have some differences.

## Config structure

This widget does not have its own properties. Instead, all its properties are organized in so-called _commands_ to manage the Design Editor. 

A command is a first-level property of a `design-editor` config. The following commands are supported:

- [`initial` - initialization (required)](design-editor-commands/initial.md)
- [`changeMockup` - replaces mockups stored in CC backend](design-editor-commands/change-mockup.md)
- [`setRemoteMockup` - replaces mockups by specified URL](design-editor-commands/set-remote-mockup.md)
- [`setPrintArea` - loads another template on a specific surface](design-editor-commands/set-print-area.md)
- [`setBackground` - replaces background image](design-editor-commands/set-background.md)
- [`setTheme` - changes a theme](design-editor-commands/set-theme.md)
- [`modifyItems` - modifies elements inside the editor](design-editor-commands/modify-items.md)
- [`updateContainerSettings` - updates spot colors and textures](design-editor-commands/update-container-settings.md)
- [`updateItems` - updates design elements](design-editor-commands/update-items.md)


You may omit any command except `initial`.

Each command has its own properties that you are supposed to make dynamic. As soon as the editor detects changes in a widget that you are referring to in a particular command, only this command is executed. For example, you may have the following commands:

``` json
{
    "name": "editor",
    "type": "design-editor",
    "params": {
        "initial": { ... },
        "setBackground": {
            "url": "{{$['gallery']._.url}}"
        },
        "changeMockup": {
            "data": {
                "mockup": {
                    "down": "{{$['color']._.mockupName}}"
                }
            }
        }
    }
}
```

Imagine that the user chooses an alternative background in the **gallery** widget. In this case, only the `setBackground` command will work, neither `initial` nor `changeMockup` will be re-applied (which would cause it to reload all of the design and result in unnecessary flickering). 

This way, you are using these commands to associate the Design Editor with different widgets and perform various actions whenever you change something. 


## How to have Customer's Canvas generate a result

The most typical scenario is to organize the editor into several steps, where, for example, the first step is the Design Editor, and the next step is an approval page where you need to display the result and pass the hi-res PDF out of the editor.

To accomplish this, you need to tell Customer's Canvas to generate a result when you leave the design step and grab the output in the config of the approval step. 

To save the result, you can call these methods:

- `getHiResImages(previewWidth, previewHeight, stateId?)` - an equivalent to [editor.finishProductDesign](https://customerscanvas.com/docs/cc/customerscanvas.iframeapi.editor.finishproductdesign.htm) from the IFrame API.
- `getProofImages(previewWidth, previewHeight)` - an equivalent to [editor.getProofImages](https://customerscanvas.com/docs/cc/customerscanvas.iframeapi.editor.getproofimages.htm) from the IFrame API.
- `saveProduct(stateId?)` - an equivalent to [editor.saveProduct](https://customerscanvas.com/docs/cc/customerscanvas.iframeapi.editor.saveproduct.htm) from the IFrame API. 

After they finish working, they will return the results to the following properties of the widget: 

- `proofImageUrls`
- `hiResUrls`
- `stateId`
- `userId`
- `userChanges`

The `getHiResImages` method changes all these properties, whereas `getProofImages` changes only `proofImageUrls`, and `saveProduct` - only `stateId` and `userId`.

The `proofImageUrls` and `hiResUrls` properties represent arrays of the same structure as returned by the IFrame API. See the documentation for the appropriate methods in the IFrame API for more details. 

You may wonder where to call the `getHiResImages` method. As usual, you can do it in the `onActivate` handler of a step where you need to use the results, or in `onClick` of the [button widget](button.md).

Due to the declarative nature of a JSON config, the `get`_`XXX`_ methods do not return any usable results. Instead, they tell Customer's Canvas to initialize the appropriate property. When this happens, the dynamic config engine is notified about changes and the config is re-applied.

### Example

``` json
{
    "widgets": [
        {
            "name": "editor",
            "type": "design-editor",
            "params": {
                "initial": { ... },
                ... // other commands
            }
        },
        {
            "name": "preview-image",
            "type": "image-carousel",
            "params": {
                "containerColor": "#fff",
                "images": [{ "url": "{{$['editor'].proofImageUrls[0][0]}}" }]
            }
        }
    ],
    "steps": [
        {
            "name": "design",
            "title": "Design",
            "mainPanel": {"name":"editor"} 
        },
        {
            "name": "approve",
            "title": "Preview",
            "mainPanel": {"name":"preview-image"},
            "onActivate": "{{#function $['editor'].getHiResImages(800,800)}}" 
        },
    ]
}
```


## Working with product pages

In **DesignEditor**, you can add, remove, switch surfaces and change surface names:

- `addSurface(surface, position)` method - an equivalent to [product.addSurface](https://customerscanvas.com/docs/cc/customerscanvas.iframeapi.objectmodel.product.addsurface.htm) from the IFrame API.
- `addSurfaces(surfaces, position)` method - an equivalent to [product.addsurfaces](https://customerscanvas.com/docs/cc/customerscanvas.iframeapi.objectmodel.product.addsurfaces.htm) from the IFrame API.
- `removesurface(position)` method - an equivalent to [product.removesurface](https://customerscanvas.com/docs/cc/customerscanvas.iframeapi.objectmodel.product.removesurface.htm) from the IFrame API.
- `switchSurfaceTo(surfaceIndex)` method - to change a product page in the Design Editor.
- `updateCurrentSurfaceName()` method and `currentSurfaceName` property - to invalidate and get the current surface name.

### Example

``` json
{
    "widgets": [
        {
            "name": "editor",
            "type": "design-editor",
            "params": {
                "initial": { ... },
                ... // other commands
            }
        },
        {
            "name": "add-page-button",
            "type": "button",
            "params": {
              "text": "Add Page",
              "onClick": [
                "{{ #function $['editor'].addSurface({ width: 612, height: 436 }) }}"
              ]
            }
        }
    ],
    "steps": [
        {
            "name": "design",
            "title": "Design",
            "mainPanel": {"name": "editor"},
            "bottomPanel": {"name": "add-page-button"}
        },
        ...
    ]
}
```


## Variable data printing

You can use the `getVariableData()` method to detect what particular variable fields are used in the design. It is used to build an array of names and values of variable fields:

```
{
    name: string;
    value: string;
}
```

The result is available in the `variableData` property.

For interpolation placeholders in the `{{Name}}` format, you can use `replaceInterpolationPlaceholders()` to transform them into in-string placeholders.

## Working with product tags

The `getTags()` and `setTags()` methods allow you to read and write custom data (such as Variable Data) to the state file.

`getTags()` returns a promise with a dictionary `[key: string]: any;`. The result is available in the `tags` property. `setTags()` takes either an object, an array, or a string.

_**Note!** The `setTags` method resets existing product tags. If you need to add a tag to the current set of tags, you first need to get the tags, then write them and the desired value._


## DepositPhotos details

The `getDepositPhotos()` method returns details about images from DepositPhotos in a promise with an array of such objects:

```
{
    imageId: string;
    depositPhotosId: string;
}
```

The result is available in the `depositPhotos` property.


## Other methods and properties 

For most use cases, the methods and properties described above are enough. However, for more complicated configs (e.g. related to Variable Data Printing), you may be interested in using additional members: 

- `getAllItems()` method and `allItems` property - to read info about items in the Design Editor.
- `applyViewerSettings(params)` method - to change the zoom level of the editor.
- `openAssetManager(itemName)` method - to open the **Asset Manager** for the specified item.
- `modifiedItem` property - to find the last edited item in the Design Editor.
