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 { Model } from '../abstract';
import Module from '../abstract/Module';
@ -8,13 +40,13 @@ import defaults from './config/config';
import View from './view/ItemView';
interface LayerData {
name: string,
open: boolean,
selected: boolean,
hovered: boolean,
visible: boolean,
locked: boolean,
components: Component[],
name: string;
open: boolean;
selected: boolean;
hovered: boolean;
visible: boolean;
locked: boolean;
components: Component[];
}
export const evAll = 'layer';
@ -31,255 +63,270 @@ const events = {
const styleOpts = { mediaText: '' };
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 = {}) => {
return (style.display || '').trim().indexOf('none') === 0;
};
export default class LayerManager extends Module<typeof defaults> {
model!: Model;
view?: View;
events = events;
constructor(em: EditorModel) {
super(em, 'LayerManager', defaults);
bindAll(this, 'componentChanged', '__onRootChange', '__onComponent');
this.model = new Model(this, { opened: {} });
// @ts-ignore
this.config.stylePrefix = this.config.pStylePrefix;
return this;
}
onLoad() {
const { em, config, model } = this;
model.listenTo(em, 'component:selected', this.componentChanged);
model.on('change:root', this.__onRootChange);
model.listenTo(em, propsToListen, this.__onComponent);
this.componentChanged();
model.listenToOnce(em, 'load', () => {
this.setRoot(config.root);
this.__appendTo();
});
}
/**
* Set new root for layers
* @param {Component|string} component Component to be set as the root
* @return {Component}
*/
setRoot(component: Component | string): Component {
const wrapper: Component = this.em.getWrapper();
let root = isComponent(component) ? component as Component : wrapper;
if (component && isString(component) && hasWin()) {
root = wrapper.find(component)[0] || wrapper;
}
this.model.set('root', root);
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);
model!: Model;
view?: View;
events = events;
constructor(em: EditorModel) {
super(em, 'LayerManager', defaults);
bindAll(this, 'componentChanged', '__onRootChange', '__onComponent');
this.model = new Model(this, { opened: {} });
// @ts-ignore
this.config.stylePrefix = this.config.pStylePrefix;
return this;
}
onLoad() {
const { em, config, model } = this;
model.listenTo(em, 'component:selected', this.componentChanged);
model.on('change:root', this.__onRootChange);
model.listenTo(em, propsToListen, this.__onComponent);
this.componentChanged();
model.listenToOnce(em, 'load', () => {
this.setRoot(config.root);
this.__appendTo();
});
}
/**
* Update root layer with another component.
* @param {[Component]|String} component Component to be set as root
* @return {[Component]}
* @example
* const component = editor.getSelected();
* layers.setRoot(component);
*/
setRoot(component: Component | string): Component {
const wrapper: Component = this.em.getWrapper();
let root = isComponent(component) ? (component as Component) : wrapper;
if (component && isString(component) && hasWin()) {
root = wrapper.find(component)[0] || wrapper;
}
isOpen(component: Component): boolean {
return !!component.get('open');
this.model.set('root', root);
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!);
}
/**
* Update component visibility
* */
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);
}
if (isDef(selected)) {
if (selected) {
em.setSelected(component, cmpOpts);
const scroll = config.scrollCanvas;
scroll && component.views.forEach((view: any) => view.scrollIntoView(scroll));
} else {
display && component.set(prevDspKey, display);
style.display = 'none';
em.removeSelected(component, cmpOpts);
}
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));
}
/**
* Update component locked value
* */
setLocked(component: Component, value: boolean) {
component.set('locked', value);
if (isDef(hovered) && config.showHover) {
hovered ? em.setHovered(component, cmpOpts) : em.setHovered(null, cmpOpts);
}
/**
* Check if the component is locked
* */
isLocked(component: Component): boolean {
return component.get('locked');
if (isDef(visible)) {
visible !== this.isVisible(component) && this.setVisible(component, visible!);
}
/**
* Update component name
* */
setName(component: Component, value: string) {
component.set('custom-name', value);
if (isDef(locked)) {
this.setLocked(component, locked!);
}
/**
* Return the view of layers
* @return {View}
* @private
*/
getAll() {
return this.view;
if (isDef(name)) {
this.setName(component, name!);
}
/**
* 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];
}
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 {
return !!component.get('open');
}
/**
* Update component visibility
* */
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);
}
while (parent) {
parent.set('open', true);
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();
} else {
display && component.set(prevDspKey, display);
style.display = 'none';
}
__onRootChange() {
const root = this.getRoot();
this.view?.setRoot(root);
this.em.trigger(evRoot, root);
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));
}
/**
* 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) {
this.updateLayer(component);
while (parent) {
parent.set('open', true);
opened[parent.cid] = parent;
parent = parent.parent();
}
__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);
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() {
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