topol-editor

TOPOL.io plugin

Welcome to TOPOL.io Plugin Documentation

This document describes how to use TOPOL.io plugin for embedding e-mail editor into your app. More information can be found at TOPOL.io.

TOPOL.io editor communicates with your app through a given set of endpoints. You can set these endpoints in options when you instantiate the editor. Basically, all you need to do is handle the load and save of the template and image upload.

The installation will take you only few a minutes.

Table of content

  1. Initializing the plugin A prototype in 3 minutes.

  2. Plugin configuration Configure your plugin: languages, theme, layout, merge tags, special links, fonts…

  3. Save and load options How to save and load your templates.

  4. Custom file manager Use file manager your users already know.

  5. Storage options Custom file storage.

  6. Custom API endpoints Advanced options.

  7. Miscellaneous Domains used by TOPOL.io plugin.

Initializing the plugin

Generate your API key in Settings / Plugin in your account at TOPOL.io:

API key

As token name, you can set any name (usually the name of your project). As a token domain, you have set the domain where you want to run our plugin, examples:

topol.io
www.topol.io
localhost:563295

The API key is always connected with given domains and will not work on a different domain. If you set the domain for example to topol.io the API key will be working on all subdomains of topol.io (like one.topol.io, two.topol.io).

Once you get your API key, first, insert this HTML within your application:

    <div id="app"></div>

This is where the plugin will be shown.

Then, insert this within your file with plugin implementation:

<script>
// Plugin Settings
var TOPOL_OPTIONS = {
            id: "#app",
            authorize: {
                apiKey: "Your Api Key",
                userId: "User ID",
            },
            templateId: 1
        };

// Plugin script
</script>

<script src="https://d5aoblv5p04cg.cloudfront.net/editor/loader/build.js" type="text/javascript" />

<script>
// Plugin start
TopolPlugin.init(TOPOL_OPTIONS);
</script>

You need to provide your API Key, current User ID and a template ID.

apiKey - Your API key. You can generate your account in Settings / Plugin.

userId - UserId is ID of your user (you will not find it in our app, just use any ID you want). UserID is an alphanumeric string (it can contain letters, numbers, _ or -) and it identifies the unique user of Your app and allows the plugin to load resources for that user (e.g. images). It will be counted as a unique user for monthly billing purposes.

templateId - Unique ID of a template being edited. To create new template just use any ID you want.

React and AngularJS

When using frameworks like React and AngularJS as SPA (Single Page Application), every time when hiding the editor, you should use the TopolPlugin.destroy() function to end the editor:

TopolPlugin.destroy()

When opening again, inicialize the editor with TopolPlugin.init(TOPOL_OPTIONS).

Plugin Configuration

You can configure the plugin for your needs with providing specific configuration within the TOPOL_OPTIONS variable.

This is what You need for the basic configuration:

    var TOPOL_OPTIONS = {
            id: "#app",
            authorize: {
                apiKey: "Your Api Key",
                userId: "User ID",
            },
            language: "en",
            templateId: 1,
            callbacks: {
              onSaveAndClose: function(json, html) {
                // HTML of the email
                console.log(html);
                // JSON object of the email
                console.log(json); 
                // Implement your own close callback
                // Data variable contains the response data of the save request
              },
              onSave: function(json, html) {
                // HTML of the email
                console.log(html);
                // JSON object of the email
                console.log(json);
              },
            }
        };

