Browse Source

Start updating Layers jsDoc

pull/4427/head
Artur Arseniev 4 years ago
parent
commit
953e0243ba
  1. 517
      src/navigator/index.ts

517
src/navigator/index.ts

@ -1,3 +1,35 @@
/**
* You can customize the initial state of the module from the editor initialization
* ```js
* const editor = grapesjs.init({
* // ...
* layerManager: {
* // ...
* },
* })
* ```
*
* Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
*
* ```js
* const layers = editor.Layers;
* ```
*
* ## Available Events
* * `layer:root` - Root layer changed. The new root component is passed as an argument to the callback.
* * `layer:component` - Component layer is updated. The updated component is passed as an argument to the callback.
*
* ## Methods
* * [setRoot](#setroot)
* * [getRoot](#getroot)
* * [getLayerData](#getlayerdata)
*
* [Page]: page.html
* [Component]: component.html
*
* @module Layers
*/
import { isString, bindAll } from 'underscore'; import { isString, bindAll } from 'underscore';
import { Model } from '../abstract'; import { Model } from '../abstract';
import Module from '../abstract/Module'; import Module from '../abstract/Module';
@ -8,13 +40,13 @@ import defaults from './config/config';
import View from './view/ItemView'; import View from './view/ItemView';
interface LayerData { interface LayerData {
name: string, name: string;
open: boolean, open: boolean;
selected: boolean, selected: boolean;
hovered: boolean, hovered: boolean;
visible: boolean, visible: boolean;
locked: boolean, locked: boolean;
components: Component[], components: Component[];
} }
export const evAll = 'layer'; export const evAll = 'layer';
@ -31,255 +63,270 @@ const events = {
const styleOpts = { mediaText: '' }; const styleOpts = { mediaText: '' };
const propsToListen = ['open', 'status', 'locked', 'custom-name', 'components', 'classes'] const propsToListen = ['open', 'status', 'locked', 'custom-name', 'components', 'classes']
.map(p => `component:update:${p}`).join(' '); .map(p => `component:update:${p}`)
.join(' ');
const isStyleHidden = (style: any = {}) => { const isStyleHidden = (style: any = {}) => {
return (style.display || '').trim().indexOf('none') === 0; return (style.display || '').trim().indexOf('none') === 0;
}; };
export default class LayerManager extends Module<typeof defaults> { export default class LayerManager extends Module<typeof defaults> {
model!: Model; model!: Model;
view?: View; view?: View;
events = events; events = events;
constructor(em: EditorModel) { constructor(em: EditorModel) {
super(em, 'LayerManager', defaults); super(em, 'LayerManager', defaults);
bindAll(this, 'componentChanged', '__onRootChange', '__onComponent'); bindAll(this, 'componentChanged', '__onRootChange', '__onComponent');
this.model = new Model(this, { opened: {} }); this.model = new Model(this, { opened: {} });
// @ts-ignore // @ts-ignore
this.config.stylePrefix = this.config.pStylePrefix; this.config.stylePrefix = this.config.pStylePrefix;
return this; return this;
} }
onLoad() { onLoad() {
const { em, config, model } = this; const { em, config, model } = this;
model.listenTo(em, 'component:selected', this.componentChanged); model.listenTo(em, 'component:selected', this.componentChanged);
model.on('change:root', this.__onRootChange); model.on('change:root', this.__onRootChange);
model.listenTo(em, propsToListen, this.__onComponent); model.listenTo(em, propsToListen, this.__onComponent);
this.componentChanged(); this.componentChanged();
model.listenToOnce(em, 'load', () => { model.listenToOnce(em, 'load', () => {
this.setRoot(config.root); this.setRoot(config.root);
this.__appendTo(); this.__appendTo();
}); });
} }
/** /**
* Set new root for layers * Update root layer with another component.
* @param {Component|string} component Component to be set as the root * @param {[Component]|String} component Component to be set as root
* @return {Component} * @return {[Component]}
*/ * @example
setRoot(component: Component | string): Component { * const component = editor.getSelected();
const wrapper: Component = this.em.getWrapper(); * layers.setRoot(component);
let root = isComponent(component) ? component as Component : wrapper; */
setRoot(component: Component | string): Component {
if (component && isString(component) && hasWin()) { const wrapper: Component = this.em.getWrapper();
root = wrapper.find(component)[0] || wrapper; let root = isComponent(component) ? (component as Component) : wrapper;
}
if (component && isString(component) && hasWin()) {
this.model.set('root', root); root = wrapper.find(component)[0] || wrapper;
return root;
}
/**
* Get the root of layers
* @return {Component}
*/
getRoot(): Component {
return this.model.get('root');// || this.em.getWrapper();
}
getLayerData(component: any): LayerData {
const status = component.get('status');
return {
name: component.getName(),
open: this.isOpen(component),
selected: status === 'selected',
hovered: status === 'hovered', // || this.em.getHovered() === component,
visible: this.isVisible(component),
locked: this.isLocked(component),
components: this.getComponents(component),
}
}
setLayerData(component: any, data: Partial<Omit<LayerData, 'components'>>, opts = {}) {
const { em, config } = this;
const { open, selected, hovered, visible, locked, name } = data;
const cmpOpts = { fromLayers: true, ...opts };
if (isDef(open)) {
this.setOpen(component, open!);
}
if (isDef(selected)) {
if (selected) {
em.setSelected(component, cmpOpts);
const scroll = config.scrollCanvas;
scroll && component.views.forEach((view: any) => view.scrollIntoView(scroll));
} else {
em.removeSelected(component, cmpOpts);
}
}
if (isDef(hovered) && config.showHover) {
hovered ? em.setHovered(component, cmpOpts) : em.setHovered(null, cmpOpts);
}
if (isDef(visible)) {
visible !== this.isVisible(component) && this.setVisible(component, visible!);
}
if (isDef(locked)) {
this.setLocked(component, locked!);
}
if (isDef(name)) {
this.setName(component, name!);
}
}
getComponents(component: Component): Component[] {
return component.components().filter((cmp: any) => this.__isLayerable(cmp));
}
setOpen(component: Component, value: boolean) {
component.set('open', value);
} }
isOpen(component: Component): boolean { this.model.set('root', root);
return !!component.get('open');
return root;
}
/**
* Get the current root layer.
* @return {[Component]}
* @example
* const layerRoot = layers.getRoot();
*/
getRoot(): Component {
return this.model.get('root'); // || this.em.getWrapper();
}
/**
* Get layer data from a component.
* @param {[Component]} component Component from which you want to read layer data.
* @returns {LayerData} Object containing layer data
* @example
* const component = editor.getSelected();
* const layerData = layers.getLayerData(component);
* console.log(layerData);
*/
getLayerData(component: Component): LayerData {
const status = component.get('status');
return {
name: component.getName(),
open: this.isOpen(component),
selected: status === 'selected',
hovered: status === 'hovered', // || this.em.getHovered() === component,
visible: this.isVisible(component),
locked: this.isLocked(component),
components: this.getComponents(component),
};
}
setLayerData(component: any, data: Partial<Omit<LayerData, 'components'>>, opts = {}) {
const { em, config } = this;
const { open, selected, hovered, visible, locked, name } = data;
const cmpOpts = { fromLayers: true, ...opts };
if (isDef(open)) {
this.setOpen(component, open!);
} }
if (isDef(selected)) {
/** if (selected) {
* Update component visibility em.setSelected(component, cmpOpts);
* */ const scroll = config.scrollCanvas;
setVisible(component: Component, value: boolean) { scroll && component.views.forEach((view: any) => view.scrollIntoView(scroll));
const prevDspKey = '__prev-display';
const style: any = component.getStyle(styleOpts);
const { display } = style;
if (value) {
const prevDisplay = component.get(prevDspKey);
delete style.display;
if (prevDisplay) {
style.display = prevDisplay;
component.unset(prevDspKey);
}
} else { } else {
display && component.set(prevDspKey, display); em.removeSelected(component, cmpOpts);
style.display = 'none';
} }
component.setStyle(style, styleOpts);
this.updateLayer(component);
this.em.trigger('component:toggled'); // Updates Style Manager #2938
}
/**
* Check if the component is visible
* */
isVisible(component: Component): boolean {
return !isStyleHidden(component.getStyle(styleOpts));
} }
if (isDef(hovered) && config.showHover) {
/** hovered ? em.setHovered(component, cmpOpts) : em.setHovered(null, cmpOpts);
* Update component locked value
* */
setLocked(component: Component, value: boolean) {
component.set('locked', value);
} }
if (isDef(visible)) {
/** visible !== this.isVisible(component) && this.setVisible(component, visible!);
* Check if the component is locked
* */
isLocked(component: Component): boolean {
return component.get('locked');
} }
if (isDef(locked)) {
/** this.setLocked(component, locked!);
* Update component name
* */
setName(component: Component, value: string) {
component.set('custom-name', value);
} }
if (isDef(name)) {
/** this.setName(component, name!);
* Return the view of layers
* @return {View}
* @private
*/
getAll() {
return this.view;
} }
}
/**
* Triggered when the selected component is changed getComponents(component: Component): Component[] {
* @private return component.components().filter((cmp: any) => this.__isLayerable(cmp));
*/ }
componentChanged(sel?: Component, opts = {}) {
// @ts-ignore setOpen(component: Component, value: boolean) {
if (opts.fromLayers) return; component.set('open', value);
const { em, config } = this; }
const { scrollLayers } = config;
const opened = this.model.get('opened'); isOpen(component: Component): boolean {
const selected = em.getSelected(); return !!component.get('open');
let parent = selected?.parent(); }
for (let cid in opened) { /**
opened[cid].set('open', false); * Update component visibility
delete opened[cid]; * */
setVisible(component: Component, value: boolean) {
const prevDspKey = '__prev-display';
const style: any = component.getStyle(styleOpts);
const { display } = style;
if (value) {
const prevDisplay = component.get(prevDspKey);
delete style.display;
if (prevDisplay) {
style.display = prevDisplay;
component.unset(prevDspKey);
} }
} else {
while (parent) { display && component.set(prevDspKey, display);
parent.set('open', true); style.display = 'none';
opened[parent.cid] = parent;
parent = parent.parent();
}
if (selected && scrollLayers) {
// @ts-ignore
const el = selected.viewLayer?.el;
el?.scrollIntoView(scrollLayers);
}
}
render() {
const { config, model } = this;
const ItemView = View.extend(config.extend);
this.view = new ItemView({
el: this.view?.el,
ItemView,
level: 0,
config,
opened: model.get('opened'),
model: this.getRoot(),
module: this,
});
return this.view?.render().el as HTMLElement;
}
destroy() {
this.view?.remove();
} }
__onRootChange() { component.setStyle(style, styleOpts);
const root = this.getRoot(); this.updateLayer(component);
this.view?.setRoot(root); this.em.trigger('component:toggled'); // Updates Style Manager #2938
this.em.trigger(evRoot, root); }
/**
* Check if the component is visible
* */
isVisible(component: Component): boolean {
return !isStyleHidden(component.getStyle(styleOpts));
}
/**
* Update component locked value
* */
setLocked(component: Component, value: boolean) {
component.set('locked', value);
}
/**
* Check if the component is locked
* */
isLocked(component: Component): boolean {
return component.get('locked');
}
/**
* Update component name
* */
setName(component: Component, value: string) {
component.set('custom-name', value);
}
/**
* Return the view of layers
* @return {View}
* @private
*/
getAll() {
return this.view;
}
/**
* Triggered when the selected component is changed
* @private
*/
componentChanged(sel?: Component, opts = {}) {
// @ts-ignore
if (opts.fromLayers) return;
const { em, config } = this;
const { scrollLayers } = config;
const opened = this.model.get('opened');
const selected = em.getSelected();
let parent = selected?.parent();
for (let cid in opened) {
opened[cid].set('open', false);
delete opened[cid];
} }
__onComponent(component: Component) { while (parent) {
this.updateLayer(component); parent.set('open', true);
opened[parent.cid] = parent;
parent = parent.parent();
} }
__isLayerable(cmp: Component): boolean { if (selected && scrollLayers) {
const tag = cmp.get('tagName'); // @ts-ignore
const hideText = this.config.hideTextnode; const el = selected.viewLayer?.el;
const isValid = !hideText || (!cmp.is('textnode') && tag !== 'br'); el?.scrollIntoView(scrollLayers);
return isValid && cmp.get('layerable');
}
updateLayer(component: Component, opts?: any) {
this.em.trigger(evComponent, component, opts);
} }
}; }
render() {
const { config, model } = this;
const ItemView = View.extend(config.extend);
this.view = new ItemView({
el: this.view?.el,
ItemView,
level: 0,
config,
opened: model.get('opened'),
model: this.getRoot(),
module: this,
});
return this.view?.render().el as HTMLElement;
}
destroy() {
this.view?.remove();
}
__onRootChange() {
const root = this.getRoot();
this.view?.setRoot(root);
this.em.trigger(evRoot, root);
}
__onComponent(component: Component) {
this.updateLayer(component);
}
__isLayerable(cmp: Component): boolean {
const tag = cmp.get('tagName');
const hideText = this.config.hideTextnode;
const isValid = !hideText || (!cmp.is('textnode') && tag !== 'br');
return isValid && cmp.get('layerable');
}
updateLayer(component: Component, opts?: any) {
this.em.trigger(evComponent, component, opts);
}
}

Loading…
Cancel
Save