UNPKG

grapesjs_codeapps

Version:

Free and Open Source Web Builder Framework/SC Modification

475 lines (419 loc) 13.8 kB
/** * 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/commands/config/config.js) * ```js * 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 * * ```js * const commands = editor.Commands; * ``` * * * [add](#add) * * [get](#get) * * [getAll](#getall) * * [has](#has) * * [run](#run) * * [stop](#stop) * * [isActive](#isactive) * * [getActive](#getactive) * * @module Commands */ import { isFunction, isUndefined } from 'underscore'; import CommandAbstract from './view/CommandAbstract'; module.exports = () => { let em; var c = {}, commands = {}, defaultCommands = {}, defaults = require('./config/config'); const active = {}; // Need it here as it would be used below const add = function(id, obj) { if (isFunction(obj)) obj = { run: obj }; if (!obj.stop) obj.noStop = 1; delete obj.initialize; obj.id = id; commands[id] = CommandAbstract.extend(obj); return this; }; return { CommandAbstract, /** * Name of the module * @type {String} * @private */ name: 'Commands', /** * Initialize module. Automatically called with a new instance of the editor * @param {Object} config Configurations * @private */ init(config) { c = config || {}; for (var name in defaults) { if (!(name in c)) c[name] = defaults[name]; } em = c.em; var ppfx = c.pStylePrefix; if (ppfx) c.stylePrefix = ppfx + c.stylePrefix; // Load commands passed via configuration for (var k in c.defaults) { var obj = c.defaults[k]; if (obj.id) this.add(obj.id, obj); } const ViewCode = require('./view/ExportTemplate'); defaultCommands['select-comp'] = require('./view/SelectComponent'); defaultCommands['create-comp'] = require('./view/CreateComponent'); defaultCommands['delete-comp'] = require('./view/DeleteComponent'); defaultCommands['image-comp'] = require('./view/ImageComponent'); defaultCommands['move-comp'] = require('./view/MoveComponent'); defaultCommands['text-comp'] = require('./view/TextComponent'); defaultCommands['insert-custom'] = require('./view/InsertCustom'); defaultCommands['export-template'] = ViewCode; defaultCommands['sw-visibility'] = require('./view/SwitchVisibility'); defaultCommands['open-layers'] = require('./view/OpenLayers'); defaultCommands['open-sm'] = require('./view/OpenStyleManager'); defaultCommands['open-tm'] = require('./view/OpenTraitManager'); defaultCommands['template-list'] = require('./view/TemplateList'); defaultCommands['location-manager'] = require('./view/LocationManager'); defaultCommands['bg-manager'] = require('./view/BgManager'); defaultCommands['open-blocks'] = require('./view/OpenBlocks'); defaultCommands['open-assets'] = require('./view/OpenAssets'); defaultCommands['show-offset'] = require('./view/ShowOffset'); defaultCommands['select-parent'] = require('./view/SelectParent'); defaultCommands.fullscreen = require('./view/Fullscreen'); defaultCommands.preview = require('./view/Preview'); defaultCommands.resize = require('./view/Resize'); defaultCommands.drag = require('./view/Drag'); defaultCommands['tlb-delete'] = { run(ed) { return ed.runCommand('core:component-delete'); } }; defaultCommands['tlb-clone'] = { run(ed) { ed.runCommand('core:copy'); ed.runCommand('core:paste'); } }; defaultCommands['tlb-move'] = { run(ed, sender, opts) { let dragger; const em = ed.getModel(); const event = opts && opts.event; const sel = ed.getSelected(); const selAll = [...ed.getSelectedAll()]; const toolbarStyle = ed.Canvas.getToolbarEl().style; const nativeDrag = event && event.type == 'dragstart'; const defComOptions = { preserveSelected: 1 }; const hideTlb = () => { toolbarStyle.display = 'none'; em.stopDefault(defComOptions); }; if (!sel || !sel.get('draggable')) { console.warn('The element is not draggable'); return; } // Without setTimeout the ghost image disappears nativeDrag ? setTimeout(() => hideTlb, 0) : hideTlb(); const onStart = (e, opts) => { var el = opts.el; el.style.position = 'absolute'; el.style.margin = 0; }; const onEnd = (e, opts) => { em.runDefault(defComOptions); selAll.forEach(sel => sel.set('status', 'selected')); ed.select(selAll); sel.emitUpdate(); dragger && dragger.blur(); }; const onDrag = (e, opts) => { // console.log('Delta ', opts.delta); // console.log('Current ', opts.current); }; if (em.get('designerMode')) { // TODO move grabbing func in editor/canvas from the Sorter dragger = editor.runCommand('drag', { el: sel.view.el, options: { event, onStart, onDrag, onEnd } }); } else { if (nativeDrag) { event.dataTransfer.setDragImage(sel.view.el, 0, 0); //sel.set('status', 'freezed'); } const cmdMove = ed.Commands.get('move-comp'); cmdMove.onEndMoveFromModel = onEnd; cmdMove.initSorterFromModels(selAll); } selAll.forEach(sel => sel.set('status', 'freezed-selected')); } }; defaultCommands['tlb-drag'] = { run(ed, sender, opts) { let dragger; const em = ed.getModel(); const event = opts && opts.event; const sel = ed.getSelected(); const selAll = [...ed.getSelectedAll()]; const style = sel.getStyle(); const toolbarStyle = ed.Canvas.getToolbarEl().style; const nativeDrag = event && event.type == 'dragstart'; const defComOptions = { preserveSelected: 1 }; const hideTlb = () => { toolbarStyle.display = 'none'; em.stopDefault(defComOptions); }; if (!sel || !sel.get('draggable')) { console.warn('The element is not draggable'); return; } // Without setTimeout the ghost image disappears nativeDrag ? setTimeout(() => hideTlb, 0) : hideTlb(); const onStart = (e, opts) => { var el = opts.el; // el.style.position = 'absolute'; // el.style.margin = 0; }; const onEnd = (e, opts) => { em.runDefault(defComOptions); selAll.forEach(sel => sel.set('status', 'selected')); ed.select(selAll); updateStyle('position', 'absolute'); updateStyle('top', opts['end'].y.toFixed() + 'px'); updateStyle('left', opts['end'].x.toFixed() + 'px'); sel.emitUpdate(); dragger && dragger.blur(); }; const onDrag = (e, opts) => { // console.log(e); // console.log('Delta ', opts.delta); // console.log('Current ', opts.current); }; const updateStyle = (property, value) => { if (value) { style[property] = value; } else { delete style[property]; } sel.setStyle(style); }; if (!em.get('designerMode')) { // TODO move grabbing func in editor/canvas from the Sorter dragger = ed.runCommand('drag', { el: sel.view.el, options: { event, onStart, onDrag, onEnd } }); } else { if (nativeDrag) { event.dataTransfer.setDragImage(sel.view.el, 0, 0); //sel.set('status', 'freezed'); } const cmdMove = ed.Commands.get('move-comp'); cmdMove.onEndMoveFromModel = onEnd; cmdMove.initSorterFromModels(selAll); } selAll.forEach(sel => sel.set('status', 'freezed-selected')); } }; // Core commands defaultCommands['core:undo'] = e => e.UndoManager.undo(); defaultCommands['core:redo'] = e => e.UndoManager.redo(); [ ['copy', 'CopyComponent'], ['paste', 'PasteComponent'], ['component-next', 'ComponentNext'], ['component-prev', 'ComponentPrev'], ['component-enter', 'ComponentEnter'], ['component-exit', 'ComponentExit'], ['canvas-clear', 'CanvasClear'], ['component-delete', 'ComponentDelete'], ['component-style-clear', 'ComponentStyleClear'] ].forEach( item => (defaultCommands[`core:${item[0]}`] = require(`./view/${ item[1] }`).run) ); if (c.em) c.model = c.em.get('Canvas'); this.loadDefaultCommands(); return this; }, /** * Add new command to the collection * @param {string} id Command's ID * @param {Object|Function} command 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). * @return {this} * @example * commands.add('myCommand', { * run(editor, sender) { * alert('Hello world!'); * }, * stop(editor, sender) { * }, * }); * // As a function * commands.add('myCommand2', editor => { ... }); * */ add, /** * Get command by ID * @param {string} id Command's ID * @return {Object} Object representing the command * @example * var myCommand = commands.get('myCommand'); * myCommand.run(); * */ get(id) { var el = commands[id]; if (typeof el == 'function') { el = new el(c); commands[id] = el; } return el; }, /** * Check if command exists * @param {string} id Command's ID * @return {Boolean} * */ has(id) { return !!commands[id]; }, /** * Get an object containing all the commands * @return {Object} */ getAll() { return commands; }, /** * Execute the command * @param {String} id Command ID * @param {Object} [options={}] Options * @return {*} The return is defined by the command * @example * commands.run('myCommand', { someOption: 1 }); */ run(id, options = {}) { return this.runCommand(this.get(id), options); }, /** * Stop the command * @param {String} id Command ID * @param {Object} [options={}] Options * @return {*} The return is defined by the command * @example * commands.stop('myCommand', { someOption: 1 }); */ stop(id, options = {}) { return this.stopCommand(this.get(id), options); }, /** * Check if the command is active. You activate commands with `run` * and disable them with `stop`. If the command was created without `stop` * method it can't be registered as active * @param {String} id Command id * @return {Boolean} * @example * const cId = 'some-command'; * commands.run(cId); * commands.isActive(cId); * // -> true * commands.stop(cId); * commands.isActive(cId); * // -> false */ isActive(id) { return this.getActive().hasOwnProperty(id); }, /** * Get all active commands * @return {Object} * @example * console.log(commands.getActive()); * // -> { someCommand: itsLastReturn, anotherOne: ... }; */ getActive() { return active; }, /** * Load default commands * @return {this} * @private * */ loadDefaultCommands() { for (var id in defaultCommands) { this.add(id, defaultCommands[id]); } return this; }, /** * Run command via its object * @param {Object} command * @param {Object} options * @return {*} Result of the command * @private */ runCommand(command, options = {}) { let result; if (command && command.run) { const id = command.id; const editor = em.get('Editor'); result = command.callRun(editor, options); if (id && command.stop && !command.noStop) { active[id] = result; } } return result; }, /** * [runCommand description] * @param {Object} command * @param {Object} options * @return {*} Result of the command * @private */ stopCommand(command, options = {}) { let result; if (command && command.run) { const id = command.id; const editor = em.get('Editor'); result = command.callStop(editor, options); if (id) delete active[id]; } return result; }, /** * Create anonymous Command instance * @param {Object} command Command object * @return {Command} * @private * */ create(command) { const cmd = CommandAbstract.extend(command); return new cmd(c); } }; };