Here is the list of all possible options:

    var TOPOL_OPTIONS = {
            id: "#app",
            authorize: {
                apiKey: "Your Api Key",
                userId: "User ID",
            },
            language: "en",
            templateId: 1, // Not required, if not provided the editor will wait for the "TopolPlugin.load(json)" function call to load the template
            removeTopBar: true, // Hides the top bar of the email editor
            light: false, // set the editor theme to be light
            customFileManager: true, // sets the build in file manager to be disabled and change to call the callbacks provided below
            mergeTags: [
              { name: 'Merge tags', // Group name 
                items: [ 
                  { value: "*|FIRST_NAME|*", // Text to be inserted
                    text: "First name", // Shown text in the menu
                    label: "Customer's first name" // Shown description title in the menu
                  },
                  { value: "*|LAST_NAME|*",
                    text: "Last name",
                    label: "Customer's last name"
                  }
                ]},{
                name: 'Special links', // Group name 
                items: [ 
                  { value: "<a href=\"*|UNSUBSCRIBE_LINK|*\">Unsubscribe</a>",
                    text: "Unsubscribe",
                    label: "Unsubscribe link"
                  },
                  { value: "<a href=\"*|WEB_VERSION_LINK|*\">Web version</a>",
                    text: "Web version",
                    label: "Web version link"
                  }
                ]},{
                name: 'Special content', // Group name 
                items: [ 
                  { value: "For more details, please visit our <a href=\"https://www.shop.shop\">e-shop</a>!",
                    text: "Visit our site",
                    label: "Call to action"
                  }
                ]
              }
            ],
            googleFonts: [  // List of google fonts to load
                'Roboto',
                'K2D',
                'Mali'
            ],
            fonts: [ // List of all font shown in select box
                {
                    'label': 'Roboto', // Label shown to user
                    'style': 'Roboto, Tahoma, sans-serif' // CSS style applied with font selected
                },
                {
                    'label': 'K2D',
                    'style': 'K2D'
                },
                {
                    'label': 'Mali',
                    'style': 'Mali'
                }
            ],
            savedBlocks: [
              {
                id: 1,
                name: 'My saved block 001',
                img: 'src to my img', // The editor shows only name or img (img if both set)
                definition: [{ "tagName": "mj-section", "attributes": { "full-width": false, "padding": "9px 0px 9px 0px", "background-color": "#000000" }, "type": null, "children": [{ "tagName": "mj-column", "attributes": { "width": "33.333333%", "vertical-align": "top" }, "children": [{ "tagName": "mj-social", "attributes": { "display": "facebook:url twitter:url google:url", "padding": "10px 10px 10px 30px", "text-mode": "false", "icon-size": "25px", "base-url": "https://s3-eu-west-1.amazonaws.com/ecomail-assets/editor/social-icos/simplewhite/", "facebook-href": "https://www.facebook.com/PROFILE", "facebook-icon-color": "none", "facebook-alt": "Sdílet", "twitter-href": "https://www.twitter.com/PROFILE", "twitter-icon-color": "none", "twitter-alt": "", "google-href": "https://plus.google.com/PROFILE", "google-icon-color": "none", "google-alt": "", "instagram-icon-color": "none", "linkedin-icon-color": "none", "align": "left", "youtube-icon-color": "none", "youtube-alt": "", "youtube-icon": "https://s3-eu-west-1.amazonaws.com/ecomail-assets/editor/social-icos/simplewhite/youtube.png", "youtube-href": "https://www.youtube.com", "containerWidth": 200 }, "uid": "H1lqIiX4lm" }], "uid": "SJ3I0XVx7" }, { "tagName": "mj-column", "attributes": { "width": "33.333333%", "vertical-align": "top" }, "children": [{ "tagName": "mj-image", "attributes": { "src": "https://storage.googleapis.com/jan50/blackberrylogo.png", "padding": "19px 10px 10px 10px", "alt": "", "href": "", "containerWidth": 200, "width": 100, "widthPercent": 50 }, "uid": "rkEyL-HeQ" }], "uid": "r1e280m4xQ" }, { "tagName": "mj-column", "attributes": { "width": "33.333333%", "vertical-align": "top" }, "children": [{ "tagName": "mj-spacer", "attributes": { "height": 15, "containerWidth": 200 }, "uid": "rJfqLiXEgm" }], "uid": "B1W380QVxX" }], "layout": 1, "backgroundColor": "", "backgroundImage": "", "paddingTop": 0, "paddingBottom": 0, "paddingLeft": 0, "paddingRight": 0, "uid": "rkqIjQNe7" }]
              }
            ],
            premadeBlocks: {
              'headers': [
                {
                    'img': 'url', // Image url
                    'definition': [{"tagName":"mj-section","attributes":{"full-width":false,"padding":"9px 0px 9px 0px","background-color":"#000000"},"type":null,"children":[{"tagName":"mj-column","attributes":{"width":"33.333333%","vertical-align":"top"},"children":[{"tagName":"mj-social","attributes":{"display":"facebook:url twitter:url google:url","padding":"10px 10px 10px 30px","text-mode":"false","icon-size":"25px","base-url":"https://s3-eu-west-1.amazonaws.com/ecomail-assets/editor/social-icos/simplewhite/","facebook-href":"https://www.facebook.com/PROFILE","facebook-icon-color":"none","facebook-alt":"Sdílet","twitter-href":"https://www.twitter.com/PROFILE","twitter-icon-color":"none","twitter-alt":"","google-href":"https://plus.google.com/PROFILE","google-icon-color":"none","google-alt":"","instagram-icon-color":"none","linkedin-icon-color":"none","align":"left","youtube-icon-color":"none","youtube-alt":"","youtube-icon":"https://s3-eu-west-1.amazonaws.com/ecomail-assets/editor/social-icos/simplewhite/youtube.png","youtube-href":"https://www.youtube.com","containerWidth":200},"uid":"H1lqIiX4lm"}],"uid":"SJ3I0XVx7"},{"tagName":"mj-column","attributes":{"width":"33.333333%","vertical-align":"top"},"children":[{"tagName":"mj-image","attributes":{"src":"https://storage.googleapis.com/jan50/blackberrylogo.png","padding":"19px 10px 10px 10px","alt":"","href":"","containerWidth":200,"width":100,"widthPercent":50},"uid":"rkEyL-HeQ"}],"uid":"r1e280m4xQ"},{"tagName":"mj-column","attributes":{"width":"33.333333%","vertical-align":"top"},"children":[{"tagName":"mj-spacer","attributes":{"height":15,"containerWidth":200},"uid":"rJfqLiXEgm"}],"uid":"B1W380QVxX"}],"layout":1,"backgroundColor":"","backgroundImage":"","paddingTop":0,"paddingBottom":0,"paddingLeft":0,"paddingRight":0,"uid":"rkqIjQNe7"} // MJML JSON
                    ]
                }]
            },
            sendTestEmail: true, // Hides the send test email input & button if false
            // URL or Callback when clicked on Save & close
            callbacks: {
                onSaveAndClose: function(json, html) {
                    // HTML of the email
                    console.log(html);
                    // JSON object of the email
                    console.log(json); 
                    // Implement your own close callback
                    // Data variable contains the response data of the save request
                },
                onSave: function(json, html) {
                    // HTML of the email
                    console.log(html);
                    // JSON object of the email
                    console.log(json);
                },
                onTestSend: function(email, json, html) {
                    // HTML of the email
                    console.log(html);
                    // JSON object of the email
                    console.log(json);
                    // Email of the recipient
                    console.log(email);
                    // Callback when send test email button is clicked
                },
                onOpenFileManager: function() {
                    // Implement your own file manager open callback
                },
                onAutoSave(json) {
                    // Called when the editor decides that it needs an autosave. Mostly when the user makes a change and does not save it immediately.
                    console.log(json);
                },
                onBlockSave(json) {
                  var name = window.prompt('Enter block name:')
                    if (name !== null) {
                        console.log('saving block', json)
                    }
                },
                onBlockRemove(id) {
                    if (window.confirm('Are you sure?')) {
                        console.log('removing block', id)
                    }
                },
                onBlockEdit(id) {
                    var name = window.prompt('Block name:', 'My block 001')
                    if (name !== null) {
                        console.log('saving edited block', id)
                    }
                }
            },
            api: {
                IMAGE_UPLOAD: "/images/upload",
                // Your own endpoint for uploading images
                FOLDERS: "/images/folder-contents"
                // Your own endpoint for getting contents of current folder
            }
        };

