404
How did we get here?Take me home.
diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 000000000..4192995ce --- /dev/null +++ b/docs/404.html @@ -0,0 +1,19 @@ + + +
+ + +
+ GrapesJS
+ This page will introduce you to the main options of GrapesJS and how it works, in the way to be able to create your custom editor.
The pretty minimalistic way to instantiate the editor could be like this:
<link rel="stylesheet" href="path/to/grapes.min.css">
+<script src="path/to/grapes.min.js"></script>
+
+<div id="gjs"></div>
+
+<script type="text/javascript">
+ var editor = grapesjs.init({
+ container : '#gjs',
+ components: '<div class="txt-red">Hello world!</div>',
+ style: '.txt-red{color: red}',
+ });
+</script>
+In just few lines, with the default configurations, you're already able to see something with which play around.
[[img/default-gjs.jpg]]
You'll see components commands on top left position that come handy to create and manage your blocks, below there are options which need to highlight and export them. When you select components ('mouse pointer' icon), on the right side, you should see pop up Class Manager and Style Manager options which allow to customize the style of the components. There is also a Layer Manager/Navigator ('hamburger' icon) which helps to manage easily the structure.
Of course all those stuff (panels, buttons, commands, etc.) are set just as default so you can overwrite them and add more other. Before you start to create things you should know that GrapesJS UI is composed basically by a canvas (where you will 'draw') and panels (which will contain buttons)
[[img/canvas-panels.jpg]]
If you'd like to extend the already instantiated editor you have to check API Reference. Check also how to create plugins using the same API. +In this guide we'll focus on how to initialize the editor with all custom UI from scratch.
Let's start the editor with some basic toolbar panel
...
+var editor = grapesjs.init({
+ container : '#gjs',
+ height: '100%',
+
+ panels: {
+ defaults: [{
+ id: 'commands',
+ }],
+ }
+});
+...
+In this example we set a panel with 'commands' as an id and after the render we'll see nothing more than an empty div added to our panels. The new panel is already styled as the id 'commands' is one of the default but you can use whatever you like and place it wherever you want with CSS. With refresh we might see something like shown in the image below, with the new panel on the left:
[[img/new-panel.png]]
Check Editor API Reference for more details about editor configurations
Now let's put some button inside
...
+ panels: {
+ defaults : [{
+ id : 'commands',
+ buttons : [{
+ id : 'smile',
+ className : 'fa fa-smile-o',
+ attributes : { title: 'Smile' }
+ }],
+ }],
+ }
+...
+On refresh the page might present some changes ('fa fa-smile-o' are from FontAwesome set, so be sure to have placed correctly the font directory)
[[img/new-btn.png]]
Yeah, the button is pretty nice and happy, but useless without any command assigned, if you click on it nothing gonna happen.
Check Panels API Reference for more details about Panels and Buttons
Assigning commands is pretty easy, but before you should define one or use one of defaults (Built-in commands). So in this case we gonna create a new one.
...
+ panels: {
+ defaults : [{
+ id : 'commands',
+ buttons : [{
+ id : 'smile',
+ className : 'fa fa-smile-o',
+ attributes : { title: 'Smile' },
+ command : 'helloWorld',
+ }],
+ }],
+ },
+ commands: {
+ defaults: [{
+ id: 'helloWorld',
+
+ run: function(editor, senderBtn){
+ alert('Hello world!');
+ // Deactivate button
+ senderBtn.set('active', false);
+ },
+
+ stop: function(editor, senderBtn){
+ },
+ }]
+ }
+...
+As you see we added a new command helloWorld and used its id as an identifier inside button.command. In addition to this we've also implemented two required methods, run and stop, to make button execute commands.
[[img/btn-clicked.png]]
Check Commands API Reference
Check the demo for more complete usage of panels, buttons and built-in commands.
Components are elements inside the canvas, which can be drawn by commands or injected directly via configurations. In simple terms components represent the structure of our HTML document. You can init the editor with passing components as an HTML string
...
+ // Disable default local storage in case you've already used GrapesJS
+ storageManager: {type: 'none'},
+
+ components: '<div style="width:300px; min-height:100px; margin: 0 auto"></div>' +
+ '<div style="width:400px; min-height:100px; margin: 0 auto"></div>' +
+ '<div style="width:500px; min-height:100px; margin: 0 auto"></div>',
+...
+We added 3 simple components with some basic style. If you refresh probably you'll see the same empty page but are actually there, you only need to highlight them. +For this purpose already exists a command, so add it to your panel in this way
...
+ panels: {
+ defaults : [{
+ id : 'commands',
+ buttons : [
+ {
+ id: 'smile',
+ ...
+ },
+ {
+ id : 'vis',
+ className : 'fa fa-eye',
+ command : 'sw-visibility',
+ context : 'some-random-context', // For grouping context of buttons in the same panel
+ active : true,
+ },
+ ],
+ }],
+ },
+...
+Worth noting the use of context option (try to click 'smile' command without it) and active to enable it after the render.
+Now you should be able to see blocks inside canvas.
[[img/blocks3.jpg]]
You could add other commands to enable interactions with blocks. Check Built-in commands to get more information
Check Components API Reference
Any HTML structure requires, at some point, a proper style, so to meet this need the Style Manager was added as a built-in feature in GrapesJS. Style manager is composed by sectors, which group inside different types of CSS properties. So you can add, for instance, a Dimension sector for width and height, and another one as Typography for font-size and color. So it's up to you decide how organize sectors.
To enable this module we rely on a built-in command open-sm, which shows up the Style Manager, which we gonna bind to another button in a separate panel
...
+panels: {
+ defaults : [
+ {
+ id : 'commands',
+ ...
+ },{
+ // If you use this id the default CSS will place this panel on top right corner for you
+ id : 'views',
+ buttons : [{
+ id : 'open-style-manager',
+ className : 'fa fa-paint-brush',
+ command : 'open-sm',
+ active : true,
+ }]
+ }
+ ],
+},
+...
+After this you'll be able to see something like in the image below
[[img/enabled-sm.jpg]]
As you can see Style Manager is enabled but before using it you have to select an element in the canvas, for this purpose we can add another button with a built-in command select-comp in this way
...
+ panels: {
+ defaults : [{
+ id : 'commands',
+ buttons : [
+ {
+ id: 'smile',
+ ...
+ },{
+ id : 'select',
+ className : 'fa fa-mouse-pointer',
+ command : 'select-comp',
+ }
+ ],
+ }],
+ },
+...
+Selecting one of the component will show up the Style Manager with default sectors, properties and an input where you can manage classes. The default class you see (cXX) was generated by extracting style from the component
[[img/default-sm.jpg]]
As we exploring different configurations inside GrapesJS we gonna overwrite all the default sectors to create some custom one
Let's put a few sectors with use of buildProps which helps us building common properties
...
+ styleManager : {
+ sectors: [{
+ name: 'Dimension',
+ buildProps: ['width', 'min-height']
+ },{
+ name: 'Extra',
+ buildProps: ['background-color', 'box-shadow']
+ }]
+ }
+...
+Now you should be able to style components
[[img/style-comp.jpg]]
You can check the list of usable properties inside buildProps here: Built-in properties
+otherwise is possible to build them on your own, let's see how we'd have done the previous configuration without the buildProps helper
...
+styleManager : {
+ sectors: [
+ {
+ name: 'Dimension',
+ properties:[
+ {
+ // Just the name
+ name : 'Width',
+ // CSS property
+ property : 'width',
+ // Type of the input, options: integer | radio | select | color | file | composite | stack
+ type : 'integer',
+ // Units, available only for 'integer' types
+ units : ['px', '%'],
+ // Default value
+ defaults : 'auto',
+ // Min value, available only for 'integer' types
+ min : 0,
+ },{
+ // Here I'm going to be more original
+ name : 'Minimum height',
+ property : 'min-height',
+ type : 'select',
+ defaults : '100px',
+ // List of options, available only for 'select' and 'radio' types
+ list : [{
+ value : '100px',
+ name : '100',
+ },{
+ value : '200px',
+ name : '200',
+ },{
+ value : '300px',
+ name : '300',
+ }],
+ }
+ ]
+ },{
+ name: 'Extra',
+ // Sectors are expanded by default so put this one closed
+ open: false,
+ properties:[
+ {
+ name : 'Background',
+ property : 'background-color',
+ type : 'color',
+ defaults: 'none'
+ },{
+ name : 'Box shadow',
+ property : 'box-shadow',
+ type : 'stack',
+ preview : true,
+ // List of nested properties, available only for 'stack' and 'composite' types
+ properties : [{
+ name: 'Shadow type',
+ // Nested properties with stack/composite type don't require proper 'property' name
+ // as all of them will be merged to parent property, eg. box-shadow: X Y ...;
+ property: 'shadow-type',
+ type: 'select',
+ defaults: '',
+ list: [ { value : '', name : 'Outside', },
+ { value : 'inset', name : 'Inside', }],
+ },{
+ name: 'X position',
+ property: 'shadow-x',
+ type: 'integer',
+ units: ['px','%'],
+ defaults : 0,
+ },{
+ name: 'Y position',
+ property: 'shadow-y',
+ type: 'integer',
+ units: ['px','%'],
+ defaults : 0,
+ },{
+ name: 'Blur',
+ property: 'shadow-blur',
+ type: 'integer',
+ units: ['px'],
+ defaults : 0,
+ min: 0,
+ },{
+ name: 'Spread',
+ property: 'shadow-spread',
+ type: 'integer',
+ units: ['px'],
+ defaults : 0,
+ },{
+ name: 'Color',
+ property: 'shadow-color',
+ type: 'color',
+ defaults: 'black',
+ },],
+ }
+ ]
+ }
+ ]
+}
+...
+As you can see using buildProps actually will save you a lot of work. You could also mix this techniques to obtain custom properties in less time. For example, let's see how can we setup the same width but with a different value of min:
...
+ styleManager : {
+ sectors: [{
+ name: 'Dimension',
+ buildProps: ['width', 'min-height'],
+ properties:[{
+ property: 'width', // Use 'property' as id
+ min: 30
+ }]
+ },
+ ...
+ }
+...
+In this last part we're gonna see how to store and load template data inside GrapesJS. You may already noticed that even if you refresh the page after changes on canvas your data are not lost and this because GrapesJS comes with some built-in storage implementation. +The default one is the localStorage which is pretty simple and all the data are stored locally on your computer. Let's see the options available for this storage
...
+var editor = grapesjs.init({
+ container : '#gjs',
+ ...
+ // Default configuration
+ storageManager: {
+ id: 'gjs-', // Prefix identifier that will be used inside storing and loading
+ type: 'local', // Type of the storage
+ autosave: true, // Store data automatically
+ autoload: true, // Autoload stored data on init
+ stepsBeforeSave: 1, // If autosave enabled, indicates how many changes are necessary before store method is triggered
+ storeComponents: false, // Enable/Disable storing of components in JSON format
+ storeStyles: false, // Enable/Disable storing of rules/style in JSON format
+ storeHtml: true, // Enable/Disable storing of components as HTML string
+ storeCss: true, // Enable/Disable storing of rules/style as CSS string
+ }
+});
+...
+Worth noting the defaut id parameter which adds a prefix for all keys to store. If you check the localStorage inside your DOM panel you'll see something like { 'gjs-components': '<div>....' ...} in this way it prevents the risk of collisions, quite common with localStorage use in large applications.
Storing data locally it's easy and fast but useless in some common cases. In the next example we'll see how to setup a remote storage, which is not far from the previous one
...
+var editor = grapesjs.init({
+ container : '#gjs',
+ ...
+ storageManager: {
+ type: 'remote',
+ stepsBeforeSave: 10,
+ urlStore: 'http://store/endpoint',
+ urlLoad: 'http://load/endpoint',
+ params: {}, // For custom values on requests
+ }
+});
+...
+As you can see we've left some default option unchanged, increased changes necessary for autosave triggering and passed remote endpoints.
If you prefer you could also disable autosaving and do it by yourself using some custom command in this way:
...
+ storageManager: {
+ type: 'remote',
+ autosave: false,
+ },
+ ...
+ commands: {
+ defaults: [{
+ id: 'storeData',
+ run: function(editor, senderBtn){
+ editor.store();
+ },
+ }]
+ }
+...
+
+ GrapesJS
+ You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ assetManager: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const assetManager = editor.AssetManager;
+Add new asset/s to the collection. URLs are supposed to be unique
asset(string | Object | Array<string> | Array<Object>) URL strings or an objects representing the resource.optsObject? Options (optional, default {})// In case of strings, would be interpreted as images
+assetManager.add('http://img.jpg');
+assetManager.add(['http://img.jpg', './path/to/img.png']);
+
+// Using objects you could indicate the type and other meta informations
+assetManager.add({
+ src: 'http://img.jpg',
+ //type: 'image', //image is default
+ height: 300,
+width: 200,
+});
+assetManager.add([{
+ src: 'http://img.jpg',
+},{
+ src: './path/to/img.png',
+}]);
+Returns Model
Returns the asset by URL
srcstring URL of the assetvar asset = assetManager.get('http://img.jpg');
+Returns Object Object representing the asset
Return the global collection, containing all the assets
Returns Collection
Return the visible collection, which containes assets actually rendered
Returns Collection
Remove the asset by its URL
srcstring URL of the assetassetManager.remove('http://img.jpg');
+Returns this
Store assets data to the selected storage
noStoreBoolean If true, won't storevar assets = assetManager.store();
+Returns Object Data to store
Load data from the passed object. +The fetched data will be added to the collection.
dataObject Object of data to load (optional, default {})var assets = assetManager.load({
+ assets: [...]
+})
+Returns Object Loaded assets
Return the Asset Manager Container
Returns HTMLElement
Get assets element container
Returns HTMLElement
Render assets
assetsarray Assets to render, without the argument will render
+all global assets// Render all assets
+assetManager.render();
+
+// Render some of the assets
+const assets = assetManager.getAll();
+assetManager.render(assets.filter(
+ asset => asset.get('category') == 'cats'
+));
+Returns HTMLElement
Add new type. If you want to get more about type definition we suggest to read the module's page
idstring Type IDdefinitionObject Definition of the type. Each definition contains
+model (business logic), view (presentation logic)
+and isType function which recognize the type of the
+passed entityassetManager.addType('my-type', {
+ model: {},
+ view: {},
+ isType: (value) => {},
+})
+Get type
idstring Type IDReturns Object Type definition
Get types
Returns Array
+ ← + Editor + + Block Manager + → +
+ GrapesJS
+ You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ blockManager: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const blockManager = editor.BlockManager;
+Get configuration object
Returns Object
Load default blocks if the collection is empty
Add new block to the collection.
idstring Block idoptsObject Options
+opts.labelstring Name of the blockopts.contentstring HTML contentopts.category(string | Object) Group the block inside a catgegory.
+You should pass objects with id property, eg:
+{id: 'some-uid', label: 'My category'}
+The string will be converted in:
+'someid' => {id: 'someid', label: 'someid'}opts.attributesObject Block attributes (optional, default {})blockManager.add('h1-block', {
+ label: 'Heading',
+ content: '<h1>Put your title here</h1>',
+ category: 'Basic',
+ attributes: {
+ title: 'Insert h1 block'
+ }
+});
+Returns Block Added block
Return the block by id
idstring Block idconst block = blockManager.get('h1-block');
+console.log(JSON.stringify(block));
+// {label: 'Heading', content: '<h1>Put your ...', ...}
+Return all blocks
const blocks = blockManager.getAll();
+console.log(JSON.stringify(blocks));
+// [{label: 'Heading', content: '<h1>Put your ...'}, ...]
+Returns Collection
Return the visible collection, which containes blocks actually rendered
Returns Collection
Remove a block by id
idstring Block idReturns Block Removed block
Get all available categories. +It's possible to add categories only within blocks via 'add()' method
Returns (Array | Collection)
Return the Blocks container element
Returns HTMLElement
Render blocks
blocksArray Blocks to render, without the argument will render
+all global blocks// Render all blocks (inside the global collection)
+blockManager.render();
+
+// Render new set of blocks
+const blocks = blockManager.getAll();
+blockManager.render(blocks.filter(
+ block => block.get('category') == 'sections'
+));
+// Or a new set from an array
+blockManager.render([
+ {label: 'Label text', content: '<div>Content</div>'}
+]);
+
+// Back to blocks from the global collection
+blockManager.render();
+Returns HTMLElement Rendered element
+ ← + Asset Manager + + Commands + → +
+ GrapesJS
+ You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ commands: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const commands = editor.Commands;
+Add new command to the collection
idstring Command's IDcommand(Object | Function) Object representing your command,
+By passing just a function it's intended as a stateless command
+(just like passing an object with only run method).commands.add('myCommand', {
+ run(editor, sender) {
+ alert('Hello world!');
+ },
+ stop(editor, sender) {
+ },
+});
+// As a function
+commands.add('myCommand2', editor => { ... });
+Returns this
Get command by ID
idstring Command's IDvar myCommand = commands.get('myCommand');
+myCommand.run();
+Returns Object Object representing the command
Check if command exists
idstring Command's IDReturns Boolean
+ ← + Block Manager + + DOM Components + → +
+ GrapesJS
+ With this module is possible to manage components inside the canvas. You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ domComponents: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const domComponents = editor.DomComponents;
+Load components from the passed object, if the object is empty will try to fetch them +autonomously from the selected storage +The fetched data will be added to the collection
dataObject Object of data to load (optional, default '')Returns Object Loaded data
Store components on the selected storage
noStoreBoolean If true, won't storeReturns Object Data to store
Returns root component inside the canvas. Something like <body> inside HTML page
+The wrapper doesn't differ from the original Component Model
// Change background of the wrapper and set some attribute
+var wrapper = domComponents.getWrapper();
+wrapper.set('style', {'background-color': 'red'});
+wrapper.set('attributes', {'title': 'Hello!'});
+Returns Component Root Component
Returns wrapper's children collection. Once you have the collection you can +add other Components(Models) inside. Each component can have several nested +components inside and you can nest them as more as you wish.
// Let's add some component
+var wrapperChildren = domComponents.getComponents();
+var comp1 = wrapperChildren.add({
+ style: { 'background-color': 'red'}
+});
+var comp2 = wrapperChildren.add({
+ tagName: 'span',
+ attributes: { title: 'Hello!'}
+});
+// Now let's add an other one inside first component
+// First we have to get the collection inside. Each
+// component has 'components' property
+var comp1Children = comp1.get('components');
+// Procede as before. You could also add multiple objects
+comp1Children.add([
+ { style: { 'background-color': 'blue'}},
+ { style: { height: '100px', width: '100px'}}
+]);
+// Remove comp2
+wrapperChildren.remove(comp2);
+Returns Components Collection of components
Add new components to the wrapper's children. It's the same +as 'domComponents.getComponents().add(...)'
component(Object | Component | Array<Object>) Component/s to add
+component.tagNamestring Tag name (optional, default 'div')component.typestring Type of the component. Available: ''(default), 'text', 'image' (optional, default '')component.removableboolean If component is removable (optional, default true)component.draggableboolean If is possible to move the component around the structure (optional, default true)component.droppableboolean If is possible to drop inside other components (optional, default true)component.badgableboolean If the badge is visible when the component is selected (optional, default true)component.stylableboolean If is possible to style component (optional, default true)component.copyableboolean If is possible to copy&paste the component (optional, default true)component.contentstring String inside component (optional, default '')component.styleObject Style object (optional, default {})component.attributesObject Attribute object (optional, default {})// Example of a new component with some extra property
+var comp1 = domComponents.addComponent({
+ tagName: 'div',
+ removable: true, // Can't remove it
+ draggable: true, // Can't move it
+ copyable: true, // Disable copy/past
+ content: 'Content text', // Text inside component
+ style: { color: 'red'},
+ attributes: { title: 'here' }
+});
+Returns (Component | Array<Component>) Component/s added
Render and returns wrapper element with all components inside. +Once the wrapper is rendered, and it's what happens when you init the editor, +the all new components will be added automatically and property changes are all +updated immediately
Returns HTMLElement
Remove all components
Returns this
+ ← + Commands + + Panels + → +
+ GrapesJS
+ This module contains and manage CSS rules for the template inside the canvas. +You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ cssComposer: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const cssComposer = editor.CssComposer;
+Load data from the passed object, if the object is empty will try to fetch them +autonomously from the storage manager. +The fetched data will be added to the collection
dataObject Object of data to loadReturns Object Loaded rules
Store data to the selected storage
noStoreBoolean If true, won't storeReturns Object Data to store
Add new rule to the collection, if not yet exists with the same selectors
selectorsArray<Selector> Array of selectorsstateString Css rule statewidthString For which device this style is orientedoptsObject Other options for the rule (optional, default {})var sm = editor.SelectorManager;
+var sel1 = sm.add('myClass1');
+var sel2 = sm.add('myClass2');
+var rule = cssComposer.add([sel1, sel2], 'hover');
+rule.set('style', {
+ width: '100px',
+ color: '#fff',
+});
+Returns Model
Get the rule
selectorsArray<Selector> Array of selectorsstateString Css rule statewidthString For which device this style is orientedrulePropsObject Other rule propsvar sm = editor.SelectorManager;
+var sel1 = sm.add('myClass1');
+var sel2 = sm.add('myClass2');
+var rule = cssComposer.get([sel1, sel2], 'hover');
+// Update the style
+rule.set('style', {
+ width: '300px',
+ color: '#000',
+});
+Returns (Model | null)
Get the collection of rules
Returns Collection
Remove all rules
Returns this
Add/update the CSS rule with id selector
namestring Id selector name, eg. 'my-id'styleObject Style properties and values (optional, default {})optsObject Custom options, like state and mediaText (optional, default {})const rule = cc.setIdRule('myid', { color: 'red' });
+const ruleHover = cc.setIdRule('myid', { color: 'blue' }, { state: 'hover' });
+// This will add current CSS:
+// #myid { color: red }
+// #myid:hover { color: blue }
+Returns CssRule The new/updated rule
Get the CSS rule by id selector
namestring Id selector name, eg. 'my-id'optsObject Custom options, like state and mediaText (optional, default {})const rule = cc.getIdRule('myid');
+const ruleHover = cc.setIdRule('myid', { state: 'hover' });
+Returns CssRule
Add/update the CSS rule with class selector
namestring Class selector name, eg. 'my-class'styleObject Style properties and values (optional, default {})optsObject Custom options, like state and mediaText (optional, default {})const rule = cc.setClassRule('myclass', { color: 'red' });
+const ruleHover = cc.setClassRule('myclass', { color: 'blue' }, { state: 'hover' });
+// This will add current CSS:
+// .myclass { color: red }
+// .myclass:hover { color: blue }
+Returns CssRule The new/updated rule
Get the CSS rule by class selector
namestring Class selector name, eg. 'my-class'optsObject Custom options, like state and mediaText (optional, default {})const rule = cc.getClassRule('myclass');
+const ruleHover = cc.getClassRule('myclass', { state: 'hover' });
+Returns CssRule
+ ← + Selector Manager + + Modal + → +
+ GrapesJS
+ You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ deviceManager: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const deviceManager = editor.DeviceManager;
+Add new device to the collection. URLs are supposed to be unique
deviceManager.add('Tablet', '900px');
+deviceManager.add('Tablet2', '900px', {
+ height: '300px',
+ widthMedia: '810px', // the width that will be used for the CSS media
+});
+Returns Device Added device
Return device by name
namestring Name of the devicevar device = deviceManager.get('Tablet');
+console.log(JSON.stringify(device));
+// {name: 'Tablet', width: '900px'}
+Return all devices
var devices = deviceManager.getAll();
+console.log(JSON.stringify(devices));
+// [{name: 'Desktop', width: ''}, ...]
+Returns Collection
+ GrapesJS
+ Editor contains the top level API which you'll probably use to customize the editor or extend it with plugins. +You get the Editor instance on init method and you can pass options via its Configuration Object
const editor = grapesjs.init({
+ // options
+});
+You can make use of available events in this way
editor.on('EVENT-NAME', (some, argument) => {
+ // do something
+})
+component:add - Triggered when a new component is added to the editor, the model is passed as an argument to the callbackcomponent:remove - Triggered when a component is removed, the model is passed as an argument to the callbackcomponent:clone - Triggered when a new component is added by a clone command, the model is passed as an argument to the callbackcomponent:update - Triggered when a component is updated (moved, styled, etc.), the model is passed as an argument to the callbackcomponent:update:{propertyName} - Listen any property change, the model is passed as an argument to the callbackcomponent:styleUpdate - Triggered when the style of the component is updated, the model is passed as an argument to the callbackcomponent:styleUpdate:{propertyName} - Listen for a specific style property change, the model is passed as an argument to the callbackcomponent:selected - New component selected, the selected model is passed as an argument to the callbackcomponent:deselected - Component deselected, the deselected model is passed as an argument to the callbackcomponent:toggled - Component selection changed, toggled model is passed as an argument to the callbackblock:add - New block addedblock:remove - Block removedblock:drag:start - Started dragging block, model of the block is passed as an argumentblock:drag - Dragging block, the block's model and the drag event are passed as argumentsblock:drag:stop - Dragging of the block is stopped. As agruments for the callback you get, the dropped component model (if dropped successfully) and the model of the blockasset:add - New asset addedasset:remove - Asset removedasset:upload:start - Before the upload is startedasset:upload:end - After the upload is endedasset:upload:error - On any error in upload, passes the error as an argumentasset:upload:response - On upload response, passes the result as an argumentkeymap:add - New keymap added. The new keyamp object is passed as an argumentkeymap:remove - Keymap removed. The removed keyamp object is passed as an argumentkeymap:emit - Some keymap emitted, in arguments you get keymapId, shortcutUsed, Eventkeymap:emit:{keymapId} - keymapId emitted, in arguments you get keymapId, shortcutUsed, EventstyleManager:change - Triggered on style property change from new selected component, the view of the property is passed as an argument to the callbackstyleManager:change:{propertyName} - As above but for a specific style propertystorage:start - Before the storage request is startedstorage:start:store - Before the store request. The object to store is passed as an argumnet (which you can edit)storage:start:load - Before the load request. Items to load are passed as an argumnet (which you can edit)storage:load - Triggered when something was loaded from the storage, loaded object passed as an argumnetstorage:store - Triggered when something is stored to the storage, stored object passed as an argumnetstorage:end - After the storage request is endedstorage:end:store - After the store requeststorage:end:load - After the load requeststorage:error - On any error on storage request, passes the error as an argumentstorage:error:store - Error on store request, passes the error as an argumentstorage:error:load - Error on load request, passes the error as an argumentcanvas:dragenter - When something is dragged inside the canvas, DataTransfer instance passed as an argumentcanvas:dragover - When something is dragging on canvas, DataTransfer instance passed as an argumentcanvas:drop - Something is dropped in canvas, DataTransfer instance and the dropped model are passed as argumentscanvas:dragend - When a drag operation is ended, DataTransfer instance passed as an argumentcanvas:dragdata - On any dataTransfer parse, DataTransfer instance and the result are passed as arguments.
+By changing result.content you're able to customize what is droppedselector:add - Triggers when a new selector/class is createdrte:enable - RTE enabled. The view, on which RTE is enabled, is passed as an argumentrte:disable - RTE disabled. The view, on which RTE is disabled, is passed as an argumentrun:{commandName} - Triggered when some command is called to run (eg. editor.runCommand('preview'))stop:{commandName} - Triggered when some command is called to stop (eg. editor.stopCommand('preview'))run:{commandName}:before - Triggered before the command is calledstop:{commandName}:before - Triggered before the command is called to stopabort:{commandName} - Triggered when the command execution is aborted (editor.on(run:preview:before, opts => opts.abort = 1);)canvasScroll - Triggered when the canvas is scrolleundo - Undo executedredo - Redo executedload - When the editor is loadedReturns configuration object
propstring? Property nameReturns any Returns the configuration object or +the value of the specified property
Returns HTML built inside canvas
optsReturns string HTML string
Returns CSS built inside canvas
optsObject Options (optional, default {})Returns string CSS string
Returns JS of all components
Returns string JS string
Returns components in JSON format object
Returns Object
Set components inside editor's canvas. This method overrides actual components
editor.setComponents('<div class="cls">New component</div>');
+// or
+editor.setComponents({
+ type: 'text',
+ classes:['cls'],
+ content: 'New component'
+});
+Returns this
Add components
components(Array<Object> | Object | string) HTML string or components modeloptsObject Options
+opts.avoidUpdateStyleBoolean If the HTML string contains styles,
+by default, they will be created and, if already exist, updated. When this option
+is true, styles already created will not be updated. (optional, default false)editor.addComponents('<div class="cls">New component</div>');
+// or
+editor.addComponents({
+ type: 'text',
+ classes:['cls'],
+ content: 'New component'
+});
+Returns (Model | Array<Model>)
Returns style in JSON format object
Returns Object
Set style inside editor's canvas. This method overrides actual style
editor.setStyle('.cls{color: red}');
+//or
+editor.setStyle({
+ selectors: ['cls']
+ style: { color: 'red' }
+});
+Returns this
Returns the last selected component, if there is one
Returns Model
Returns an array of all selected components
Returns Array
Get a stylable entity from the selected component. +If you select a component without classes the entity is the Component +itself and all changes will go inside its 'style' attribute. Otherwise, +if the selected component has one or more classes, the function will +return the corresponding CSS Rule
Returns Model
Select a component
el(Component | HTMLElement) Component to select// Select dropped block
+editor.on('block:drag:stop', function(model) {
+ editor.select(model);
+});
+Returns this
Add component to selection
el(Component | HTMLElement | Array) Component to selecteditor.selectAdd(model);
+Returns this
Remove component from selection
el(Component | HTMLElement | Array) Component to selecteditor.selectRemove(model);
+Returns this
Toggle component selection
el(Component | HTMLElement | Array) Component to selecteditor.selectToggle(model);
+Returns this
Set device to the editor. If the device exists it will +change the canvas to the proper width
namestring Name of the deviceeditor.setDevice('Tablet');
+Returns this
Return the actual active device
var device = editor.getDevice();
+console.log(device);
+// 'Tablet'
+Returns string Device name
Execute command
editor.runCommand('myCommand', {someValue: 1});
+Returns any The return is defined by the command
Stop the command if stop method was provided
editor.stopCommand('myCommand', {someValue: 1});
+Returns any The return is defined by the command
Store data to the current storage
clbFunction Callback functionReturns Object Stored data
Load data from the current storage
clbFunction Callback functionReturns Object Stored data
Returns container element. The one which was indicated as 'container' +on init method
Returns HTMLElement
Return the count of changes made to the content and not yet stored.
+This count resets at any store()
Returns number
Replace the built-in Rich Text Editor with a custom one.
objObject Custom RTE Interfaceeditor.setCustomRte({
+ // Function for enabling custom RTE
+ // el is the HTMLElement of the double clicked Text Component
+ // rte is the same instance you have returned the first time you call
+ // enable(). This is useful if need to check if the RTE is already enabled so
+ // ion this case you'll need to return the RTE and the end of the function
+ enable: function(el, rte) {
+ rte = new MyCustomRte(el, {}); // this depends on the Custom RTE API
+ ...
+ return rte; // return the RTE instance
+ },
+
+ // Disable the editor, called for example when you unfocus the Text Component
+ disable: function(el, rte) {
+ rte.blur(); // this depends on the Custom RTE API
+ }
+
+// Called when the Text Component is focused again. If you returned the RTE instance
+// from the enable function, the enable won't be called again instead will call focus,
+// in this case to avoid double binding of the editor
+ focus: function (el, rte) {
+ rte.focus(); // this depends on the Custom RTE API
+ }
+});
+Attach event
Returns this
Detach event
Returns this
Trigger event
eventstring Event to triggerReturns this
Destroy the editor
Render editor
Returns HTMLElement
+ ← + API Reference + + Asset Manager + → +
+ GrapesJS
+ Here you can find the documentation about GrapesJS' APIs. Mainly, you would use them for your editor to extend the basic functionality of the framework or you could also create a plugin and make those extensions reusable and available to others.
+ Editor + → +
+ GrapesJS
+ You can customize the initial state of the module from the editor initialization
const editor = grapesjs.init({
+ keymaps: {
+ // Object of keymaps
+ defaults: {
+ 'your-namespace:keymap-name' {
+ keys: '⌘+z, ctrl+z',
+ handler: 'some-command-id'
+ },
+ ...
+ }
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const keymaps = editor.Keymaps;
+Get module configurations
Returns Object Configuration object
Add new keymap
idstring Keymap idkeysstring Keymap keys, eg. ctrl+a, ⌘+z, ctrl+zhandler(Function | string) Keymap handler, might be a function// 'ns' is just a custom namespace
+keymaps.add('ns:my-keymap', '⌘+j, ⌘+u, ctrl+j, alt+u', editor => {
+ console.log('do stuff');
+});
+// or
+keymaps.add('ns:my-keymap', '⌘+s, ctrl+s', 'some-gjs-command');
+
+// listen to events
+editor.on('keymap:emit', (id, shortcut, e) => {
+ // ...
+})
+Returns Object Added keymap +or just a command id as a string
Get the keymap by id
idstring Keymap idkeymaps.get('ns:my-keymap');
+// -> {keys, handler};
+Returns Object Keymap object
Get all keymaps
keymaps.getAll();
+// -> {id1: {}, id2: {}};
+Returns Object
Remove the keymap by id
idstring Keymap idkeymaps.remove('ns:my-keymap');
+// -> {keys, handler};
+Returns Object Removed keymap
+ ← + Rich Text Editor + + Undo Manager + → +
+ GrapesJS
+ You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ modal: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const modal = editor.Modal;
+Open the modal window
Returns this
Close the modal window
Returns this
Checks if the modal window is open
Returns Boolean
Set the title to the modal window
titlestring Titlemodal.setTitle('New title');
+Returns this
Returns the title of the modal window
Returns string
Set the content of the modal window
content(string | HTMLElement) Contentmodal.setContent('<div>Some HTML content</div>');
+Returns this
Get the content of the modal window
Returns string
+ ← + CSS Composer + + Rich Text Editor + → +
+ GrapesJS
+ You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ panels: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const panelManager = editor.Panels;
+Returns the collection of panels
Returns Collection Collection of panel
Returns panels element
Returns HTMLElement
Add new panel to the collection
panel(Object | Panel) Object with right properties or an instance of Panelvar newPanel = panelManager.addPanel({
+ id: 'myNewPanel',
+ visible : true,
+ buttons : [...],
+});
+Returns Panel Added panel. Useful in case passed argument was an Object
Remove a panel from the collection
const newPanel = panelManager.removePanel({
+ id: 'myNewPanel',
+ visible : true,
+ buttons : [...],
+});
+
+const newPanel = panelManager.removePanel('myNewPanel');
+Returns Panel Removed panel. Useful in case passed argument was an Object
Get panel by ID
idstring Id stringvar myPanel = panelManager.getPanel('myNewPanel');
+Returns (Panel | null)
Add button to the panel
var newButton = panelManager.addButton('myNewPanel',{
+ id: 'myNewButton',
+ className: 'someClass',
+ command: 'someCommand',
+ attributes: { title: 'Some title'},
+ active: false,
+});
+// It's also possible to pass the command as an object
+// with .run and .stop methods
+...
+command: {
+ run: function(editor) {
+ ...
+ },
+ stop: function(editor) {
+ ...
+ }
+},
+// Or simply like a function which will be evaluated as a single .run command
+...
+command: function(editor) {
+ ...
+}
+Returns (Button | null) Added button. Useful in case passed button was an Object
Remove button from the panel
panelIdstring Panel's IDbutton(Object | Button | String) Button object or instance of Button or button idconst removedButton = panelManager.removeButton('myNewPanel',{
+ id: 'myNewButton',
+ className: 'someClass',
+ command: 'someCommand',
+ attributes: { title: 'Some title'},
+ active: false,
+});
+
+// It's also possible to use the button id
+const removedButton = panelManager.removeButton('myNewPanel','myNewButton');
+Returns (Button | null) Removed button.
Get button from the panel
var button = panelManager.getButton('myPanel','myButton');
+Returns (Button | null)
+ ← + DOM Components + + Style Manager + → +
+ GrapesJS
+ This module allows to customize the built-in toolbar of the Rich Text Editor and use commands from the HTML Editing APIs. +It's highly recommended to keep this toolbar as small as possible, especially from styling commands (eg. 'fontSize') and leave this task to the Style Manager
You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ rte: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const rte = editor.RichTextEditor;
+Add a new action to the built-in RTE toolbar
rte.add('bold', {
+ icon: '<b>B</b>',
+ attributes: {title: 'Bold',}
+ result: rte => rte.exec('bold')
+});
+rte.add('link', {
+ icon: document.getElementById('t'),
+ attributes: {title: 'Link',}
+ // Example on it's easy to wrap a selected content
+ result: rte => rte.insertHTML(`<a href="#">${rte.selection()}</a>`)
+});
+// An example with fontSize
+rte.add('fontSize', {
+ icon: `<select class="gjs-field">
+ <option>1</option>
+ <option>4</option>
+ <option>7</option>
+ </select>`,
+ // Bind the 'result' on 'change' listener
+ event: 'change',
+ result: (rte, action) => rte.exec('fontSize', action.btn.firstChild.value),
+ // Callback on any input change (mousedown, keydown, etc..)
+ update: (rte, action) => {
+ const value = rte.doc.queryCommandValue(action.name);
+ if (value != 'false') { // value is a string
+ action.btn.firstChild.value = value;
+ }
+ }
+ })
+Get the action by its name
namestring Action nameconst action = rte.get('bold');
+// {name: 'bold', ...}
+Returns Object
Get all actions
Returns Array
Remove the action from the toolbar
namestringconst action = rte.remove('bold');
+// {name: 'bold', ...}
+Returns Object Removed action
Get the toolbar element
Returns HTMLElement
+ ← + Modal + + Keymaps + → +
+ GrapesJS
+ Selectors in GrapesJS are used in CSS Composer inside Rules and in Components as classes. To get better this concept let's take +a look at this code:
span > #send-btn.btn{
+ ...
+}
+<span>
+ <button id="send-btn" class="btn"></button>
+</span>
+In this scenario we get:
tagidclassSo, for example, being btn the same class entity it'll be easier to refactor and track things.
You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ selectorManager: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const selectorManager = editor.SelectorManager;
+Get configuration object
Returns Object
Add a new selector to collection if it's not already exists. Class type is a default one
var selector = selectorManager.add('selectorName');
+// Same as
+var selector = selectorManager.add('selectorName', {
+ type: 1,
+ label: 'selectorName'
+});
+Returns Model
Add class selectors
sm.addClass('class1');
+sm.addClass('class1 class2');
+sm.addClass(['class1', 'class2']);
+// -> [SelectorObject, ...]
+Returns Array Array of added selectors
Get the selector by its name
var selector = selectorManager.get('selectorName');
+Returns (Model | null)
Get all selectors
Returns Collection
+ ← + Device Manager + + CSS Composer + → +
+ GrapesJS
+ You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ storageManager: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const storageManager = editor.StorageManager;
+Get configuration object
Returns Object
Checks if autosave is enabled
Returns Boolean
Set autosave value
Returns this
Returns number of steps required before trigger autosave
Returns number
Set steps required before trigger autosave
Returns this
Add new storage
storageManager.add('local2', {
+ load: function(keys, clb, clbErr) {
+ var res = {};
+ for (var i = 0, len = keys.length; i < len; i++){
+ var v = localStorage.getItem(keys[i]);
+ if(v) res[keys[i]] = v;
+ }
+ clb(res); // might be called inside some async method
+ // In case of errors...
+ // clbErr('Went something wrong');
+ },
+ store: function(data, clb, clbErr) {
+ for(var key in data)
+ localStorage.setItem(key, data[key]);
+ clb(); // might be called inside some async method
+ }
+});
+Returns this
Returns storage by id
idstring Storage IDReturns (Object | null)
Returns all storages
Returns Array
Returns current storage type
Returns string
Set current storage type
idstring Storage IDReturns this
Store key-value resources in the current storage
dataObject Data in key-value format, eg. {item1: value1, item2: value2}clbFunction Callback functionstorageManager.store({item1: value1, item2: value2});
+Returns (Object | null)
Load resource from the current storage by keys
storageManager.load(['item1', 'item2'], res => {
+ // res -> {item1: value1, item2: value2}
+});
+storageManager.load('item1', res => {
+// res -> {item1: value1}
+});
+Get current storage
Returns Storage
+ ← + Style Manager + + Device Manager + → +
+ GrapesJS
+ With Style Manager you build categories (called sectors) of CSS properties which could be used to customize the style of components. +You can customize the initial state of the module from the editor initialization, by passing the following Configuration Object
const editor = grapesjs.init({
+ styleManager: {
+ // options
+ }
+})
+Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const styleManager = editor.StyleManager;
+Get configuration object
Returns Object
Add new sector to the collection. If the sector with the same id already exists, +that one will be returned
var sector = styleManager.addSector('mySector',{
+ name: 'My sector',
+ open: true,
+ properties: [{ name: 'My property'}]
+});
+Returns Sector Added Sector
Get sector by id
idstring Sector idvar sector = styleManager.getSector('mySector');
+Returns (Sector | null)
Remove a sector by id
idstring Sector idconst removed = styleManager.removeSector('mySector');
+Returns Sector Removed sector
Get all sectors
Returns Sectors Collection of sectors
Add property to the sector identified by id
sectorIdstring Sector idpropertyObject Property object
+property.namestring Name of the property (optional, default '')property.propertystring CSS property, eg. min-height (optional, default '')property.typestring Type of the property: integer | radio | select | color | file | composite | stack (optional, default '')property.unitsArray<string> Unit of measure available, eg. ['px','%','em']. Only for integer type (optional, default [])property.unitstring Default selected unit from units. Only for integer type (optional, default '')property.minnumber Min possible value. Only for integer type (optional, default null)property.maxnumber Max possible value. Only for integer type (optional, default null)property.defaultsstring Default value (optional, default '')property.infostring Some description (optional, default '')property.iconstring Class name. If exists no text will be displayed (optional, default '')property.previewBoolean Show layers preview. Only for stack type (optional, default false)property.functionNamestring Indicates if value need to be wrapped in some function, for istance transform: rotate(90deg) (optional, default '')property.propertiesArray<Object> Nested properties for composite and stack type (optional, default [])property.layersArray<Object> Layers for stack properties (optional, default [])property.listArray<Object> List of possible options for radio and select types (optional, default [])var property = styleManager.addProperty('mySector',{
+ name: 'Minimum height',
+ property: 'min-height',
+ type: 'select',
+ defaults: '100px',
+ list: [{
+ value: '100px',
+ name: '100',
+ },{
+ value: '200px',
+ name: '200',
+ }],
+});
+Returns (Property | null) Added Property or null in case sector doesn't exist
Get property by its CSS name and sector id
var property = styleManager.getProperty('mySector','min-height');
+Returns (Property | null)
Remove a property from the sector
const property = styleManager.removeProperty('mySector', 'min-height');
+Returns Property Removed property
Get properties of the sector
sectorIdstring Sector idvar properties = styleManager.getProperties('mySector');
+Returns Properties Collection of properties
Get what to style inside Style Manager. If you select the component +without classes the entity is the Component itself and all changes will +go inside its 'style' property. Otherwise, if the selected component has +one or more classes, the function will return the corresponding CSS Rule
modelModelReturns Model
Add new property type
idstring Type IDdefinitionObject Definition of the type. Each definition contains
+model (business logic), view (presentation logic)
+and isType function which recognize the type of the
+passed entitystyleManager.addType('my-type', {
+ model: {},
+ view: {},
+ isType: (value) => {
+ if (value && value.type == 'my-type') {
+ return value;
+ }
+ },
+})
+Get type
idstring Type IDReturns Object Type definition
Get all types
Returns Array
Create new property from type
const propView = styleManager.createType('integer', {
+ model: {units: ['px', 'rem']}
+});
+propView.render();
+propView.model.on('change:value', ...);
+someContainer.appendChild(propView.el);
+Returns PropertyView
+ ← + Panels + + Storage Manager + → +
+ GrapesJS
+ This module allows to manage the stack of changes applied in canvas. +Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
const um = editor.UndoManager;
+Get module configurations
const config = um.getConfig();
+// { ... }
+Returns Object Configuration object
Add an entity (Model/Collection) to track +Note: New Components and CSSRules will be added automatically
entity(Model | Collection) Entity to trackum.add(someModelOrCollection);
+Returns this
Remove and stop tracking the entity (Model/Collection)
entity(Model | Collection) Entity to removeum.remove(someModelOrCollection);
+Returns this
Remove all entities
um.removeAll();
+Returns this
Start/resume tracking changes
um.start();
+Returns this
Stop tracking changes
um.stop();
+Returns this
Undo last change
um.undo();
+Returns this
Undo all changes
um.undoAll();
+Returns this
Redo last change
um.redo();
+Returns this
Redo all changes
um.redoAll();
+Returns this
Checks if exists an available undo
um.hasUndo();
+Returns Boolean
Checks if exists an available redo
um.hasRedo();
+Returns Boolean
Get stack of changes
const stack = um.getStack();
+stack.each(item => ...);
+Returns Collection
Clear the stack
um.clear();
+Returns this
+ ← + Keymaps +
+ GrapesJS
+ Coming soon