mirror of https://github.com/artf/grapesjs.git
committed by
GitHub
45 changed files with 4508 additions and 4108 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 3.1 KiB |
@ -1,6 +1,35 @@ |
|||
import Backbone from 'backbone'; |
|||
import Backbone, { AddOptions } from 'backbone'; |
|||
import { isArray, isObject, isUndefined } from 'underscore'; |
|||
import Model from './Model'; |
|||
|
|||
export default class Collection< |
|||
TModel extends Model = Model |
|||
> extends Backbone.Collection<TModel> {} |
|||
type Module<TModel extends Model> = TModel extends Model<infer M> ? M : unknown; |
|||
type ModelConstructor<TModel extends Model> = { new (mod: Module<TModel>, attr: any): TModel }; |
|||
|
|||
export default class Collection<TModel extends Model = Model> extends Backbone.Collection<TModel> { |
|||
module!: Module<TModel>; |
|||
private newModel!: ModelConstructor<TModel>; |
|||
|
|||
add(model: Array<Record<string, any>> | TModel, options?: AddOptions): TModel; |
|||
add(models: Array<Array<Record<string, any>> | TModel>, options?: AddOptions): TModel[]; |
|||
add(model?: unknown, options?: AddOptions): any { |
|||
//Note: the undefined case needed because backbonejs not handle the reset() correctly
|
|||
var models = isArray(model) ? model : !isUndefined(model) ? [model] : undefined; |
|||
|
|||
models = models?.map(m => (m instanceof this.newModel ? m : new this.newModel(this.module, m))) ?? [undefined]; |
|||
|
|||
return super.add(isArray(model) ? models : models[0], options); |
|||
} |
|||
|
|||
constructor( |
|||
module: Module<TModel>, |
|||
models: TModel[] | Array<Record<string, any>>, |
|||
modelConstructor: ModelConstructor<TModel> |
|||
) { |
|||
super(models, { module, modelConstructor }); |
|||
} |
|||
|
|||
preinitialize(models?: TModel[] | Array<Record<string, any>>, options?: any) { |
|||
this.newModel = options.modelConstructor; |
|||
this.module = options.module; |
|||
} |
|||
} |
|||
|
|||
@ -1,29 +1,46 @@ |
|||
import Backbone from 'backbone'; |
|||
import Collection from './Collection'; |
|||
import Model from './Model'; |
|||
import Module, { IBaseModule } from './Module'; |
|||
import { IBaseModule } from './Module'; |
|||
|
|||
export default class View<TModel extends Model = Model, TElement extends Element = HTMLElement> extends Backbone.View< |
|||
TModel, |
|||
TElement |
|||
> { |
|||
type ModuleFromModel<TModel extends Model> = TModel extends Model<infer M> ? M : unknown; |
|||
type Module<TItem extends Model | Collection> = TItem extends Collection<infer M> |
|||
? ModuleFromModel<M> |
|||
: TItem extends Model<infer M> |
|||
? M |
|||
: unknown; |
|||
|
|||
type TCollection<TItem extends Model | Collection> = TItem extends Collection ? TItem : unknown; |
|||
|
|||
export default class View< |
|||
TModel extends Model | Collection = Model, |
|||
TElement extends Element = HTMLElement |
|||
> extends Backbone.View<TModel extends Model ? TModel : undefined, TElement> { |
|||
protected get pfx() { |
|||
return this.ppfx + this.config.stylePrefix || ''; |
|||
return this.ppfx + (this.config as any).stylePrefix || ''; |
|||
} |
|||
|
|||
protected get ppfx() { |
|||
return (this.em.config as any).stylePrefix || ''; |
|||
return this.em.config.stylePrefix || ''; |
|||
} |
|||
|
|||
protected get module(): TModel extends Model<infer M> ? M : unknown { |
|||
//console.log((this.collection.first as any).module)
|
|||
return this.model?.module ?? (this.collection as any).module; |
|||
collection!: TModel extends Model ? Collection<Model> : TModel; |
|||
|
|||
protected get module(): Module<TModel> { |
|||
return (this.model as any)?.module ?? this.collection.module; |
|||
} |
|||
|
|||
protected get em() { |
|||
return this.module.em; |
|||
} |
|||
|
|||
protected get config(): TModel extends Model<infer M> ? (M extends IBaseModule<infer C> ? C : unknown) : unknown { |
|||
protected get config(): Module<TModel> extends IBaseModule<infer C> ? C : unknown { |
|||
return this.module.config as any; |
|||
} |
|||
|
|||
public className!: string; |
|||
|
|||
preinitialize(options?: any) { |
|||
this.className = ''; |
|||
} |
|||
} |
|||
|
|||
@ -1,283 +0,0 @@ |
|||
/** |
|||
* 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 = {}; |
|||
}, |
|||
}; |
|||
}; |
|||
@ -0,0 +1,264 @@ |
|||
/** |
|||
* 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 { EventHandler } from 'backbone'; |
|||
import { debounce, isFunction, isString } from 'underscore'; |
|||
import { Module } from '../abstract'; |
|||
import EditorView from '../editor/view/EditorView'; |
|||
import EditorModel from '../editor/model/Editor'; |
|||
import { createText } from '../utils/dom'; |
|||
import defaults from './config/config'; |
|||
import ModalM from './model/Modal'; |
|||
import ModalView from './view/ModalView'; |
|||
|
|||
export default class ModalManager extends Module<typeof defaults> { |
|||
modal?: ModalView; |
|||
|
|||
/** |
|||
* Initialize module. Automatically called with a new instance of the editor |
|||
* @param {Object} config Configurations |
|||
* @private |
|||
*/ |
|||
constructor(em: EditorModel) { |
|||
super(em, 'Modal', defaults); |
|||
|
|||
this.model = new ModalM(this); |
|||
this.model.on('change:open', (m: ModalM, enable: boolean) => { |
|||
em.trigger(`modal:${enable ? 'open' : 'close'}`); |
|||
}); |
|||
this.model.on( |
|||
'change', |
|||
debounce(() => { |
|||
const data = this._evData(); |
|||
const { custom } = this.config; |
|||
//@ts-ignore
|
|||
isFunction(custom) && custom(data); |
|||
em.trigger('modal', data); |
|||
}, 0) |
|||
); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
_evData() { |
|||
const titl = this.getTitle(); |
|||
const cnt = this.getContent(); |
|||
const { open, attributes } = this.model.attributes; |
|||
return { |
|||
open, |
|||
attributes, |
|||
title: isString(titl) ? createText(titl) : titl, |
|||
//@ts-ignore
|
|||
content: isString(cnt) ? createText(cnt) : cnt.get ? cnt.get(0) : cnt, |
|||
close: () => this.close(), |
|||
}; |
|||
} |
|||
|
|||
postRender(view: EditorView) { |
|||
const el = view.model.config.el || view.el; |
|||
const res = this.render(); |
|||
res && el?.appendChild(res); |
|||
} |
|||
|
|||
/** |
|||
* 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: any = {}) { |
|||
const attr = opts.attributes || {}; |
|||
opts.title && this.setTitle(opts.title); |
|||
opts.content && this.setContent(opts.content); |
|||
this.model.set('attributes', attr); |
|||
this.model.open(); |
|||
this.modal && this.modal.updateAttr(attr); |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* Close the modal window |
|||
* @returns {this} |
|||
* @example |
|||
* modal.close(); |
|||
*/ |
|||
close() { |
|||
this.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: EventHandler) { |
|||
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: EventHandler) { |
|||
this.em.once('modal:open', clb); |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* Checks if the modal window is open |
|||
* @returns {Boolean} |
|||
* @example |
|||
* modal.isOpen(); // true | false
|
|||
*/ |
|||
isOpen() { |
|||
return !!this.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: string) { |
|||
this.model.set('title', title); |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* Returns the title of the modal window |
|||
* @returns {string | HTMLElement} |
|||
* @example |
|||
* modal.getTitle(); |
|||
*/ |
|||
getTitle() { |
|||
return this.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: string | HTMLElement) { |
|||
this.model.set('content', ' '); |
|||
this.model.set('content', content); |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* Get the content of the modal window |
|||
* @returns {string | HTMLElement} |
|||
* @example |
|||
* modal.getContent(); |
|||
*/ |
|||
getContent(): string | HTMLElement { |
|||
return this.model.get('content'); |
|||
} |
|||
|
|||
/** |
|||
* Returns content element |
|||
* @return {HTMLElement} |
|||
* @private |
|||
*/ |
|||
getContentEl() { |
|||
//@ts-ignore
|
|||
return this.modal?.getContent().get(0); |
|||
} |
|||
|
|||
/** |
|||
* Returns modal model |
|||
* @return {Model} |
|||
* @private |
|||
*/ |
|||
getModel() { |
|||
return this.model; |
|||
} |
|||
|
|||
/** |
|||
* Render the modal window |
|||
* @return {HTMLElement} |
|||
* @private |
|||
*/ |
|||
render(): HTMLElement | undefined { |
|||
if (this.config.custom) return; |
|||
const View = ModalView.extend(this.config.extend); |
|||
const el = this.modal && this.modal.el; |
|||
this.modal = new View({ |
|||
el, |
|||
model: this.model, |
|||
config: this.config, |
|||
}); |
|||
return this.modal?.render().el; |
|||
} |
|||
|
|||
destroy() { |
|||
this.modal?.remove(); |
|||
} |
|||
} |
|||
@ -1,6 +1,7 @@ |
|||
import { Model } from '../../common'; |
|||
import ModalManager from '..'; |
|||
import { Model } from '../../abstract'; |
|||
|
|||
export default class Modal extends Model { |
|||
export default class Modal extends Model<ModalManager> { |
|||
defaults() { |
|||
return { |
|||
title: '', |
|||
@ -1,245 +0,0 @@ |
|||
/** |
|||
* 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/panels/config/config.js)
|
|||
* ```js
|
|||
* 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 |
|||
* |
|||
* ```js
|
|||
* const panelManager = editor.Panels; |
|||
* ``` |
|||
* |
|||
* * [addPanel](#addpanel) |
|||
* * [addButton](#addbutton) |
|||
* * [getButton](#getbutton) |
|||
* * [getPanel](#getpanel) |
|||
* * [getPanels](#getpanels) |
|||
* * [getPanelsEl](#getpanelsel) |
|||
* * [removePanel](#removepanel) |
|||
* * [removeButton](#removebutton) |
|||
* |
|||
* @module Panels |
|||
*/ |
|||
import defaults from './config/config'; |
|||
import Panel from './model/Panel'; |
|||
import Panels from './model/Panels'; |
|||
import PanelsView from './view/PanelsView'; |
|||
|
|||
export default () => { |
|||
var c = {}; |
|||
var panels, PanelsViewObj; |
|||
|
|||
return { |
|||
/** |
|||
* Name of the module |
|||
* @type {String} |
|||
* @private |
|||
*/ |
|||
name: 'Panels', |
|||
|
|||
/** |
|||
* 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]; |
|||
} |
|||
|
|||
var ppfx = c.pStylePrefix; |
|||
if (ppfx) c.stylePrefix = ppfx + c.stylePrefix; |
|||
|
|||
panels = new Panels(c.defaults); |
|||
return this; |
|||
}, |
|||
|
|||
/** |
|||
* Returns the collection of panels |
|||
* @return {Collection} Collection of panel |
|||
*/ |
|||
getPanels() { |
|||
return panels; |
|||
}, |
|||
|
|||
/** |
|||
* Returns panels element |
|||
* @return {HTMLElement} |
|||
*/ |
|||
getPanelsEl() { |
|||
return PanelsViewObj && PanelsViewObj.el; |
|||
}, |
|||
|
|||
/** |
|||
* Add new panel to the collection |
|||
* @param {Object|Panel} panel Object with right properties or an instance of Panel |
|||
* @return {Panel} Added panel. Useful in case passed argument was an Object |
|||
* @example |
|||
* var newPanel = panelManager.addPanel({ |
|||
* id: 'myNewPanel', |
|||
* visible : true, |
|||
* buttons : [...], |
|||
* }); |
|||
*/ |
|||
addPanel(panel) { |
|||
return panels.add(panel); |
|||
}, |
|||
|
|||
/** |
|||
* Remove a panel from the collection |
|||
* @param {Object|Panel|String} panel Object with right properties or an instance of Panel or Painel id |
|||
* @return {Panel} Removed panel. Useful in case passed argument was an Object |
|||
* @example |
|||
* const newPanel = panelManager.removePanel({ |
|||
* id: 'myNewPanel', |
|||
* visible : true, |
|||
* buttons : [...], |
|||
* }); |
|||
* |
|||
* const newPanel = panelManager.removePanel('myNewPanel'); |
|||
* |
|||
*/ |
|||
removePanel(panel) { |
|||
return panels.remove(panel); |
|||
}, |
|||
|
|||
/** |
|||
* Get panel by ID |
|||
* @param {string} id Id string |
|||
* @return {Panel|null} |
|||
* @example |
|||
* var myPanel = panelManager.getPanel('myNewPanel'); |
|||
*/ |
|||
getPanel(id) { |
|||
var res = panels.where({ id }); |
|||
return res.length ? res[0] : null; |
|||
}, |
|||
|
|||
/** |
|||
* Add button to the panel |
|||
* @param {string} panelId Panel's ID |
|||
* @param {Object|Button} button Button object or instance of Button |
|||
* @return {Button|null} Added button. Useful in case passed button was an Object |
|||
* @example |
|||
* 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) { |
|||
* ... |
|||
* } |
|||
*/ |
|||
addButton(panelId, button) { |
|||
var pn = this.getPanel(panelId); |
|||
return pn ? pn.get('buttons').add(button) : null; |
|||
}, |
|||
|
|||
/** |
|||
* Remove button from the panel |
|||
* @param {String} panelId Panel's ID |
|||
* @param {String} buttonId Button's ID |
|||
* @return {Button|null} Removed button. |
|||
* @example |
|||
* const removedButton = panelManager.addButton('myNewPanel',{ |
|||
* id: 'myNewButton', |
|||
* className: 'someClass', |
|||
* command: 'someCommand', |
|||
* attributes: { title: 'Some title'}, |
|||
* active: false, |
|||
* }); |
|||
* |
|||
* const removedButton = panelManager.removeButton('myNewPanel', 'myNewButton'); |
|||
* |
|||
*/ |
|||
removeButton(panelId, button) { |
|||
var pn = this.getPanel(panelId); |
|||
return pn && pn.get('buttons').remove(button); |
|||
}, |
|||
|
|||
/** |
|||
* Get button from the panel |
|||
* @param {string} panelId Panel's ID |
|||
* @param {string} id Button's ID |
|||
* @return {Button|null} |
|||
* @example |
|||
* var button = panelManager.getButton('myPanel','myButton'); |
|||
*/ |
|||
getButton(panelId, id) { |
|||
var pn = this.getPanel(panelId); |
|||
if (pn) { |
|||
var res = pn.get('buttons').where({ id }); |
|||
return res.length ? res[0] : null; |
|||
} |
|||
return null; |
|||
}, |
|||
|
|||
/** |
|||
* Render panels and buttons |
|||
* @return {HTMLElement} |
|||
* @private |
|||
*/ |
|||
render() { |
|||
PanelsViewObj && PanelsViewObj.remove(); |
|||
PanelsViewObj = new PanelsView({ |
|||
collection: panels, |
|||
config: c, |
|||
}); |
|||
return PanelsViewObj.render().el; |
|||
}, |
|||
|
|||
/** |
|||
* Active activable buttons |
|||
* @private |
|||
*/ |
|||
active() { |
|||
this.getPanels().each(p => { |
|||
p.get('buttons').each(btn => { |
|||
btn.get('active') && btn.trigger('updateActive'); |
|||
}); |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* Disable buttons flagged as disabled |
|||
* @private |
|||
*/ |
|||
disableButtons() { |
|||
this.getPanels().each(p => { |
|||
p.get('buttons').each(btn => { |
|||
if (btn.get('disable')) btn.trigger('change:disable'); |
|||
}); |
|||
}); |
|||
}, |
|||
|
|||
destroy() { |
|||
panels.reset(); |
|||
panels.stopListening(); |
|||
PanelsViewObj && PanelsViewObj.remove(); |
|||
[c, panels, PanelsViewObj].forEach(i => (i = {})); |
|||
}, |
|||
|
|||
Panel, |
|||
}; |
|||
}; |
|||
@ -0,0 +1,232 @@ |
|||
/** |
|||
* 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/panels/config/config.js)
|
|||
* ```js
|
|||
* 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 |
|||
* |
|||
* ```js
|
|||
* const panelManager = editor.Panels; |
|||
* ``` |
|||
* |
|||
* * [addPanel](#addpanel) |
|||
* * [addButton](#addbutton) |
|||
* * [getButton](#getbutton) |
|||
* * [getPanel](#getpanel) |
|||
* * [getPanels](#getpanels) |
|||
* * [getPanelsEl](#getpanelsel) |
|||
* * [removePanel](#removepanel) |
|||
* * [removeButton](#removebutton) |
|||
* |
|||
* @module Panels |
|||
*/ |
|||
import { Module } from '../abstract'; |
|||
import EditorModel from '../editor/model/Editor'; |
|||
import defaults from './config/config'; |
|||
import Button from './model/Button'; |
|||
import Panel from './model/Panel'; |
|||
import Panels from './model/Panels'; |
|||
import PanelsView from './view/PanelsView'; |
|||
|
|||
export default class PanelManager extends Module<typeof defaults> { |
|||
//config = {};
|
|||
panels: Panels; |
|||
PanelsViewObj?: PanelsView; |
|||
|
|||
/** |
|||
* Initialize module. Automatically called with a new instance of the editor |
|||
* @param {Object} config Configurations |
|||
* @private |
|||
*/ |
|||
constructor(em: EditorModel) { |
|||
super(em, 'Panels', defaults); |
|||
this.panels = new Panels(this, this.config.defaults); |
|||
for (var name in defaults) { |
|||
//@ts-ignore
|
|||
if (!(name in this.config)) this.config[name] = defaults[name]; |
|||
} |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* Returns the collection of panels |
|||
* @return {Collection} Collection of panel |
|||
*/ |
|||
getPanels() { |
|||
return this.panels; |
|||
} |
|||
|
|||
/** |
|||
* Returns panels element |
|||
* @return {HTMLElement} |
|||
*/ |
|||
getPanelsEl() { |
|||
return this.PanelsViewObj && this.PanelsViewObj.el; |
|||
} |
|||
|
|||
/** |
|||
* Add new panel to the collection |
|||
* @param {Object|Panel} panel Object with right properties or an instance of Panel |
|||
* @return {Panel} Added panel. Useful in case passed argument was an Object |
|||
* @example |
|||
* var newPanel = panelManager.addPanel({ |
|||
* id: 'myNewPanel', |
|||
* visible : true, |
|||
* buttons : [...], |
|||
* }); |
|||
*/ |
|||
addPanel(panel: Panel | Array<Record<string, any>>) { |
|||
return this.panels.add(panel); |
|||
} |
|||
|
|||
/** |
|||
* Remove a panel from the collection |
|||
* @param {Object|Panel|String} panel Object with right properties or an instance of Panel or Painel id |
|||
* @return {Panel} Removed panel. Useful in case passed argument was an Object |
|||
* @example |
|||
* const newPanel = panelManager.removePanel({ |
|||
* id: 'myNewPanel', |
|||
* visible : true, |
|||
* buttons : [...], |
|||
* }); |
|||
* |
|||
* const newPanel = panelManager.removePanel('myNewPanel'); |
|||
* |
|||
*/ |
|||
removePanel(panel: Panel) { |
|||
return this.panels.remove(panel); |
|||
} |
|||
|
|||
/** |
|||
* Get panel by ID |
|||
* @param {string} id Id string |
|||
* @return {Panel|null} |
|||
* @example |
|||
* var myPanel = panelManager.getPanel('myNewPanel'); |
|||
*/ |
|||
getPanel(id: string) { |
|||
var res = this.panels.where({ id }); |
|||
return res.length ? res[0] : null; |
|||
} |
|||
|
|||
/** |
|||
* Add button to the panel |
|||
* @param {string} panelId Panel's ID |
|||
* @param {Object|Button} button Button object or instance of Button |
|||
* @return {Button|null} Added button. Useful in case passed button was an Object |
|||
* @example |
|||
* 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) { |
|||
* ... |
|||
* } |
|||
*/ |
|||
addButton(panelId: string, button: any) { |
|||
var pn = this.getPanel(panelId); |
|||
return pn ? pn.get('buttons').add(button) : null; |
|||
} |
|||
|
|||
/** |
|||
* Remove button from the panel |
|||
* @param {String} panelId Panel's ID |
|||
* @param {String} buttonId Button's ID |
|||
* @return {Button|null} Removed button. |
|||
* @example |
|||
* const removedButton = panelManager.addButton('myNewPanel',{ |
|||
* id: 'myNewButton', |
|||
* className: 'someClass', |
|||
* command: 'someCommand', |
|||
* attributes: { title: 'Some title'}, |
|||
* active: false, |
|||
* }); |
|||
* |
|||
* const removedButton = panelManager.removeButton('myNewPanel', 'myNewButton'); |
|||
* |
|||
*/ |
|||
removeButton(panelId: string, button: any) { |
|||
var pn = this.getPanel(panelId); |
|||
return pn && pn.get('buttons').remove(button); |
|||
} |
|||
|
|||
/** |
|||
* Get button from the panel |
|||
* @param {string} panelId Panel's ID |
|||
* @param {string} id Button's ID |
|||
* @return {Button|null} |
|||
* @example |
|||
* var button = panelManager.getButton('myPanel','myButton'); |
|||
*/ |
|||
getButton(panelId: string, id: string) { |
|||
var pn = this.getPanel(panelId); |
|||
if (pn) { |
|||
var res = pn.get('buttons').where({ id }); |
|||
return res.length ? res[0] : null; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* Render panels and buttons |
|||
* @return {HTMLElement} |
|||
*/ |
|||
render() { |
|||
this.PanelsViewObj && this.PanelsViewObj.remove(); |
|||
this.PanelsViewObj = new PanelsView(this.panels); |
|||
return this.PanelsViewObj.render().el; |
|||
} |
|||
|
|||
/** |
|||
* Active activable buttons |
|||
* @private |
|||
*/ |
|||
active() { |
|||
this.getPanels().each(p => { |
|||
//@ts-ignore
|
|||
p.get('buttons').each(btn => { |
|||
btn.get('active') && btn.trigger('updateActive'); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Disable buttons flagged as disabled |
|||
* @private |
|||
*/ |
|||
disableButtons() { |
|||
this.getPanels().each(p => { |
|||
//@ts-ignore
|
|||
p.get('buttons').each(btn => { |
|||
if (btn.get('disable')) btn.trigger('change:disable'); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
destroy() { |
|||
this.panels.reset(); |
|||
this.panels.stopListening(); |
|||
this.PanelsViewObj && this.PanelsViewObj.remove(); |
|||
} |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
import { Model } from '../../common'; |
|||
|
|||
export default class Button extends Model { |
|||
defaults() { |
|||
return { |
|||
id: '', |
|||
label: '', |
|||
tagName: 'span', |
|||
className: '', |
|||
command: '', |
|||
context: '', |
|||
buttons: [], |
|||
attributes: {}, |
|||
options: {}, |
|||
active: false, |
|||
dragDrop: false, |
|||
togglable: true, |
|||
runDefaultCommand: true, |
|||
stopDefaultCommand: false, |
|||
disable: false, |
|||
}; |
|||
} |
|||
|
|||
initialize(options) { |
|||
if (this.get('buttons').length) { |
|||
var Buttons = require('./Buttons').default; |
|||
this.set('buttons', new Buttons(this.get('buttons'))); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
import PanelManager from '..'; |
|||
import { Model } from '../../abstract'; |
|||
import EditorModel from '../../editor/model/Editor'; |
|||
import Buttons from './Buttons'; |
|||
|
|||
export default class Button extends Model<PanelManager> { |
|||
defaults() { |
|||
return { |
|||
id: '', |
|||
label: '', |
|||
tagName: 'span', |
|||
className: '', |
|||
command: '', |
|||
context: '', |
|||
buttons: [], |
|||
attributes: {}, |
|||
options: {}, |
|||
active: false, |
|||
dragDrop: false, |
|||
togglable: true, |
|||
runDefaultCommand: true, |
|||
stopDefaultCommand: false, |
|||
disable: false, |
|||
}; |
|||
} |
|||
|
|||
get className(): string { |
|||
return this.get('className'); |
|||
} |
|||
|
|||
get command(): string { |
|||
return this.get('command'); |
|||
} |
|||
|
|||
get active(): boolean { |
|||
return this.get('active'); |
|||
} |
|||
set active(isActive: boolean) { |
|||
this.set('active', isActive); |
|||
} |
|||
|
|||
get togglable(): boolean { |
|||
return this.get('togglable'); |
|||
} |
|||
|
|||
get runDefaultCommand(): boolean { |
|||
return this.get('runDefaultCommand'); |
|||
} |
|||
get stopDefaultCommand(): boolean { |
|||
return this.get('stopDefaultCommand'); |
|||
} |
|||
get disable(): boolean { |
|||
return this.get('disable'); |
|||
} |
|||
|
|||
constructor(module: PanelManager, options: any) { |
|||
super(module, options); |
|||
if (this.get('buttons').length) { |
|||
this.set('buttons', new Buttons(this.module, this.get('buttons'))); |
|||
} |
|||
} |
|||
} |
|||
@ -1,20 +0,0 @@ |
|||
import { Model } from '../../common'; |
|||
import Buttons from './Buttons'; |
|||
|
|||
export default class Panel extends Model { |
|||
defaults() { |
|||
return { |
|||
id: '', |
|||
content: '', |
|||
visible: true, |
|||
buttons: [], |
|||
attributes: {}, |
|||
}; |
|||
} |
|||
|
|||
initialize(options) { |
|||
this.btn = this.get('buttons') || []; |
|||
this.buttons = new Buttons(this.btn); |
|||
this.set('buttons', this.buttons); |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
import PanelManager from '..'; |
|||
import { Model } from '../../abstract'; |
|||
import Buttons from './Buttons'; |
|||
|
|||
export default class Panel extends Model<PanelManager> { |
|||
defaults() { |
|||
return { |
|||
id: '', |
|||
content: '', |
|||
visible: true, |
|||
buttons: [], |
|||
attributes: {}, |
|||
}; |
|||
} |
|||
|
|||
get buttons() { |
|||
return this.get('buttons'); |
|||
} |
|||
|
|||
private set buttons(buttons: Buttons) { |
|||
this.set('buttons', buttons); |
|||
} |
|||
|
|||
view?: any; |
|||
|
|||
constructor(module: PanelManager, options: any) { |
|||
super(module, options); |
|||
var btn = this.get('buttons') || []; |
|||
this.buttons = new Buttons(module, btn); |
|||
} |
|||
} |
|||
@ -1,6 +0,0 @@ |
|||
import { Collection } from '../../common'; |
|||
import Panel from './Panel'; |
|||
|
|||
export default class Panels extends Collection {} |
|||
|
|||
Panels.prototype.model = Panel; |
|||
@ -0,0 +1,11 @@ |
|||
import PanelManager from '..'; |
|||
import { Collection } from '../../abstract'; |
|||
import Panel from './Panel'; |
|||
|
|||
export default class Panels extends Collection<Panel> { |
|||
constructor(module: PanelManager, models: Panel[] | Array<Record<string, any>>) { |
|||
super(module, models, Panel); |
|||
} |
|||
} |
|||
|
|||
Panels.prototype.model = Panel; |
|||
File diff suppressed because it is too large
Loading…
Reference in new issue