Here is the list of all plugin functions:

    TopolPlugin.init(TOPOL_OPTIONS);
    TopolPlugin.load('json-template'); // To load JSON format use this load function with the JSON template. STRING FORMAT
    TopolPlugin.save(); // To force the save -> the onSave callback will be called with the JSON and HTML of the template
    TopolPlugin.togglePreview(); // Toggles the mode of Preview
    TopolPlugin.chooseFile('http://url.to/picture.png'); // When the onOpenFileManager is called, it is awaiting to call this function with the url of the chosen file.

    // Sets the saved blocks - this should be called with updated list of saved blocks after all actions: onBlockSave, onBlockRemove, onBlockEdit to update the editor with the updated information.
    TopolPlugin.setSavedBlocks([
            {
                'id': 11,
                'name': 'My saved block - by setSavedBlocks',
                'definition': [{ "tagName": "mj-section", "attributes": { "full-width": false, "padding": "9px 0px 9px 0px", "background-color": "#000000" }, "type": null, "children": [{ "tagName": "mj-column", "attributes": { "width": "33.333333%", "vertical-align": "top" }, "children": [{ "tagName": "mj-social", "attributes": { "display": "facebook:url twitter:url google:url", "padding": "10px 10px 10px 30px", "text-mode": "false", "icon-size": "25px", "base-url": "https://s3-eu-west-1.amazonaws.com/ecomail-assets/editor/social-icos/simplewhite/", "facebook-href": "https://www.facebook.com/PROFILE", "facebook-icon-color": "none", "facebook-alt": "Sdílet", "twitter-href": "https://www.twitter.com/PROFILE", "twitter-icon-color": "none", "twitter-alt": "", "google-href": "https://plus.google.com/PROFILE", "google-icon-color": "none", "google-alt": "", "instagram-icon-color": "none", "linkedin-icon-color": "none", "align": "left", "youtube-icon-color": "none", "youtube-alt": "", "youtube-icon": "https://s3-eu-west-1.amazonaws.com/ecomail-assets/editor/social-icos/simplewhite/youtube.png", "youtube-href": "https://www.youtube.com", "containerWidth": 200 }, "uid": "H1lqIiX4lm" }], "uid": "SJ3I0XVx7" }, { "tagName": "mj-column", "attributes": { "width": "33.333333%", "vertical-align": "top" }, "children": [{ "tagName": "mj-image", "attributes": { "src": "https://storage.googleapis.com/jan50/blackberrylogo.png", "padding": "19px 10px 10px 10px", "alt": "", "href": "", "containerWidth": 200, "width": 100, "widthPercent": 50 }, "uid": "rkEyL-HeQ" }], "uid": "r1e280m4xQ" }, { "tagName": "mj-column", "attributes": { "width": "33.333333%", "vertical-align": "top" }, "children": [{ "tagName": "mj-spacer", "attributes": { "height": 15, "containerWidth": 200 }, "uid": "rJfqLiXEgm" }], "uid": "B1W380QVxX" }], "layout": 1, "backgroundColor": "", "backgroundImage": "", "paddingTop": 0, "paddingBottom": 0, "paddingLeft": 0, "paddingRight": 0, "uid": "rkqIjQNe7" }]
            },
            {
                'id': 12,
                'img': 'https://d5aoblv5p04cg.cloudfront.net/editor/blocks/menu1.jpg',
                'definition': [{ "tagName": "mj-section", "attributes": { "full-width": false, "padding": "9px 0px 9px 0px", "background-color": "#000000" }, "type": null, "children": [{ "tagName": "mj-column", "attributes": { "width": "33.333333%", "vertical-align": "top" }, "children": [{ "tagName": "mj-social", "attributes": { "display": "facebook:url twitter:url google:url", "padding": "10px 10px 10px 30px", "text-mode": "false", "icon-size": "25px", "base-url": "https://s3-eu-west-1.amazonaws.com/ecomail-assets/editor/social-icos/simplewhite/", "facebook-href": "https://www.facebook.com/PROFILE", "facebook-icon-color": "none", "facebook-alt": "Sdílet", "twitter-href": "https://www.twitter.com/PROFILE", "twitter-icon-color": "none", "twitter-alt": "", "google-href": "https://plus.google.com/PROFILE", "google-icon-color": "none", "google-alt": "", "instagram-icon-color": "none", "linkedin-icon-color": "none", "align": "left", "youtube-icon-color": "none", "youtube-alt": "", "youtube-icon": "https://s3-eu-west-1.amazonaws.com/ecomail-assets/editor/social-icos/simplewhite/youtube.png", "youtube-href": "https://www.youtube.com", "containerWidth": 200 }, "uid": "H1lqIiX4lm" }], "uid": "SJ3I0XVx7" }, { "tagName": "mj-column", "attributes": { "width": "33.333333%", "vertical-align": "top" }, "children": [{ "tagName": "mj-image", "attributes": { "src": "https://storage.googleapis.com/jan50/blackberrylogo.png", "padding": "19px 10px 10px 10px", "alt": "", "href": "", "containerWidth": 200, "width": 100, "widthPercent": 50 }, "uid": "rkEyL-HeQ" }], "uid": "r1e280m4xQ" }, { "tagName": "mj-column", "attributes": { "width": "33.333333%", "vertical-align": "top" }, "children": [{ "tagName": "mj-spacer", "attributes": { "height": 15, "containerWidth": 200 }, "uid": "rJfqLiXEgm" }], "uid": "B1W380QVxX" }], "layout": 1, "backgroundColor": "", "backgroundImage": "", "paddingTop": 0, "paddingBottom": 0, "paddingLeft": 0, "paddingRight": 0, "uid": "rkqIjQNe7" }]
            }
        ])

