diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 5064e3f02..dbc72e320 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -58,6 +58,7 @@ module.exports = { '/api/': [ '', ['/api/editor', 'Editor'], + ['/api/canvas', 'Canvas'], ['/api/assets', 'Asset Manager'], ['/api/block_manager', 'Block Manager'], ['/api/commands', 'Commands'], diff --git a/docs/api.js b/docs/api.js index 14bb8dfe3..33749e140 100644 --- a/docs/api.js +++ b/docs/api.js @@ -20,6 +20,7 @@ const cmds = [ ['rich_text_editor/index.js', 'rich_text_editor.md'], ['keymaps/index.js', 'keymaps.md'], ['undo_manager/index.js', 'undo_manager.md'], + ['canvas/index.js', 'canvas.md'], ].map(entry => `${binRoot}documentation build ${srcRoot}/${entry[0]} -o ${docRoot}/api/${entry[1]} -f md --shallow --markdown-toc false`) .join(' && '); diff --git a/docs/api/canvas.md b/docs/api/canvas.md new file mode 100644 index 000000000..7a2c3c65d --- /dev/null +++ b/docs/api/canvas.md @@ -0,0 +1,153 @@ + + +## Canvas + +You can customize the initial state of the module from the editor initialization, by passing the following [Configuration Object][1] + +```js +const editor = grapesjs.init({ + canvas: { + // options + } +}) +``` + +Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance + +```js +const blockManager = editor.Canvas; +``` + +- [getConfig][2] +- [getElement][3] +- [getFrameEl][4] +- [getWindow][5] +- [getDocument][6] +- [getBody][7] +- [getWrapperEl][8] +- [setCustomBadgeLabel][9] +- [hasFocus][10] +- [scrollTo][11] + +## getConfig + +Get the configuration object + +Returns **[Object][12]** + +## getElement + +Get the canvas element + +Returns **[HTMLElement][13]** + +## getFrameEl + +Get the iframe element of the canvas + +Returns **[HTMLIFrameElement][14]** + +## getWindow + +Get the window instance of the iframe element + +Returns **[Window][15]** + +## getDocument + +Get the document of the iframe element + +Returns **HTMLDocument** + +## getBody + +Get the body of the iframe element + +Returns **[HTMLBodyElement][16]** + +## getWrapperEl + +Get the wrapper element containing all the components + +Returns **[HTMLElement][13]** + +## setCustomBadgeLabel + +Set custom badge naming strategy + +### Parameters + +- `f` **[Function][17]** + +### Examples + +```javascript +canvas.setCustomBadgeLabel(function(component){ + return component.getName(); +}); +``` + +## hasFocus + +Check if the canvas is focused + +Returns **[Boolean][18]** + +## scrollTo + +Scroll canvas to the element if it's not visible. The scrolling is +executed via `scrollIntoView` API and options of this method are +passed to it. For instance, you can scroll smoothly by using +`{ behavior: 'smooth' }`. + +### Parameters + +- `el` **([HTMLElement][13] | Component)** +- `opts` **[Object][12]** Options, same as options for `scrollIntoView` (optional, default `{}`) + - `opts.force` **[Boolean][18]** Force the scroll, even if the element is already visible (optional, default `false`) + +### Examples + +```javascript +const selected = editor.getSelected(); +// Scroll smoothly (this behavior can be polyfilled) +canvas.scrollTo(selected, { behavior: 'smooth' }); +// Force the scroll, even if the element is alredy visible +canvas.scrollTo(selected, { force: true }); +``` + +[1]: https://github.com/artf/grapesjs/blob/master/src/canvas/config/config.js + +[2]: #getconfig + +[3]: #getelement + +[4]: #getframeel + +[5]: #getwindow + +[6]: #getdocument + +[7]: #getbody + +[8]: #getwrapperel + +[9]: #setcustombadgelabel + +[10]: #hasfocus + +[11]: #scrollto + +[12]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object + +[13]: https://developer.mozilla.org/docs/Web/HTML/Element + +[14]: https://developer.mozilla.org/docs/Web/API/HTMLIFrameElement + +[15]: https://developer.mozilla.org/docs/Web/API/Window + +[16]: https://developer.mozilla.org/docs/Web/HTML/Element/body + +[17]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function + +[18]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean diff --git a/docs/api/commands.md b/docs/api/commands.md index ddc3220e9..2e4e57b76 100644 --- a/docs/api/commands.md +++ b/docs/api/commands.md @@ -21,6 +21,8 @@ const commands = editor.Commands; - [add][2] - [get][3] - [has][4] +- [run][5] +- [stop][6] ## add @@ -28,8 +30,8 @@ Add new command to the collection ### Parameters -- `id` **[string][5]** Command's ID -- `command` **([Object][6] \| [Function][7])** Object representing your command, +- `id` **[string][7]** Command's ID +- `command` **([Object][8] \| [Function][9])** 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). @@ -55,7 +57,7 @@ Get command by ID ### Parameters -- `id` **[string][5]** Command's ID +- `id` **[string][7]** Command's ID ### Examples @@ -64,7 +66,7 @@ var myCommand = commands.get('myCommand'); myCommand.run(); ``` -Returns **[Object][6]** Object representing the command +Returns **[Object][8]** Object representing the command ## has @@ -72,9 +74,43 @@ Check if command exists ### Parameters -- `id` **[string][5]** Command's ID +- `id` **[string][7]** Command's ID -Returns **[Boolean][8]** +Returns **[Boolean][10]** + +## run + +Execute the command + +### Parameters + +- `id` **[String][7]** Command ID +- `options` **[Object][8]** Options (optional, default `{}`) + +### Examples + +```javascript +commands.run('myCommand', { someOption: 1 }); +``` + +Returns **any** The return is defined by the command + +## stop + +Stop the command + +### Parameters + +- `id` **[String][7]** Command ID +- `options` **[Object][8]** Options (optional, default `{}`) + +### Examples + +```javascript +commands.stop('myCommand', { someOption: 1 }); +``` + +Returns **any** The return is defined by the command [1]: https://github.com/artf/grapesjs/blob/master/src/commands/config/config.js @@ -84,10 +120,14 @@ Returns **[Boolean][8]** [4]: #has -[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String +[5]: #run + +[6]: #stop + +[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String -[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object +[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object -[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function +[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function -[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean diff --git a/docs/api/modal_dialog.md b/docs/api/modal_dialog.md index f187f6189..f88c35fee 100644 --- a/docs/api/modal_dialog.md +++ b/docs/api/modal_dialog.md @@ -30,6 +30,12 @@ const modal = editor.Modal; Open the modal window +### Parameters + +- `opts` **[Object][9]** Options (optional, default `{}`) + - `opts.title` **([String][10] \| [HTMLElement][11])?** Title to set for the modal + - `opts.content` **([String][10] \| [HTMLElement][11])?** Content to set for the modal + Returns **this** ## close @@ -42,7 +48,7 @@ Returns **this** Checks if the modal window is open -Returns **[Boolean][9]** +Returns **[Boolean][12]** ## setTitle @@ -104,8 +110,10 @@ Returns **[string][10]** [8]: #getcontent -[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object [10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String [11]: https://developer.mozilla.org/docs/Web/HTML/Element + +[12]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean diff --git a/package-lock.json b/package-lock.json index 0e4ba5957..f394a7594 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1426,9 +1426,9 @@ } }, "@vue/component-compiler-utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.1.1.tgz", - "integrity": "sha512-iP+5zKyAwkDvRLZMEntCPbYzd6lWnbqYcpg5waHj0QPm4RC7zWt5PQ0EkbVZVSt5KHbAHxeWGlvEr2YmzGIpFw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.1.2.tgz", + "integrity": "sha512-ISkl1xQhYgPwxlhq9KPUgjWurTS4atdvMhc0cpIPbXdyCDEKkDRS4wsDM6jNtoMSVKoDLfOiCPP4TZTwAu0uEQ==", "dev": true, "requires": { "consolidate": "^0.15.1", @@ -1437,7 +1437,7 @@ "merge-source-map": "^1.1.0", "postcss": "^6.0.20", "postcss-selector-parser": "^3.1.1", - "prettier": "^1.13.7", + "prettier": "1.13.7", "source-map": "^0.5.6", "vue-template-es2015-compiler": "^1.6.0" }, @@ -1452,6 +1452,12 @@ "indexes-of": "^1.0.1", "uniq": "^1.0.1" } + }, + "prettier": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.13.7.tgz", + "integrity": "sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==", + "dev": true } } }, diff --git a/src/canvas/config/config.js b/src/canvas/config/config.js index e69831d7a..1cd99480a 100644 --- a/src/canvas/config/config.js +++ b/src/canvas/config/config.js @@ -1,33 +1,27 @@ module.exports = { stylePrefix: 'cv-', - // Coming soon - rulers: false, - /* - * Append external scripts in head of the iframe before renderBody content - * In this case, you have to add them manually later in the final HTML page + * Append external scripts to the `` of the iframe. + * Be aware that these scripts will not be printed in the export code * @example - * scripts: [ - * 'https://...', - * ] + * scripts: [ 'https://...1.js', 'https://...2.js' ] */ scripts: [], /* - * Append external styles. This styles won't be added to the final HTML/CSS + * Append external styles to the `` of the iframe + * Be aware that these styles will not be printed in the export code * @example - * styles: [ - * 'https://...', - * ] + * styles: [ 'https://...1.css', 'https://...2.css' ] */ styles: [], /** * Add custom badge naming strategy * @example - * customBadgeLabel: function(ComponentModel) { - * return ComponentModel.getName(); + * customBadgeLabel: function(component) { + * return component.getName(); * } */ customBadgeLabel: '' diff --git a/src/canvas/index.js b/src/canvas/index.js index a14aad27c..108eb560c 100644 --- a/src/canvas/index.js +++ b/src/canvas/index.js @@ -1,3 +1,33 @@ +/** + * You can customize the initial state of the module from the editor initialization, by passing the following [Configuration Object](https://github.com/artf/grapesjs/blob/master/src/canvas/config/config.js) + * ```js + * const editor = grapesjs.init({ + * canvas: { + * // options + * } + * }) + * ``` + * + * Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance + * + * ```js + * const canvas = editor.Canvas; + * ``` + * + * * [getConfig](#getconfig) + * * [getElement](#getelement) + * * [getFrameEl](#getframeel) + * * [getWindow](#getwindow) + * * [getDocument](#getdocument) + * * [getBody](#getbody) + * * [getWrapperEl](#getwrapperel) + * * [setCustomBadgeLabel](#setcustombadgelabel) + * * [hasFocus](#hasfocus) + * * [scrollTo](#scrollto) + * + * @module Canvas + */ + import { on, off, hasDnd, getElement } from 'utils/mixins'; import Droppable from 'utils/Droppable'; @@ -28,6 +58,7 @@ module.exports = () => { /** * Initialize module. Automatically called with a new instance of the editor * @param {Object} config Configurations + * @private */ init(config) { c = config || {}; @@ -54,7 +85,7 @@ module.exports = () => { }, /** - * Return config object + * Get the configuration object * @return {Object} */ getConfig() { @@ -64,14 +95,14 @@ module.exports = () => { /** * Add wrapper * @param {Object} wrp Wrapper - * + * @private * */ setWrapper(wrp) { canvas.set('wrapper', wrp); }, /** - * Returns canvas element + * Get the canvas element * @return {HTMLElement} */ getElement() { @@ -79,39 +110,39 @@ module.exports = () => { }, /** - * Returns frame element of the canvas - * @return {HTMLElement} + * Get the iframe element of the canvas + * @return {HTMLIFrameElement} */ getFrameEl() { return CanvasView.frame.el; }, /** - * Returns the frame document - * @return {HTMLElement} + * Get the window instance of the iframe element + * @return {Window} */ - getDocument() { - return this.getFrameEl().contentDocument; + getWindow() { + return this.getFrameEl().contentWindow; }, /** - * Returns the frame's window - * @return {HTMLElement} + * Get the document of the iframe element + * @return {HTMLDocument} */ - getWindow() { - return this.getFrameEl().contentWindow; + getDocument() { + return this.getFrameEl().contentDocument; }, /** - * Returns body element of the frame - * @return {HTMLElement} + * Get the body of the iframe element + * @return {HTMLBodyElement} */ getBody() { - return CanvasView.frame.el.contentDocument.body; + return this.getDocument().body; }, /** - * Returns body wrapper element of the frame + * Get the wrapper element containing all the components * @return {HTMLElement} */ getWrapperEl() { @@ -121,6 +152,7 @@ module.exports = () => { /** * Returns element containing all canvas tools * @return {HTMLElement} + * @private */ getToolsEl() { return CanvasView.toolsEl; @@ -129,6 +161,7 @@ module.exports = () => { /** * Returns highlighter element * @return {HTMLElement} + * @private */ getHighlighter() { return CanvasView.hlEl; @@ -137,6 +170,7 @@ module.exports = () => { /** * Returns badge element * @return {HTMLElement} + * @private */ getBadgeEl() { return CanvasView.badgeEl; @@ -145,6 +179,7 @@ module.exports = () => { /** * Returns placer element * @return {HTMLElement} + * @private */ getPlacerEl() { return CanvasView.placerEl; @@ -162,6 +197,7 @@ module.exports = () => { /** * Returns toolbar element * @return {HTMLElement} + * @private */ getToolbarEl() { return CanvasView.toolbarEl; @@ -170,6 +206,7 @@ module.exports = () => { /** * Returns resizer element * @return {HTMLElement} + * @private */ getResizerEl() { return CanvasView.resizerEl; @@ -178,6 +215,7 @@ module.exports = () => { /** * Returns offset viewer element * @return {HTMLElement} + * @private */ getOffsetViewerEl() { return CanvasView.offsetEl; @@ -186,6 +224,7 @@ module.exports = () => { /** * Returns fixed offset viewer element * @return {HTMLElement} + * @private */ getFixedOffsetViewerEl() { return CanvasView.fixedOffsetEl; @@ -193,6 +232,7 @@ module.exports = () => { /** * Render canvas + * @private * */ render() { return CanvasView.render().el; @@ -213,7 +253,7 @@ module.exports = () => { }, /** - * Get the offset of the element + * Get the offset of the passed component element * @param {HTMLElement} el * @return {Object} * @private @@ -226,8 +266,8 @@ module.exports = () => { * Set custom badge naming strategy * @param {Function} f * @example - * canvas.setCustomBadgeLabel(function(model){ - * return ComponentModel.getName(); + * canvas.setCustomBadgeLabel(function(component){ + * return component.getName(); * }); */ setCustomBadgeLabel(f) { @@ -238,6 +278,7 @@ module.exports = () => { * Get element position relative to the canvas * @param {HTMLElement} el * @return {Object} + * @private */ getElementPos(el, opts) { return CanvasView.getElementPos(el, opts); @@ -257,6 +298,7 @@ module.exports = () => { * @param {Object} options Custom options * @param {Boolean} options.toRight Set to true if you want the toolbar attached to the right * @return {Object} + * @private */ getTargetToElementDim(target, element, options) { var opts = options || {}; @@ -305,6 +347,7 @@ module.exports = () => { * canvas area, which is in the iframe * @param {Event} e * @return {Object} + * @private */ getMouseRelativePos(e, options) { var opts = options || {}; @@ -333,6 +376,7 @@ module.exports = () => { * X and Y mouse position relative to the canvas * @param {Event} e * @return {Object} + * @private */ getMouseRelativeCanvas(e, options) { var opts = options || {}; @@ -359,8 +403,8 @@ module.exports = () => { /** * Detects if some input is focused (input elements, text components, etc.) - * Used internally, for example, to avoid undo/redo in text editing mode * @return {Boolean} + * @private */ isInputFocused() { return this.getFrameEl().contentDocument.activeElement.tagName !== 'BODY'; @@ -369,16 +413,17 @@ module.exports = () => { /** * Scroll canvas to the element if it's not visible. The scrolling is * executed via `scrollIntoView` API and options of this method are - * passed to it. For instance, you can scroll smoothly with - * `{ behavior: 'smooth' }`. You can also force the scroll + * passed to it. For instance, you can scroll smoothly by using + * `{ behavior: 'smooth' }`. * @param {HTMLElement|Component} el * @param {Object} [opts={}] Options, same as options for `scrollIntoView` + * @param {Boolean} [opts.force=false] Force the scroll, even if the element is already visible * @example * const selected = editor.getSelected(); * // Scroll smoothly (this behavior can be polyfilled) - * cv.scrollTo(selected, { behavior: 'smooth' }); + * canvas.scrollTo(selected, { behavior: 'smooth' }); * // Force the scroll, even if the element is alredy visible - * cv.scrollTo(selected, { force: true }); + * canvas.scrollTo(selected, { force: true }); */ scrollTo(el, opts = {}) { const elem = getElement(el); @@ -391,6 +436,7 @@ module.exports = () => { /** * Start autoscroll + * @private */ startAutoscroll() { this.dragging = 1; @@ -405,6 +451,9 @@ module.exports = () => { }, 0); }, + /** + * @private + */ autoscroll(e) { e.preventDefault(); if (this.dragging) { @@ -430,6 +479,7 @@ module.exports = () => { /** * Stop autoscroll + * @private */ stopAutoscroll() { this.dragging = 0; @@ -450,6 +500,7 @@ module.exports = () => { * Returns wrapper element * @return {HTMLElement} * ???? + * @private */ getFrameWrapperEl() { return CanvasView.frame.getWrapper();