grapesjs-clot
Version:
Free and Open Source Web Builder Framework
284 lines (259 loc) • 7.14 kB
JavaScript
/**
* 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/modal_dialog/config/config.js)
* ```js
* 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
*
* ```js
* const modal = editor.Modal;
* ```
*
* ## Available Events
* * `modal:open` - Modal is opened
* * `modal:close` - Modal is closed
* * `modal` - Event triggered on any change related to the modal. An object containing all the available data about the triggered event is passed as an argument to the callback.
*
* ## Methods
* * [open](#open)
* * [close](#close)
* * [isOpen](#isopen)
* * [setTitle](#settitle)
* * [getTitle](#gettitle)
* * [setContent](#setcontent)
* * [getContent](#getcontent)
* * [onceClose](#onceclose)
* * [onceOpen](#onceopen)
*
* @module Modal
*/
import { debounce, isFunction, isString } from 'underscore';
import { createText } from '../utils/dom';
import defaults from './config/config';
import ModalM from './model/Modal';
import ModalView from './view/ModalView';
export default () => {
var c = {};
var model, modal;
const triggerEvent = (enable, em) => {
em && em.trigger(`modal:${enable ? 'open' : 'close'}`);
};
return {
/**
* Name of the module
* @type {String}
* @private
*/
name: 'Modal',
getConfig() {
return c;
},
/**
* Initialize module. Automatically called with a new instance of the editor
* @param {Object} config Configurations
* @private
*/
init(config = {}) {
c = {
...defaults,
...config
};
const em = c.em;
this.em = em;
var ppfx = c.pStylePrefix;
if (ppfx) c.stylePrefix = ppfx + c.stylePrefix;
model = new ModalM(c);
model.on('change:open', (m, enb) => triggerEvent(enb, em));
model.on(
'change',
debounce(() => {
const data = this._evData();
const { custom } = this.getConfig();
isFunction(custom) && custom(data);
em.trigger('modal', data);
})
);
return this;
},
_evData() {
const titl = this.getTitle();
const cnt = this.getContent();
const { open, attributes } = model.attributes;
return {
open,
attributes,
title: isString(titl) ? createText(titl) : titl,
content: isString(cnt) ? createText(cnt) : cnt.get ? cnt.get(0) : cnt,
close: () => this.close()
};
},
postRender(view) {
const el = view.model.getConfig().el || view.el;
const res = this.render();
res && res.appendTo(el);
},
/**
* Open the modal window
* @param {Object} [opts={}] Options
* @param {String|HTMLElement} [opts.title] Title to set for the modal
* @param {String|HTMLElement} [opts.content] Content to set for the modal
* @param {Object} [opts.attributes] Updates the modal wrapper with custom attributes
* @returns {this}
* @example
* modal.open({
* title: 'My title',
* content: 'My content',
* attributes: { class: 'my-class' },
* });
*/
open(opts = {}) {
const attr = opts.attributes || {};
opts.title && this.setTitle(opts.title);
opts.content && this.setContent(opts.content);
model.set('attributes', attr);
model.open();
modal && modal.updateAttr(attr);
return this;
},
/**
* Close the modal window
* @returns {this}
* @example
* modal.close();
*/
close() {
model.close();
return this;
},
/**
* Execute callback when the modal will be closed.
* The callback will be called one only time
* @param {Function} clb Callback to call
* @returns {this}
* @example
* modal.onceClose(() => {
* console.log('The modal is closed');
* });
*/
onceClose(clb) {
this.em.once('modal:close', clb);
return this;
},
/**
* Execute callback when the modal will be opened.
* The callback will be called one only time
* @param {Function} clb Callback to call
* @returns {this}
* @example
* modal.onceOpen(() => {
* console.log('The modal is opened');
* });
*/
onceOpen(clb) {
this.em.once('modal:open', clb);
return this;
},
/**
* Checks if the modal window is open
* @returns {Boolean}
* @example
* modal.isOpen(); // true | false
*/
isOpen() {
return !!model.get('open');
},
/**
* Set the title to the modal window
* @param {string | HTMLElement} title Title
* @returns {this}
* @example
* // pass a string
* modal.setTitle('Some title');
* // or an HTMLElement
* const el = document.createElement('div');
* el.innerText = 'New title';
* modal.setTitle(el);
*/
setTitle(title) {
model.set('title', title);
return this;
},
/**
* Returns the title of the modal window
* @returns {string | HTMLElement}
* @example
* modal.getTitle();
*/
getTitle() {
return model.get('title');
},
/**
* Set the content of the modal window
* @param {string | HTMLElement} content Content
* @returns {this}
* @example
* // pass a string
* modal.setContent('Some content');
* // or an HTMLElement
* const el = document.createElement('div');
* el.innerText = 'New content';
* modal.setContent(el);
*/
setContent(content) {
model.set('content', ' ');
model.set('content', content);
return this;
},
/**
* Get the content of the modal window
* @returns {string | HTMLElement}
* @example
* modal.getContent();
*/
getContent() {
return model.get('content');
},
/**
* Returns content element
* @return {HTMLElement}
* @private
*/
getContentEl() {
return modal.getContent().get(0);
},
/**
* Returns modal model
* @return {Model}
* @private
*/
getModel() {
return model;
},
/**
* Render the modal window
* @return {HTMLElement}
* @private
*/
render() {
if (this.getConfig().custom) return;
const View = ModalView.extend(c.extend);
const el = modal && modal.el;
modal = new View({
el,
model,
config: c
});
return modal.render().$el;
},
destroy() {
modal && modal.remove();
[c, model, modal].forEach(i => (i = {}));
this.em = {};
}
};
};