Supported Languages

List of all currently supported languages:

Country Language Code
English en
French fr
Portuguese pt
Spanish es
Japanese jp
Chinese zh
Russian ru
Turkish tr
German de
Swedish se
Dutch nl
Italian it
Finnish fin
Romanian ro
Czech cs
Polish pl
Korean ko
Vietnamese vi
Hebrew iw

It’s easy to add another language. Feel free to contact us (get@topol.io).

Merge tags, special links or special content provide an easy way to insert text snippets from within the text editor. You will find it in the toolbar of the text feature:

Merge tags, special links...

Code example:

mergeTags: [
              { name: 'Merge tags', // Group name 
                items: [ 
                  { value: "*|FIRST_NAME|*", // Text to be inserted
                    text: "First name", // Shown text in the menu
                    label: "Customer's first name" // Shown description title in the menu
                  },
                  { value: "*|LAST_NAME|*",
                    text: "Last name",
                    label: "Customer's last name"
                  }
                ]},{
                name: 'Special links', // Group name 
                items: [ 
                  { value: "<a href=\"*|UNSUBSCRIBE_LINK|*\">Unsubscribe</a>",
                    text: "Unsubscribe",
                    label: "Unsubscribe link"
                  },
                  { value: "<a href=\"*|WEB_VERSION_LINK|*\">Web version</a>",
                    text: "Web version",
                    label: "Web version link"
                  }
                ]},{
                name: 'Special content', // Group name 
                items: [ 
                  { value: "For more details, please visit our <a href=\"https://www.shop.shop\">e-shop</a>!",
                    text: "Visit our site",
                    label: "Call to action"
                  }
                ]
              }
            ],

