---
title: "Introducing Editors"
canonical: https://customerscanvas.com/docs/cc4/product-editors.htm
archived: true
applies_to:
  - product: "Customer's Canvas On-Premises"
  - product: "UI Framework"
    versions: ["1.x (legacy Product Editors; may differ)"]
  - product: "Design Editor"
    versions: ["4.4.25", "4.x (may differ)"]
---

**You’re viewing outdated documentation.** [View the latest Customer’s Canvas On-Premises documentation](https://customerscanvas.com/docs/on-premises/).

# Introducing Editors

**Applies to:** Customer's Canvas On-Premises; UI Framework 1.x (legacy Product Editors; may differ); Design Editor 4.4.25, 4.x (may differ) · **Archived documentation**
 
Customer's Canvas provides a powerful API for web-to-print solutions. You can easily integrate this API into any website or e-commerce platform no matter what server technology you use. On the other hand, some tasks - such as integration into e-commerce systems - are routine, and many of our customers have to implement very similar functionality over and over again.
 
To simplify this process, Aurigma has developed a new technology that helps connect Customer's Canvas with any e-commerce system with minimal effort. From a technical point of view, it is a series of JavaScript applications that we call *Product editors*. Unlike Customer's Canvas, which operates with PSD templates and images, a Product editor is a higher-level application that works with product options, attributes, variants, etc. It knows as much about the product as your e-commerce system.
 
Let us see how an e-commerce product editor works.
 
## Obtaining the Latest Product Editors
  
At the moment, the current Customer's Canvas distribution does not include Product editors. Please contact info@aurigma.com for the actual version of this editor. We will start publishing it on our website soon.
 
Also, you can [download a package](https://customerscanvas.com/docs/cc4/samples/editor-package.zip) containing assets, configuration data, a sample page, and the Customer's Canvas templates used in this sample page.
 
## Getting Started
  
You can find a fully-working sample in the `sample.html` file. Note that, to get it working with your Customer's Canvas instance, you should set the **customersCanvasUrl** property in this file to a URL to your Customer's Canvas instance. Also, if you did not copy our sample designs to your Customer's Canvas folder, make sure that the `data\product\simple-business-card.json` file refers to an existing PSD template.
 
```
{
    "id": 0,
    "sku": "DEFAULT-001",
    "name": "Business Card #1",
    "description": "A default product for demo.",
    "options": [],
    "price": 0.16,
    "attributes": [{
        "id": 0,
        "name": "Template",
        "value": "business-card/simple"
    }]
}
```
 
Here, the **value** property points to the PSD file relative to the `cc-data\ProductTemplates\designs` folder of your Customer's Canvas instance. Note, you should omit the `.psd` extension. In other words, it is the same syntax as you use to refer to PSD templates in Customer's Canvas.
 
Now, let us see how you can create such a webpage from scratch.
 
### Step 1. Prepare
 
The Product editor is loaded to the page using RequireJS. Code examples in this topic demonstrate how you can use this technology to load the Product editor.
 
Download RequireJS files from here:
 [http://requirejs.org/docs/download.html↗](http://requirejs.org/docs/download.html)
 
Put it into a folder on your server where you keep your JavaScript libraries. In addition, you need to put the `ecommerce-driver.js` file, enclosed with the Product editor package, to the same location.
 
At last, you must put the folder containing the Product editor files in a designated location (it may be located in the same folder or somewhere else on your server). We release new versions of the editors quite frequently, so it makes sense to organize each version in a separate subfolder of a root folder for all editors.
 
In our examples, we assume that you are using the following folder structure:
 
- `\editors\base-<version>\`
- `\assets\ecommerce-driver.js`
- `\assets\requirejs\require.js`
- `\sample.html`

### Step 2. Configure RequireJS
 
First, add a link to RequireJS to the page.
 
```
<script src="assets/requirejs/require.js"></script>
```
 
The following code allows RequireJS to know where to search for the editor modules.
 
```
require.config({
    baseUrl: '/assets',
    paths: { "editors": "/editors" }
});
```
 
Note, this should be executed before you try to load the editor. A good place to do this is the document load event handler.
 
After that, you can add some code that loads the editor to the page. It can be located on a button click event handler or just on the page load. The code that loads the editor looks like this:
 
```
require(['ecommerce-driver', 'editors/base-1.1.5/editor'], function (driver, editor) {
    // Define the Customer's Canvas URL.
    var settings = {
        customersCanvasUrl: "http://localhost:8181"
    };
    // The order data, which the editor returns.
    var restoreData = null;
    var quantity = 1;

    // Initialize the driver with a product model, editor instance, config,
    // data returned by the editor, and an item's quantity (when it is necessary).
    driver.init(productModel, editor, configParams, settings, restoreData, quantity);

    // Embed the editor into the specified DIV element.
    driver.products.current.renderEditor($("#aurigma-editor-root")[0]);

    // Define a callback, which is called when the user finishes editing.
    // You should insert the code which sends the product order to a shopping cart.
    driver.orders.current.onSubmit = function(data) {
        // This callback returns the hi-res URLs, preview images, and the data
        // used to restore the state of the editor.
        console.log(data);
    };
});
```
 
You can find descriptions of productModel and configParams in the following paragraphs. In this code, after loading the e-commerce driver and editor itself, the Product editor goes through the following basic steps:
 
1. **Initializing the driver** with the Customer's Canvas link, product model (including product options and attributes), and the editor configuration. In reality, you retrieve the model and configuration from your e-commerce database.
2. **Embedding the editor** into a webpage. You can provide an empty DIV element on either a visible area, hidden page, or modal dialog. 
```
    <div id="aurigma-editor-root"></div>
    ```
3. **Processing the results** returned to the **onSubmit** callback, which is called by the editor when the user finishes the product editing. In our example, we just display the data in the console, but in the real life application, it is the right place to create an order and attach this data to the user's shopping cart.

Now, let us see how these new objects can be operated: the e-commerce driver, product model, and editor configuration.
 
## The E-commerce Driver
  
The Product editor works with entities from your e-commerce system. If there were a single e-commerce system, then the editor could work with the data structure of this system directly. Since there is a number of e-commerce systems, and we did not want to create a separate editor for each of them, we designed an abstraction layer called e-commerce driver. This is similar to the other drivers that were designed to handle different devices in operating systems. Just how Windows does not work with a mouse directly and uses a driver to communicate with it, the Product editor talks with your Magento, WooCommerce, or Shopify through the e-commerce driver.
 
From the point of view of a developer integrating the Product editor with an e-commerce system, the role of the e-commerce driver is mainly to convert such entities like a product, options (or variants), specification attributes, order, etc. to the model supported by the Product editor.
 
In our example, the product model comes from a JSON file stored at `data\product\simple-business-card.json`. In your application, you might want to replace it with the data gathered from your e-commerce system. You just prepare a JSON structure, which we will describe in the next section, and pass it to the **driver.init** method as shown in the previous example.
 
Now, let us describe this JSON object in detail.
 
## The Product Model
  
The product editor accepts product models in the following form.
 
```
productModel = {
    id: 1234, // A unique identifier from your e-commerce system.
    sku: "P01234-172", // An alphanumeric code of the product.
    name: "Invitation 0001234", // A display name.
    price: 5.3, // A non-negative number specifying the product price.
    description: "...", // Information about the product.
    options: [
        // An array of options.
    ],
    attributes: [
        // An array of attributes.
    ]
}
```
 
These fields are pretty common and typically found in any e-commerce system. You may omit most of them. However, you may wonder what the difference between options and attributes is.
 
The **attributes** may also be referred to as specification attributes or custom fields in e-commerce systems. These are product properties, which cannot be changed by the user. For example, if you sell mobile phones, these properties can be the manufacturer name and phone model. In this case, the **attributes** array may look as follows:
 
```
attributes = [{
    id: 0, // The numeric ID of the attribute.
    name: "Make", // An attribute name.
    value: "Apple" // An attribute value.
},
{
    id: 0,
    name: "Model",
    value: "iPhone X"
}]
```
 
The **options** are order parameters, which the user is supposed to change (typically selected from a list of predefined values). For the example of mobile phones, they can be a phone color and add-ons like protective glass or a memory card. These user choices should be included into orders and may affect the order price. An object representing the options looks as follows:
 
```
options = [{
    id: 123, // The numeric ID of an option from your database.
    title: 'Color', // The option title used to refer to it in configs, etc.
    prompt: 'Choose a phone color', // The information for a customer, appears in UI.
    description: 'detailed description', // A more detailed description.
    required: true, // Whether the user must select some value to proceed.
    type: "color", // One of list | radio | checkbox | text | textarea | color | image.
    values: [
     // For list | radio | color | image | checkbox you pass a list of possible values.
    ],
    defaultValue: '' // For text and textarea you can pass a default value here.
}]
```
 
The **text** and **textarea** options take a single value and the default. Other options take the result from selecting from a list of the following objects.
 
```
{
    id: 12, // The number of the option value in the list.
    name: 'Silver', // A display name.
    price: 100, // A value changing the resulting price, can be negative.
    preselected: true // Whether this value is preselected.
}
```
 
The **color** and **image** options have additional properties, **color** (in CSS format) and **imageUrl**, correspondingly.
 
So, to make a product model, you need to retrieve the information related to a product from your e-commerce system and convert this information into a JSON object as described in the previous examples. Then, pass this object to the e-commerce driver.
 
What if a product model of your e-commerce system cannot be defined by this structure? For example, some systems use variants instead of options. These variants may represent all possible combinations of product options. In this case, you have to develop another e-commerce driver in the same way as we developed the Shopify driver, for example.
 
## The Editor Configuration
  
Along with the product model, the **driver.init** method accepts **configParams**, the editor's configuration. While the **productModel** describes the data from your e-commerce system, **configParams** defines the settings of the Product editor (and, in particular, Customer's Canvas).
 
Currently, Aurigma provides the **base-editor**. You can implement other Product editors, including, for example, pure Customer's Canvas, multipage editors, or an editor integrating the Web API of a photo uploader. Each Product editor has its own config structure.
 
Furthermore, in this topic, we explain the structure of the **base-editor**. Unless otherwise noted, the Product editor refers to the **base-editor**.
 
Let us describe **configParams** of the **base-editor**. This configuration has the following group of settings.
 
```
{
    productDefinition: {...}, // Product templates loaded into the editor.
    editorConfig: {...}, // The Customer's Canvas configuration.
    attributeNames: [], // The list of product attributes.
    conditions: [], // The association of options with actions to be performed when users switch the options.
    steps: {
        editor: {
            optionNames: [], // The option list you want to enable in the editor.
        }, 
        approve: {
            ...
        }    
    }, // The sequence of editing steps.
    language: 'en' // The localization language.
}
```
 
The productDefinition and editorConfig are the same structures that you pass to the Customer's Canvas Iframe API (to the [loadEditor](https://customerscanvas.com/docs/cc4/customerscanvas.iframeapi.loadeditor.htm.md) method). Other objects are explained in the following sections.
 
## References to a Product Model from the Configuration
  
Now, you can say "Ok, it is clear, I just need to define a configuration for a single product and pass a PSD template name with other product properties into this configuration." Actually, if you just hardcode a PSD filename to your configuration, it may become too cluttered because you have to create many similar JSON files. In addition, this can be hard to support if you need to add a property to a config because you have to update all your configs.
 
The Product editor allows you to have one configuration for a group of products, say, for a product category, and get the required data from your product model. This is implemented through product shortcuts. To use a shortcut, enclose a property or attribute in the `%` symbols.
 
```
productDefinition: {
    surfaces: ['%product.attributes.Template%']
}
```
 
When the editor processes this configuration, it gains the value of the **Template** attribute and replaces the string enclosed in the `%` symbols with this attribute value.
 
Note, you can use spaces and even non-ASCII symbols in shortcuts - just use the value you put in the **name** property of your **Attribute** object in the product model.
 
```
'%product.attributes.Front Template%'
```
 
In the same way, you can refer to the other elements of a product model from the **editorConfig** section. For example, if you have the **sku\_placeholder** text field in your design and want to paste a product SKU into this field, pass the shortcut to [userData](https://customerscanvas.com/docs/cc4/working-with-user-data.htm.md) as follows:
 
```
editorConfig: {
    autoLoadUserInfo: true,
    userData: {
        'sku_placeholder': '%product.sku%'
    }
}
```
 
## The attributeNames Section
  
The previous example illustrated how you can refer to product attributes using shortcuts, like **%product.attributes.AttributeName%**. However, this method has a shortcoming. Say, when you rename an attribute, you need to change this attribute name in every occurrence. To avoid this, add the **attributeNames** section to **configParams**, which allows for defining attributes as follows:
 
```
"attributeNames": {
    "frontTemplate": {
        "name": "CoolTemplate_Front",
        "settings": {
            "type": "design"
        }
    }
}
```
 
After that, you can refer to this attribute as follows:
 
```
"%product.attributes.#attributeNames.frontTemplate#%"
```
 
If you decide to rename such an attribute, you only have to do this in the **attributeNames** section.
 
Another purpose of this section is keeping the attribute's metadata. It may be useful if you build an admin panel for editing product attributes based on a config (like it is implemented in our nopCommerce plugin).
 
## The Customer's Canvas Configuration
  
If you are familiar with the Customer's Canvas API, you can skip this section. Otherwise, refer to the [Configuring Products](https://customerscanvas.com/docs/cc4/configuring-products.htm.md) topics and [Configuration Files](https://customerscanvas.com/docs/cc4/configuration.htm.md). As a quick reminder, you can refer to the use cases in this section.
 
### The Product Definition
 
To define a one-page design:
 
```
productDefinition = {
    surfaces: ["%product.attributes.#attributeNames.Template#%"]
};
```
 
To define a two-page design:
 
```
productDefinition = {
    surfaces: ["%product.attributes.Side 1%", "%product.attributes.Side 2%"]
};
```
 
To define a product with mockups:
 
```
productDefinition = {
    surfaces: [{
        printAreas: [{
            designFile: "%product.attributes.Template%"
        }],
        mockup: {
            // Set a foreground mockup, "RoundedCorners.psd".
            up: "RoundedCorners"
        }
    }]
};
```
 
Note, we have referred to a template through the attribute while the mockup is hardcoded. It is often convenient when you have the same mockup for all your products. If you would rather set different mockups for different products, a good idea would be to create a separate attribute for that.
 
To define mockups for 3D preview:
 
```
productDefinition = {
    surfaces: [{
        printAreas: [{
            designFile: "blank-design"
        }],
        mockup: {
            up: "%product.attributes.#attributeNames.Model#%/case-up",
            down: {
                previewMockupFiles: [
                    "%product.attributes.#attributeNames.Model#%/case-front-white",
                    "%product.attributes.#attributeNames.Model#%/case-3-4-white",
                    "%product.attributes.#attributeNames.Model#%/case-3d-white"
                ],
                mockupFile: "%product.attributes.#attributeNames.Model#%/case-white"
            }
        }
    }]
}
```
 
The scenarios this example shows are a bit different - if you have the same design file for all products (for example, a blank image), you can hardcode it rather than creating a separate attribute for it. However, our mockups depend on the phone model. We created the **Model** attribute and use it as a part of the path (for example, as a folder name). So you don't have to specify separate attributes for different perspectives of your preview images (as long as you follow the certain naming conventions of your mockup files).
 
### The Editor Configuration
 
**editorConfig** configures the editor for a single product. If all your products are the same, you can use the `clientConfig.json` file of your Customer's Canvas instance instead. However, in practice, you may need to fine-tune Customer's Canvas for each product category. Let us consider a number of configuration examples.
 
To enable the simple edit mode allowing for changing only the content of design elements:
 
```
editorConfig = {
    initialMode: "SimpleOnly"
};
```
 
To enable watermarks and display the **ObjectInspector** on the right side of the editor:
 
```
editorConfig = {
    watermark: {
        text: {
            text: "watermark",
            opacity: 0.5
        },
        visibility: {
            proof: true,
            canvas: true
        }
    },
    widgets: {
        ObjectInspector: {
            position: "Right"
        }
    }
};
```
 
To enable the **Logos**, **Backgrounds**, and **My Files** tabs in the **Gallery** and add the **Image** and **Background** buttons to the **Toolbox**:
 
```
editorConfig = {
    initialMode: "Advanced",
    widgets: {
        Toolbox: {
            buttons: [
                "Text",
                {
                    "translationKey": "Toolbox.ADD_IMAGE",
                    "translationKeyTitle": "Toolbox.TITLE_ADD_IMAGE",
                    "iconClass": "cc-icon-add-image",
                    "action": "Image",
                    "tabs": ["Logos", "My Files"]
                },
                {
                    "translationKey": "Toolbox.CHANGE_BACKGROUND",
                    "translationKeyTitle": "Toolbox.TITLE_CHANGE_BACKGROUND",
                    "iconClass": "cc_icon_background",
                    "action": "Background",
                    "tabs": ["Backgrounds", "My Files"]
                }
            ]
        },
        GalleryDialog: {
            "publicFolderName": "business-card",
            "defaultTab": "public",
            "tabs": [
                {
                    "name": "Backgrounds",
                    "type": "public",
                    "subFolderName": "business-card\\Backgrounds",
                    "categoriesEnabled": false,
                    "canEdit": false
                },
                {
                    "name": "Logos",
                    "type": "public",
                    "subFolderName": "business-card\\Logos",
                    "categoriesEnabled": false,
                    "canEdit": false
                },
                {
                    "name": "My Files",
                    "type": "user",
                    "categoriesEnabled": true,
                    "canEdit": true,
                    "canUpload": true
                }
            ]
        }
    }
};
```
 
To disable toolbars, rulers, and the **ObjectInspector**:
 
```
editorConfig = {
    initialMode: "SimpleOnly",
    canvas: {
        rulers: {
            "enabled": false
        }
    },
    widgets: {
        Toolbox: {
            disabled: true
        },
        BottomToolbar: {
            "snapLinesCheckboxEnabled": false,
            "gridCheckboxEnabled": false
        },
        ObjectInspector: {
            "isHidden": true
        },
        FinishButton: {
            "mode": "Disabled"
        }
    }
};
```
 
For more examples and the description of the Customer's Canvas Iframe API, you can refer to the [corresponding topics](https://customerscanvas.com/docs/cc4/customerscanvas.htm.md).
 
## Product Options
  
Options make the **base-editor** more than just a handy Customer's Canvas wrapper. By using them, the ordering process becomes more interactive. For example, users can select the shape of the product's edges and the editor immediately overlays a mockup visualizing such edges. Also, users can select a color theme and the product design automatically applies this color.
 
You can find a product and config example that illustrate working with product options in the `data\product\business-card-options.json` and `data\config\business-card-options.json` files. In this topic, you can find details on how to create them yourself.
 
The first thing you should do is pass the necessary options to the product model as explained above.
 
However, the **base-editor** does not use all these options by default. You may want to prevent Customer's Canvas from showing certain options in its interface. That's why it is necessary to explicitly list the options you want to show.
 
To do this, use the **steps.editor.optionNames** section. It holds the names of the options that are available in the product model. For example, to display the **Paper Type** and **Cut Corners** options, list their names in this array.
 
```
"steps": {
    "editor": {
        "optionNames": [ "Paper Type", "Cut Corners" ]
    }
}
```
 
You can find more details about the **steps** object further in this topic.
 
Now, if you reload the webpage containing these options, you can see that they are displayed, but when you switch these options, nothing happens. To define what actions **base-editor** should perform, you have to configure conditions. You can set up **conditions** and actions as follows:
 
```
conditions: [{
    // It will trigger only when the Paper Type is changed (ignores Cut Corners). 
    // If you want to trigger it for both options, list both option names here. 
    watch: ['Paper Type'],
    // Use an optional condition to filter out options values not listed below.
    condition: "'Paper Type'='Linen' OR 'Paper Type'='Kraft'", 
    // Run this action based on the watch and condition.
    action: 'change-mockup',
    // The mockup filename can be linen.png, kraft.png, or other,
    // depending on the selected option.
    arguments: {
        "mockup": {
            "down": {
                "mockupFile": "business-card/{Paper Type}"
            }
        },
        "surface": "current"
    } 
}]
```
 
These actions represent filenames of JS files. You can find the predefined actions in the `editors\base-<version>\actions` folder. To implement your custom actions, refer to the `readme.md` file in the same folder.
 
Note, in the argument names you may refer to current values of options using the curly brackets. This way, if you give the same names for your mockups as the option names, you can easily configure switching mockups when the user changes the option value.
 
## Editing Steps
  
The Product editor allows you to split the editing procedure into a sequence of screens, or steps. For example, in the **base-editor**, there are two steps - the **editor** and **approve**. You can configure them as follows:
 
```
"steps": {
    "editor": {
        "showPrice": false,
        "optionNames": [
            "Color"
        ]
    },
    "approve": {
        "confirmationMode": "dialog",
        "preview": {
            "width": 216,
            "height": 360
        },
        "magnifier": {
            "enable": true,
            "type": "glass"
        }
    }
}
```
 
In the **editor** step, the **showPrice** property hides the price box from this page; **optionNames** enables the **Color** option in the editor. In the **approve** step, the base-editor enables the confirmation dialog and displays proof images of 216 x 360 pixels. The **magnifier** object allows for enlarging proof images when you point to them using the mouse.
 
## Languages
  
The user interface of Product editors can be multilingual. The file containing all text strings is located in the `editors\base-<version>\locales.json` file. It already includes some default languages such as **en**, **nl**, **de**, **fr**, and **ru**. To add a new language, such as Spanish, add the **es** key, paste all string resources from another language into it, and then translate them.
 
To specify the desired language, add this line to the config:
 
```
language: 'es'
```
 
## See Also
  
### Manual
 
- [Integration with E-commerce Overview](https://customerscanvas.com/docs/cc4/integration-with-e-commerce.htm.md)
- [Working with User Data](https://customerscanvas.com/docs/cc4/working-with-user-data.htm.md)
- [Configuring Products](https://customerscanvas.com/docs/cc4/configuring-products.htm.md)
- [Configuration Files](https://customerscanvas.com/docs/cc4/configuration.htm.md)

### IFrame API Reference
 
- [IframeApi Module](https://customerscanvas.com/docs/cc4/customerscanvas.iframeapi.htm.md)
- [loadEditor](https://customerscanvas.com/docs/cc4/customerscanvas.iframeapi.loadeditor.htm.md)

### Downloads
 
- [Product editor's package](https://customerscanvas.com/docs/cc4/samples/editor-package.zip)
