@print-one/grapesjs
Version:
Free and Open Source Web Builder Framework
188 lines (158 loc) • 5.18 kB
text/typescript
import { isString, isObject, isFunction } from 'underscore';
import { ModuleView } from '../../abstract';
import Button from '../model/Button';
import Buttons from '../model/Buttons';
export default class ButtonView extends ModuleView<Button> {
//@ts-ignore
tagName() {
return this.model.get('tagName');
}
events() {
return {
click: 'clicked',
};
}
commands: any;
activeCls: string;
disableCls: string;
btnsVisCls: string;
//Note: I don't think this is working
$buttons?: any;
constructor(o: any) {
super(o);
const { model, em, pfx, ppfx } = this;
const cls = model.className;
const { command, listen } = model.attributes;
this.id = pfx + model.get('id');
this.activeCls = `${pfx}active ${ppfx}four-color`;
this.disableCls = `${ppfx}disabled`;
this.btnsVisCls = `${pfx}visible`;
this.className = pfx + 'btn' + (cls ? ' ' + cls : '');
this.listenTo(model, 'change', this.render);
this.listenTo(model, 'change:active updateActive', this.updateActive);
this.listenTo(model, 'checkActive', this.checkActive);
this.listenTo(model, 'change:bntsVis', this.updateBtnsVis);
this.listenTo(model, 'change:attributes', this.updateAttributes);
this.listenTo(model, 'change:className', this.updateClassName);
this.listenTo(model, 'change:disable', this.updateDisable);
if (em && isString(command) && listen) {
const chnOpt: any = { fromListen: true };
this.listenTo(em, `run:${command}`, () => model.set('active', true, chnOpt));
this.listenTo(em, `stop:${command}`, () => model.set('active', false, chnOpt));
}
if (em && em.get) this.commands = em.get('Commands');
}
/**
* Updates class name of the button
*
* @return void
* */
private updateClassName() {
const { model, pfx } = this;
const cls = model.className;
const attrCls = model.get('attributes').class;
const classStr = `${attrCls ? attrCls : ''} ${pfx}btn ${cls ? cls : ''}`;
this.$el.attr('class', classStr.trim());
}
/**
* Updates attributes of the button
*
* @return void
* */
private updateAttributes() {
const { em, model, $el } = this;
const attr = model.get('attributes') || {};
const title = em && em.t && em.t(`panels.buttons.titles.${model.id}`);
$el.attr(attr);
title && $el.attr({ title });
this.updateClassName();
}
/**
* Updates visibility of children buttons
*
* @return void
* */
private updateBtnsVis() {
if (!this.$buttons) return;
if (this.model.get('bntsVis')) this.$buttons.addClass(this.btnsVisCls);
else this.$buttons.removeClass(this.btnsVisCls);
}
/**
* Update active status of the button
*
* @return void
* */
private updateActive(m: any, v: any, opts: any = {}) {
const { model, commands, $el, activeCls } = this;
const { fromCollection, fromListen } = opts;
const context = model.get('context');
const options = model.get('options');
const commandName = model.command;
let command = {};
if (!commandName) return;
if (commands && isString(commandName)) {
command = commands.get(commandName) || {};
} else if (isFunction(commandName)) {
command = commands.create({ run: commandName });
} else if (commandName !== null && isObject(commandName)) {
command = commands.create(commandName);
}
if (model.active) {
!fromCollection && (model.collection as Buttons)?.deactivateAll(context, model);
model.set('active', true, { silent: true }).trigger('checkActive');
!fromListen && commands.runCommand(command, { ...options, sender: model });
// Disable button if the command has no stop method
//@ts-ignore
command.noStop && model.set('active', false);
} else {
$el.removeClass(activeCls);
!fromListen && commands.stopCommand(command, { ...options, sender: model, force: 1 });
}
}
updateDisable() {
const { disableCls, model } = this;
const disable = model.disable;
this.$el[disable ? 'addClass' : 'removeClass'](disableCls);
}
/**
* Update active style status
*
* @return void
* */
checkActive() {
const { model, $el, activeCls } = this;
model.active ? $el.addClass(activeCls) : $el.removeClass(activeCls);
}
/**
* Triggered when button is clicked
* @return void
* */
clicked() {
const { model } = this;
if (model.get('bntsVis') || model.disable || !model.command) return;
this.toggleActive();
}
private toggleActive() {
const { model, em } = this;
const { active, togglable } = model;
if (active && !togglable) return;
model.active = !active;
// If the stop is requested
if (active) {
if (model.runDefaultCommand) em.runDefault();
} else {
if (model.stopDefaultCommand) em.stopDefault();
}
}
public render() {
const { model } = this;
const label = model.get('label');
const { $el } = this;
!model.get('el') && $el.empty();
this.updateAttributes();
label && $el.append(label);
this.checkActive();
this.updateDisable();
return this;
}
}