Custom Google Fonts

You can define two options to customize font loading and selection. To load Google Fonts use the googleFonts options. To update the select box user sees, update the fonts option.


googleFonts: [  // List of google fonts to load
                'Roboto',
                'K2D',
                'Mali'
            ],
            fonts: [ // List of all font shown in select box
                {
                    'label': 'Roboto', // Label shown to user
                    'style': 'Roboto, Tahoma, sans-serif' // CSS style applied when font selected
                },
                {
                    'label': 'K2D',
                    'style': 'K2D'
                },
                {
                    'label': 'Mali',
                    'style': 'Mali'
                }
            ],

When defining the style option of a font, please keep in mind that font names with space (two or more words), needs to be inside double brackets, for ex. '"Verdana Pro", sans-serif'.

Premade blocks

Premade blocks are used to enable users to use prepared parts of the email. For ex. headers or footers.

You can define your own premade blocks with option premadeBlocks on the TOPOL_OPTIONS object.

You can hide premade blocks and the premade block button using premadeBlocks: false.

premadeBlocks: {
              'headers': [
                {
                    'img': 'url', // Image url, for best experience use width > 330 px
                    'name': 'Premade header 1', // Or name if not image available
                    'definition': [{"tagName":"mj-section","attributes":{"full-width":false,"padding":"9px 0px 9px 0px","background-color":"#000000"},"type":null,"children":[{"tagName":"mj-column","attributes":{"width":"33.333333%","vertical-align":"top"},"children":[{"tagName":"mj-social","attributes":{"display":"facebook:url twitter:url google:url","padding":"10px 10px 10px 30px","text-mode":"false","icon-size":"25px","base-url":"https://s3-eu-west-1.amazonaws.com/ecomail-assets/editor/social-icos/simplewhite/","facebook-href":"https://www.facebook.com/PROFILE","facebook-icon-color":"none","facebook-alt":"Sdílet","twitter-href":"https://www.twitter.com/PROFILE","twitter-icon-color":"none","twitter-alt":"","google-href":"https://plus.google.com/PROFILE","google-icon-color":"none","google-alt":"","instagram-icon-color":"none","linkedin-icon-color":"none","align":"left","youtube-icon-color":"none","youtube-alt":"","youtube-icon":"https://s3-eu-west-1.amazonaws.com/ecomail-assets/editor/social-icos/simplewhite/youtube.png","youtube-href":"https://www.youtube.com","containerWidth":200},"uid":"H1lqIiX4lm"}],"uid":"SJ3I0XVx7"},{"tagName":"mj-column","attributes":{"width":"33.333333%","vertical-align":"top"},"children":[{"tagName":"mj-image","attributes":{"src":"https://storage.googleapis.com/jan50/blackberrylogo.png","padding":"19px 10px 10px 10px","alt":"","href":"","containerWidth":200,"width":100,"widthPercent":50},"uid":"rkEyL-HeQ"}],"uid":"r1e280m4xQ"},{"tagName":"mj-column","attributes":{"width":"33.333333%","vertical-align":"top"},"children":[{"tagName":"mj-spacer","attributes":{"height":15,"containerWidth":200},"uid":"rJfqLiXEgm"}],"uid":"B1W380QVxX"}],"layout":1,"backgroundColor":"","backgroundImage":"","paddingTop":0,"paddingBottom":0,"paddingLeft":0,"paddingRight":0,"uid":"rkqIjQNe7"} // MJML JSON
                    ]
                }]
            }

List of available categories

Saved blocks

Users can save their sections by clicking save button while moving mouse over section.

To enable this feature set savedBlocks to [], to disable it don’t set the value at all or set it to null

You can hide saved blocks and the premade block button using premadeBlocks: false a savedBlocks: false.

savedBlocks: []

Each block has the following structure:

{
  id: 1, // ID of the block, if not set it uses the Array Index
  name: 'My saved block 001', // You can set a name or an image
  img: 'http://...', // The editor shows only name or image, not both, if both set it will show the image
  definition: 'json',
}

There are three actions you need to implement to make saved blocks work: onBlockSave, onBlockEdit and onBlockRemove. All of them needs to be implement on callbacks object.

Example:

onBlockSave(json) {
  var name = window.prompt('Enter block name:')
  if (name !== null) {
    console.log('saving block', json)
  }
},
onBlockRemove(id) {
  if (window.confirm('Are you sure?')) {
    console.log('removing block', id)
  }
},
onBlockEdit(id) {
  var name = window.prompt('Block name:', 'My block 001')
  if (name !== null) {
    console.log('saving edited block', id)
  }
}

Since it’s your responsibility to take care of those actions, you also need to update the list of saved blocks once updated. To do so you the following function:

TopolPlugin.setSavedBlocks([{
  id: 1, // ID of the block, if not set it uses the Array Index
  name: 'My saved block 001', // You can set a name or an image
  img: 'http://...', // The editor shows only name or image, not both, if both set it will show the image
  definition: 'json',
}]);

This function takes an array of all saved block you want to show within the editor.

Light theme

By setting an option light: true you will switch the editor design to light theme.

Dark theme Light theme

Remove Top Bar

Top bar

If you decide to create your own save & close buttons, you can completely remove the top bar from the editor, so you don’t have to be limited by our own interface, to do so use: removeTopBar: true.

onTestSend

Top bar

When the user clicks on Send Test (The icon). The template is rendered and then the callback is called. The test input can be hidden by setting the option sendTestEmail: false.

onTestSend: function(email, json, html) {
    console.log(html);
    console.log(json);
    // Email of the recipient
    console.log(email);
},

Preview mode on desktop and mobile

When top bar is removed, You can access the preview mode using the function:

    TopolPlugin.togglePreview(); // Toggles the mode of Preview

Redo & Undo

You can apply redo and undo function on the TopolPlugin object.

TopolPlugin.undo();
TopolPlugin.redo();

Save/load options

Hosted Templates

If you want to store the templates on our servers, use the templateId option as the identifier for specific template to load. For ex. your ID of the row in database. This is set by you. Each time you use the same templateId the same saved template will be loaded.

Self-stored templates

The second option is to load a JSON template, you can find predefined templates below (click to show the JSON code). Use the “start from scratch” for new blank template:

templates      

Just call the function load in the plugin instance with the JSON.

TopolPlugin.load("{\"tagName\":..."); // Load json template from STRING format

This function can also be called if you want to load a template from a JSON to a specific templateId. So if you provide templateId and then call LOAD function the current template will be overwritten templateId.

API load example:

let request = new XMLHttpRequest();
const url = `https://tlapi.github.io/topol-editor/templates/3.json`;

request.onreadystatechange = function() {
    if (this.readyState === 4 && this.status === 200) {
      const json = JSON.parse(JSON.stringify(this.response));
      TopolPlugin.load(json);
    }
  }
request.open("GET", url, true);
request.send();

Inline load example:

TopolPlugin.load(JSON.stringify({
    "tagName": "mj-global-style",
    "attributes": {
        "h1:color": "#000",
        "h1:font-family": "Helvetica, sans-serif",
        "h2:color": "#000",
        "h2:font-family": "Ubuntu, Helvetica, Arial, sans-serif",
        "h3:color": "#000",
        "h3:font-family": "Ubuntu, Helvetica, Arial, sans-serif",
        ":color": "#000",
        ":font-family": "Ubuntu, Helvetica, Arial, sans-serif",
        ":line-height": "1.5",
        "a:color": "#24bfbc",
        "button:background-color": "#e85034",
        "containerWidth": 600,
        "fonts": "Helvetica,sans-serif,Ubuntu,Arial",
        "mj-text": {
            "line-height": 1.5,
            "font-size": 15
        },
        "mj-button": []
    },
    "children": [
        {
            "tagName": "mj-container",
            "attributes": {
                "background-color": "#FFFFFF",
                "containerWidth": 600
            },
            "children": [
                {
                    "tagName": "mj-section",
                    "attributes": {
                        "full-width": false,
                        "padding": "9px 0px 9px 0px"
                    },
                    "children": [
                        {
                            "tagName": "mj-column",
                            "attributes": {
                                "width": "100%"
                            },
                            "children": [],
                            "uid": "HJQ8ytZzW"
                        }
                    ],
                    "layout": 1,
                    "backgroundColor": null,
                    "backgroundImage": null,
                    "paddingTop": 0,
                    "paddingBottom": 0,
                    "paddingLeft": 0,
                    "paddingRight": 0,
                    "uid": "Byggju-zb"
                }
            ]
        }
    ],
    "style": {
        "h1": {
            "font-family": "\"Cabin\", sans-serif"
        }
    },
    "fonts": [
        "\"Cabin\", sans-serif"
    ]
})); // Load json template from STRING format

onSave & onSaveAndClose

When the user clicks on Save or on Save & Close button, the SAVE API endpoint is called and then the onSave/onSaveAndClose is called.

You can insert a callback that is called right after the SAVE API endpoint is called. The callback have a data attribute that contains the data of the response.

onSave: function(json, html) {
    console.log(html);
    console.log(json);
},
onSaveAndClose: function(json, jtml) {
    console.log(html);
    console.log(json);
}

onAutoSave

When the editor decides that a user could lose unsaved template it calls this function so you can save it.

onAutoSave: function(json) {
    console.log(json);
},

Custom File Manager

customFileManager

If you want to disable our build in File Manager just define a ‘customFileManager: true’ in the options object. Then the editor will use the below functions.

onOpenFileManager

When the user clicks on Choose a file (ex. as a property of an image). This callback is called. For ex. you can develop your own file manager dialog.

onOpenFileManager: function() {
    // Open your file manager and let user choose a file.
},

chooseFile

When a user chooses a file, you need to call chooseFile function on the TopolPlugin instance. with the url of the file.

TopolPlugin.chooseFile('http://url.to/picture.png');

Storage options with our File Manager

We provide custom storage options with AWS S3, Google Cloud storage and Azure Storage. Feel free to contact us (get@topol.io).

Custom API endpoints

If you don’t want to integrate File Manager by yourself but still want to use your server to process files you can change the endpoints.

FOLDERS - GET

Called when displaying file manager with these GET parameters path, userId, uuid

Response:

[{
    "name": "filename", 
    "date": last-date-modified,
    "size": 500,
    "path": "/path/",
    "type": "file" OR "folder",
    "extension": ".jpg",
    "url": "https://url-to-image.com/image.jpeg"
}]

IMAGE_UPLOAD - POST

Called when the user wants to upload a new file with the request containing path and image data.

Response:

Content-Type:application/json

{
  "success": true,
  "url": "http://191n.mj.am/img/191n/1t/hs.png"
}

AVIARY_UPLOAD - POST

Called when image is updated via Aviary editor.

Request:

Content-Type:application/json

{
  "url": "https://s3.amazonaws.com/feather-client-files-aviary-prod-us-east-1/2017-05-25/b065cca0-cb16-4a02-a0c2-c9317be0085b.png"
}

Response:

Content-Type:application/json

{
  "url": "http://placekitten.com.s3.amazonaws.com/homepage-samples/408/287.jpg"
}

LOAD - GET

Load given template.

Response:

Content-Type:application/json

[
    "template": {
        "tagName": "mj-global-style",
        "attributes": {
          "h1:color": "#000",
          "h1:font-family": "Helvetica, sans-serif",
          "h2:color": "#000",
          "h2:font-family": "Ubuntu, Helvetica, Arial, sans-serif",
          "h3:color": "#000",
          "h3:font-family": "Ubuntu, Helvetica, Arial, sans-serif",
          ":color": "#000",
          ":font-family": "Ubuntu, Helvetica, Arial, sans-serif",
          ":line-height": "1.5",
          "a:color": "#24bfbc",
          "button:background-color": "#e85034",
          "containerWidth": 600,
          "fonts": "Helvetica,sans-serif,Ubuntu,Arial",
          "mj-text": {
            "line-height": 1.5
          },
          "mj-button": {}
        },
        "children": [
          {
            "tagName": "mj-container",
            "attributes": {
              "background-color": "#f0f0f0",
              "containerWidth": 600
            },
            "children": [
              {
                "tagName": "mj-section",
                "attributes": {
                  "background-color": "#ffffff",
                  "containerWidth": 600,
                  "layout": "normal",
                  "padding": "10px 0px 10px 0px"
                },
                "children": [
                  {
                    "tagName": "mj-column",
                    "attributes": {
                      "width": "100%",
                      "vertical-align": "middle",
                      "containerWidth": 600
                    },
                    "children": [
                      {
                        "tagName": "mj-image",
                        "attributes": {
                          "src": "https://storage.googleapis.com/news1974/2017/Jan/Thu/1484820995.png",
                          "width": 151,
                          "padding": "17px 17px 17px 17px",
                          "containerWidth": 600,
                          "widthPercent": 25
                        },
                        "uid": "HkUQv-O4bZ"
                      }
                    ],
                    "uid": "ByHXPZu4WW"
                  }
                ],
                "uid": "SkE7vWuNZb"
              }
            ]
          }
        ],
        "style": []
      }
]

SAVE - POST

When saving template you will recieve JSON definition of the template. As a response you should state that the save was successfull and url of the page where you want your user to redirect.

Request:

Content-Type:application/json

{
  "definition": {
    "tagName": "mj-global-style",
    "attributes": {
      "h1:color": "#000",
      "h1:font-family": "Helvetica, sans-serif",
      "h2:color": "#000",
      "h2:font-family": "Ubuntu, Helvetica, Arial, sans-serif",
      "h3:color": "#000",
      "h3:font-family": "Ubuntu, Helvetica, Arial, sans-serif",
      ":color": "#000",
      ":font-family": "Ubuntu, Helvetica, Arial, sans-serif",
      ":line-height": "1.5",
      "a:color": "#24bfbc",
      "button:background-color": "#e85034",
      "containerWidth": 600,
      "fonts": "Helvetica,sans-serif,Ubuntu,Arial",
      "mj-text": {
        "line-height": 1.5
      },
      "mj-button": {}
    },
    "children": [
      {
        "tagName": "mj-container",
        "attributes": {
          "background-color": "#f0f0f0",
          "containerWidth": 600
        },
        "children": [
          {
            "tagName": "mj-section",
            "attributes": {
              "background-color": "#ffffff",
              "containerWidth": 600,
              "layout": "normal",
              "padding": "10px 0px 10px 0px"
            },
            "children": [
              {
                "tagName": "mj-column",
                "attributes": {
                  "width": "100%",
                  "vertical-align": "middle",
                  "containerWidth": 600
                },
                "children": [
                  {
                    "tagName": "mj-image",
                    "attributes": {
                      "src": "https://storage.googleapis.com/news1974/2017/Jan/Thu/1484820995.png",
                      "width": 151,
                      "padding": "17px 17px 17px 17px",
                      "containerWidth": 600,
                      "widthPercent": 25
                    },
                    "uid": "HkUQv-O4bZ"
                  }
                ],
                "uid": "ByHXPZu4WW"
              }
            ],
            "uid": "SkE7vWuNZb"
          }
        ]
      }
    ],
  }
}

Response:

Content-Type:application/json

{
  "success": true,
  "redirect_to": "https://www.myapp.com"
}

AUTOSAVE - POST

Providing this endpoint You could implement autosaving functionality. You will receive template JSON definition and You should return successful response.

Request:

Content-Type:application/json

{
  "definition": {
    "tagName": "mj-global-style",
    "attributes": {
      "h1:color": "#000",
      "h1:font-family": "Helvetica, sans-serif",
      "h2:color": "#000",
      "h2:font-family": "Ubuntu, Helvetica, Arial, sans-serif",
      "h3:color": "#000",
      "h3:font-family": "Ubuntu, Helvetica, Arial, sans-serif",
      ":color": "#000",
      ":font-family": "Ubuntu, Helvetica, Arial, sans-serif",
      ":line-height": "1.5",
      "a:color": "#24bfbc",
      "button:background-color": "#e85034",
      "containerWidth": 600,
      "fonts": "Helvetica,sans-serif,Ubuntu,Arial",
      "mj-text": {
        "line-height": 1.5
      },
      "mj-button": {}
    },
    "children": [
      {
        "tagName": "mj-container",
        "attributes": {
          "background-color": "#f0f0f0",
          "containerWidth": 600
        },
        "children": [
          {
            "tagName": "mj-section",
            "attributes": {
              "background-color": "#ffffff",
              "containerWidth": 600,
              "layout": "normal",
              "padding": "10px 0px 10px 0px"
            },
            "children": [
              {
                "tagName": "mj-column",
                "attributes": {
                  "width": "100%",
                  "vertical-align": "middle",
                  "containerWidth": 600
                },
                "children": [
                  {
                    "tagName": "mj-image",
                    "attributes": {
                      "src": "https://storage.googleapis.com/news1974/2017/Jan/Thu/1484820995.png",
                      "width": 151,
                      "padding": "17px 17px 17px 17px",
                      "containerWidth": 600,
                      "widthPercent": 25
                    },
                    "uid": "HkUQv-O4bZ"
                  }
                ],
                "uid": "ByHXPZu4WW"
              }
            ],
            "uid": "SkE7vWuNZb"
          }
        ]
      }
    ],
  }
}

Response:

Content-Type:application/json

{
  "success": true
}

Miscellaneous

Domains used by TOPOL.io plugin

What domains are used by the plugin? Sometimes there could be an issue caused by firewall on your clients network, so they may need to add the domains to a whitelist. TOPOL.io plugin is using following domains:

d5aoblv5p04cg.cloudfront.net
cdn.rawgit.com
cdnjs.cloudflare.com
d70shl7vidtft.cloudfront.net
fonts.googleapis.com
rawgit.com
uicdn.toast.com

Flags made by Freepik from www.flaticon.com