Browse Source

An abstract category class was added to the trait_manager, like the block_manager,and refactoring the block_manager.

pull/5606/head
AmirMohammad Rahmani 3 years ago
parent
commit
27d73e9b61
  1. 20
      .vscode/launch.json
  2. 24
      .vscode/settings.json
  3. 2
      dist/css/grapes.min.css
  4. 8
      src/abstract/ModuleCategories.ts
  5. 10
      src/abstract/ModuleCategory.ts
  6. 41
      src/abstract/ModuleCategoryView.ts
  7. 4
      src/block_manager/index.ts
  8. 4
      src/block_manager/model/Block.ts
  9. 6
      src/block_manager/view/BlocksView.ts
  10. 4
      src/index.ts
  11. 30
      src/styles/scss/_gjs_traits.scss
  12. 21
      src/trait_manager/index.ts
  13. 13
      src/trait_manager/model/Trait.ts
  14. 8
      src/trait_manager/view/TraitView.ts
  15. 134
      src/trait_manager/view/TraitsView.ts

20
.vscode/launch.json

@ -0,0 +1,20 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "msedge",
"request": "launch",
"name": "Launch Edge against localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}/src/trait_managerindex.ts",
"sourceMapPathOverrides": {
"meteor://💻app/*": "${workspaceFolder}/*",
"webpack:///./~/*": "${workspaceFolder}/node_modules/*",
"webpack://?:*/*": "${workspaceFolder}/*"
}
}
]
}

24
.vscode/settings.json

@ -0,0 +1,24 @@
{
"grammarly.selectors": [
{
"language": "markdown",
"scheme": "file",
"pattern": "c:\\Users\\amirmohammad.r\\Desktop\\pr\\Grapesjs.md"
},
{
"language": "markdown",
"scheme": "file",
"pattern": "c:\\Users\\amirmohammad.r\\Desktop\\pr\\Grapesjs.md"
},
{
"language": "markdown",
"scheme": "file",
"pattern": "c:\\Users\\amirmohammad.r\\Desktop\\pr\\Grapesjs.md"
},
{
"language": "markdown",
"scheme": "file",
"pattern": "c:\\Users\\amirmohammad.r\\Desktop\\pr\\Grapesjs.md"
}
]
}

2
dist/css/grapes.min.css

File diff suppressed because one or more lines are too long

8
src/block_manager/model/Categories.ts → src/abstract/ModuleCategories.ts

@ -1,11 +1,11 @@
import { isArray, isString } from 'underscore'; import { isArray, isString } from 'underscore';
import { AddOptions, Collection } from '../../common'; import { AddOptions, Collection } from '../common';
import { normalizeKey } from '../../utils/mixins'; import { normalizeKey } from '../utils/mixins';
import Category, { BlockCategoryProperties } from './Category'; import Category, { CategoryProperties } from './ModuleCategory';
export default class Categories extends Collection<Category> { export default class Categories extends Collection<Category> {
/** @ts-ignore */ /** @ts-ignore */
add(model: (BlockCategoryProperties | Category)[] | BlockCategoryProperties | Category, opts?: AddOptions) { add(model: (CategoryProperties | Category)[] | CategoryProperties | Category, opts?: AddOptions) {
const models = isArray(model) ? model : [model]; const models = isArray(model) ? model : [model];
models.forEach(md => md && (md.id = normalizeKey(`${md.id}`))); models.forEach(md => md && (md.id = normalizeKey(`${md.id}`)));
return super.add(model, opts); return super.add(model, opts);

10
src/block_manager/model/Category.ts → src/abstract/ModuleCategory.ts

@ -1,7 +1,7 @@
import { Model } from '../../common'; import { Model } from '../common';
import CategoryView from '../view/CategoryView'; import CategoryView from './ModuleCategoryView';
export interface BlockCategoryProperties { export interface CategoryProperties {
/** /**
* Category id. * Category id.
*/ */
@ -26,14 +26,14 @@ export interface BlockCategoryProperties {
attributes?: Record<string, any>; attributes?: Record<string, any>;
} }
export default class Category extends Model<BlockCategoryProperties> { export default class Category extends Model<CategoryProperties> {
view?: CategoryView; view?: CategoryView;
defaults() { defaults() {
return { return {
id: '', id: '',
label: '', label: '',
open: true, open: false,
attributes: {}, attributes: {},
}; };
} }

41
src/block_manager/view/CategoryView.ts → src/abstract/ModuleCategoryView.ts

@ -1,11 +1,12 @@
import { View } from '../../common'; import { View } from '../common';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../editor/model/Editor';
import html from '../../utils/html'; import html from '../utils/html';
import Category from '../model/Category'; import Category from './ModuleCategory';
export interface CategoryViewConfig { export interface CategoryViewConfig {
em: EditorModel; em: EditorModel;
pStylePrefix?: string; pStylePrefix?: string;
stylePrefix?: string;
} }
export default class CategoryView extends View<Category> { export default class CategoryView extends View<Category> {
@ -17,7 +18,8 @@ export default class CategoryView extends View<Category> {
iconClass: string; iconClass: string;
activeClass: string; activeClass: string;
iconEl?: HTMLElement; iconEl?: HTMLElement;
blocksEl?: HTMLElement; typeEl?: HTMLElement;
catName: string;
events() { events() {
return { return {
@ -25,13 +27,13 @@ export default class CategoryView extends View<Category> {
}; };
} }
template({ pfx, label }: { pfx: string; label: string }) { template({ pfx, label, catName }: { pfx: string; label: string; catName: string }) {
return html` return html`
<div class="${pfx}title" data-title> <div class="${pfx}title" data-title>
<i class="${pfx}caret-icon"></i> <i class="${pfx}caret-icon"></i>
${label} ${label}
</div> </div>
<div class="${pfx}blocks-c"></div> <div class="${pfx}${catName}s-c"></div>
`; `;
} }
@ -40,17 +42,18 @@ export default class CategoryView extends View<Category> {
return this.model.get('attributes') || {}; return this.model.get('attributes') || {};
} }
constructor(o: any, config: CategoryViewConfig) { constructor(o: any, config: CategoryViewConfig, catName: string) {
super(o); super(o);
this.config = config; this.config = config;
const pfx = config.pStylePrefix || ''; const pfx = config.pStylePrefix || '';
this.em = config.em; this.em = config.em;
this.catName = catName;
this.pfx = pfx; this.pfx = pfx;
this.caretR = 'fa fa-caret-right'; this.caretR = 'fa fa-caret-right';
this.caretD = 'fa fa-caret-down'; this.caretD = 'fa fa-caret-down';
this.iconClass = `${pfx}caret-icon`; this.iconClass = `${pfx}caret-icon`;
this.activeClass = `${pfx}open`; this.activeClass = `${pfx}open`;
this.className = `${pfx}block-category`; this.className = `${pfx}${catName}-category`;
this.listenTo(this.model, 'change:open', this.updateVisibility); this.listenTo(this.model, 'change:open', this.updateVisibility);
this.model.view = this; this.model.view = this;
} }
@ -63,13 +66,13 @@ export default class CategoryView extends View<Category> {
open() { open() {
this.$el.addClass(this.activeClass); this.$el.addClass(this.activeClass);
this.getIconEl()!.className = `${this.iconClass} ${this.caretD}`; this.getIconEl()!.className = `${this.iconClass} ${this.caretD}`;
this.getBlocksEl()!.style.display = ''; this.getTypeEl()!.style.display = '';
} }
close() { close() {
this.$el.removeClass(this.activeClass); this.$el.removeClass(this.activeClass);
this.getIconEl()!.className = `${this.iconClass} ${this.caretR}`; this.getIconEl()!.className = `${this.iconClass} ${this.caretR}`;
this.getBlocksEl()!.style.display = 'none'; this.getTypeEl()!.style.display = 'none';
} }
toggle() { toggle() {
@ -85,22 +88,22 @@ export default class CategoryView extends View<Category> {
return this.iconEl; return this.iconEl;
} }
getBlocksEl() { getTypeEl() {
if (!this.blocksEl) { if (!this.typeEl) {
this.blocksEl = this.el.querySelector(`.${this.pfx}blocks-c`)!; this.typeEl = this.el.querySelector(`.${this.pfx}${this.catName}s-c`)!;
} }
return this.blocksEl; return this.typeEl;
} }
append(el: HTMLElement) { append(el: HTMLElement) {
this.getBlocksEl().appendChild(el); this.getTypeEl().appendChild(el);
} }
render() { render() {
const { em, el, $el, model, pfx } = this; const { em, el, $el, model, pfx, catName } = this;
const label = em.t(`blockManager.categories.${model.id}`) || model.get('label'); const label = em.t(`${catName}Manager.categories.${model.id}`) || model.get('label');
el.innerHTML = this.template({ pfx, label }); el.innerHTML = this.template({ pfx, label, catName });
$el.addClass(this.className!); $el.addClass(this.className!);
$el.css({ order: model.get('order')! }); $el.css({ order: model.get('order')! });
this.updateVisibility(); this.updateVisibility();

4
src/block_manager/index.ts

@ -34,8 +34,8 @@ import EditorModel from '../editor/model/Editor';
import defaults, { BlockManagerConfig } from './config/config'; import defaults, { BlockManagerConfig } from './config/config';
import Block, { BlockProperties } from './model/Block'; import Block, { BlockProperties } from './model/Block';
import Blocks from './model/Blocks'; import Blocks from './model/Blocks';
import Categories from './model/Categories'; import Categories from '../abstract/ModuleCategories';
import Category from './model/Category'; import Category from '../abstract/ModuleCategory';
import { BlocksEvents } from './types'; import { BlocksEvents } from './types';
import BlocksView from './view/BlocksView'; import BlocksView from './view/BlocksView';

4
src/block_manager/model/Block.ts

@ -1,7 +1,7 @@
import { Model } from '../../common'; import { Model } from '../../common';
import { isFunction } from 'underscore'; import { isFunction } from 'underscore';
import Editor from '../../editor'; import Editor from '../../editor';
import { BlockCategoryProperties } from './Category'; import { CategoryProperties } from '../../abstract/ModuleCategory';
import { ComponentDefinition } from '../../dom_components/model/types'; import { ComponentDefinition } from '../../dom_components/model/types';
/** @private */ /** @private */
@ -23,7 +23,7 @@ export interface BlockProperties {
* Block category, eg. `Basic blocks` * Block category, eg. `Basic blocks`
* @default '' * @default ''
*/ */
category?: string | BlockCategoryProperties; category?: string | CategoryProperties;
/** /**
* If true, triggers the `active` event on the dropped component. * If true, triggers the `active` event on the dropped component.
* @default false * @default false

6
src/block_manager/view/BlocksView.ts

@ -4,9 +4,9 @@ import { View } from '../../common';
import Component from '../../dom_components/model/Component'; import Component from '../../dom_components/model/Component';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import Block from '../model/Block'; import Block from '../model/Block';
import Categories from '../model/Categories'; import Categories from '../../abstract/ModuleCategories';
import BlockView from './BlockView'; import BlockView from './BlockView';
import CategoryView from './CategoryView'; import CategoryView from '../../abstract/ModuleCategoryView';
export interface BlocksViewConfig { export interface BlocksViewConfig {
em: EditorModel; em: EditorModel;
@ -152,7 +152,7 @@ export default class BlocksView extends View {
model.set('category', catModel, { silent: true }); model.set('category', catModel, { silent: true });
if (!catView && categories) { if (!catView && categories) {
catView = new CategoryView({ model: catModel }, config).render(); catView = new CategoryView({ model: catModel }, config, 'block').render();
renderedCategories.set(catId, catView); renderedCategories.set(catId, catView);
categories.appendChild(catView.el); categories.appendChild(catView.el);
} }

4
src/index.ts

@ -97,8 +97,8 @@ export type { default as Asset } from './asset_manager/model/Asset';
export type { default as Assets } from './asset_manager/model/Assets'; export type { default as Assets } from './asset_manager/model/Assets';
export type { default as Block } from './block_manager/model/Block'; export type { default as Block } from './block_manager/model/Block';
export type { default as Blocks } from './block_manager/model/Blocks'; export type { default as Blocks } from './block_manager/model/Blocks';
export type { default as Categories } from './block_manager/model/Categories'; export type { default as Categories } from './abstract/ModuleCategories';
export type { default as Category } from './block_manager/model/Category'; export type { default as Category } from './abstract/ModuleCategory';
export type { default as Canvas } from './canvas/model/Canvas'; export type { default as Canvas } from './canvas/model/Canvas';
export type { default as CanvasSpot } from './canvas/model/CanvasSpot'; export type { default as CanvasSpot } from './canvas/model/CanvasSpot';
export type { default as CanvasSpots } from './canvas/model/CanvasSpots'; export type { default as CanvasSpots } from './canvas/model/CanvasSpots';

30
src/styles/scss/_gjs_traits.scss

@ -1,3 +1,31 @@
.#{$app-prefix}traits-c {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.#{$app-prefix}trait-categories {
display: flex;
flex-direction: column;
}
.#{$app-prefix}trait-category {
width: 100%;
&.#{$app-prefix}open {
@extend .#{$app-prefix}category-open;
}
.#{$app-prefix}title {
@extend .#{$app-prefix}category-title;
}
.#{$app-prefix}caret-icon {
margin-right: 5px;
}
}
.#{$app-prefix} { .#{$app-prefix} {
&traits-label { &traits-label {
border-bottom: 1px solid var(--gjs-main-dark-color); border-bottom: 1px solid var(--gjs-main-dark-color);
@ -45,4 +73,4 @@
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
} }
} }

21
src/trait_manager/index.ts

@ -12,6 +12,9 @@ import TraitButtonView from './view/TraitButtonView';
import EditorModel from '../editor/model/Editor'; import EditorModel from '../editor/model/Editor';
import Component from '../dom_components/model/Component'; import Component from '../dom_components/model/Component';
import Trait from './model/Trait'; import Trait from './model/Trait';
import Traits from './model/Traits';
import Category from '../abstract/ModuleCategory';
import Categories from '../abstract/ModuleCategories';
export const evAll = 'trait'; export const evAll = 'trait';
export const evPfx = `${evAll}:`; export const evPfx = `${evAll}:`;
@ -43,7 +46,13 @@ export default class TraitManager extends Module<TraitManagerConfig & { pStylePr
types: { [id: string]: { new (o: any): TraitView } }; types: { [id: string]: { new (o: any): TraitView } };
model: Model; model: Model;
__ctn?: any; __ctn?: any;
traits: Traits;
traitsVisible: Traits;
categories: Categories;
TraitsView = TraitsView; TraitsView = TraitsView;
Category = Category;
Categories = Categories;
events = { events = {
all: evAll, all: evAll,
@ -66,6 +75,13 @@ export default class TraitManager extends Module<TraitManagerConfig & { pStylePr
const model = new Model(); const model = new Model();
this.model = model; this.model = model;
this.types = typesDef; this.types = typesDef;
const ppfx = this.config.pStylePrefix;
ppfx && (this.config.stylePrefix = `${ppfx}${this.config.stylePrefix}`);
// Global traits collection
this.traits = new Traits([], { em });
this.traitsVisible = new Traits(this.traits.models, { em });
this.categories = new Categories();
const upAll = debounce(() => this.__upSel(), 0); const upAll = debounce(() => this.__upSel(), 0);
model.listenTo(em, 'component:toggled', upAll); model.listenTo(em, 'component:toggled', upAll);
@ -107,6 +123,9 @@ export default class TraitManager extends Module<TraitManagerConfig & { pStylePr
} }
postRender() { postRender() {
const { categories, config, em } = this;
const collection = this.traitsVisible;
this.view = new TraitsView({ collection, editor: em, config, categories }, []);
this.__appendTo(); this.__appendTo();
} }
@ -149,6 +168,7 @@ export default class TraitManager extends Module<TraitManagerConfig & { pStylePr
render() { render() {
let { view, em } = this; let { view, em } = this;
const { categories } = this;
const config = this.getConfig(); const config = this.getConfig();
const el = view && view.el; const el = view && view.el;
view = new TraitsView( view = new TraitsView(
@ -157,6 +177,7 @@ export default class TraitManager extends Module<TraitManagerConfig & { pStylePr
collection: [], collection: [],
editor: em, editor: em,
config, config,
categories,
}, },
this.getTypes() this.getTypes()
); );

13
src/trait_manager/model/Trait.ts

@ -5,6 +5,7 @@ import Editor from '../../editor';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import TraitView from '../view/TraitView'; import TraitView from '../view/TraitView';
import { isDef } from '../../utils/mixins'; import { isDef } from '../../utils/mixins';
import { CategoryProperties } from '../../abstract/ModuleCategory';
/** @private */ /** @private */
export interface TraitProperties { export interface TraitProperties {
@ -18,13 +19,19 @@ export interface TraitProperties {
* The name of the trait used as a key for the attribute/property. * The name of the trait used as a key for the attribute/property.
* By default, the name is used as attribute name or property in case `changeProp` in enabled. * By default, the name is used as attribute name or property in case `changeProp` in enabled.
*/ */
name: string; name?: string;
/** /**
* Trait id, eg. `my-trait-id`. * Trait id, eg. `my-trait-id`.
* If not specified, the `name` will be used as id. * If not specified, the `name` will be used as id.
*/ */
id?: string; id?: string | number;
/**
* Trait category.
* @default ''
*/
category?: string | CategoryProperties;
/** /**
* The trait label to show for the rendered trait. * The trait label to show for the rendered trait.
@ -80,6 +87,7 @@ type TraitOption = {
* @property {String} type Trait type, defines how the trait should rendered. Possible values: `text` (default), `number`, `select`, `checkbox`, `color`, `button` * @property {String} type Trait type, defines how the trait should rendered. Possible values: `text` (default), `number`, `select`, `checkbox`, `color`, `button`
* @property {String} label The trait label to show for the rendered trait. * @property {String} label The trait label to show for the rendered trait.
* @property {String} name The name of the trait used as a key for the attribute/property. By default, the name is used as attribute name or property in case `changeProp` in enabled. * @property {String} name The name of the trait used as a key for the attribute/property. By default, the name is used as attribute name or property in case `changeProp` in enabled.
* @property {String} [category=''] Trait category.
* @property {Boolean} changeProp If `true` the trait value is applied on component * @property {Boolean} changeProp If `true` the trait value is applied on component
* *
*/ */
@ -99,6 +107,7 @@ export default class Trait extends Model<TraitProperties> {
value: '', value: '',
default: '', default: '',
placeholder: '', placeholder: '',
category: '',
changeProp: false, changeProp: false,
options: [], options: [],
}; };

8
src/trait_manager/view/TraitView.ts

@ -48,11 +48,11 @@ export default class TraitView extends View<Trait> {
const { type } = model.attributes; const { type } = model.attributes;
this.config = config; this.config = config;
this.em = config.em; this.em = config.em;
this.ppfx = config.pStylePrefix || ''; this.pfx = this.config.stylePrefix || '';
this.pfx = this.ppfx + config.stylePrefix || ''; this.ppfx = this.config.pStylePrefix || '';
this.target = target; this.target = target;
const { ppfx } = this; this.className = this.pfx + 'trait';
this.clsField = `${ppfx}field ${ppfx}field-${type}`; this.clsField = `${this.ppfx}field ${this.ppfx}field-${type}`;
const evToListen: [string, any][] = [ const evToListen: [string, any][] = [
['change:value', this.onValueChange], ['change:value', this.onValueChange],
['remove', this.removeView], ['remove', this.removeView],

134
src/trait_manager/view/TraitsView.ts

@ -1,12 +1,26 @@
import DomainViews from '../../domain_abstract/view/DomainViews'; import DomainViews from '../../domain_abstract/view/DomainViews';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import TraitView from './TraitView'; import TraitView from './TraitView';
import CategoryView from '../../abstract/ModuleCategoryView';
import Categories from '../../abstract/ModuleCategories';
import Trait from '../model/Trait';
import { isObject, isString } from 'underscore';
export default class TraitsView extends DomainViews { export default class TraitsView extends DomainViews {
reuseView = true; reuseView = true;
em: EditorModel; em: EditorModel;
pfx: string; pfx: string;
ppfx: string; ppfx: string;
categories: Categories;
renderedCategories = new Map<string, CategoryView>();
noCatClass: string;
traitContClass: string;
catsClass: string;
catsEl?: HTMLElement;
traitsEl?: HTMLElement;
itemView?: any;
itemType: any;
rendered?: boolean;
constructor(o: any = {}, itemsView: any) { constructor(o: any = {}, itemsView: any) {
super(o); super(o);
@ -14,11 +28,14 @@ export default class TraitsView extends DomainViews {
const config = o.config || {}; const config = o.config || {};
const em = o.editor; const em = o.editor;
this.config = config;
this.em = em; this.em = em;
this.ppfx = config.pStylePrefix || ''; this.ppfx = config.pStylePrefix || '';
this.pfx = this.ppfx + config.stylePrefix || ''; this.pfx = this.ppfx + config.stylePrefix || '';
this.className = `${this.pfx}traits`; this.className = `${this.pfx}traits`;
this.categories = o.categories || '';
this.noCatClass = `${this.ppfx}traits-no-cat`;
this.traitContClass = `${this.ppfx}traits-c`;
this.catsClass = `${this.ppfx}trait-categories`;
this.listenTo(em, 'component:toggled', this.updatedCollection); this.listenTo(em, 'component:toggled', this.updatedCollection);
this.updatedCollection(); this.updatedCollection();
} }
@ -28,13 +45,122 @@ export default class TraitsView extends DomainViews {
* @private * @private
*/ */
updatedCollection() { updatedCollection() {
const { ppfx, className, em } = this; const { ppfx, em } = this;
const comp = em.getSelected(); const comp = em.getSelected();
this.el.className = `${className} ${ppfx}one-bg ${ppfx}two-color`; this.el.className = `${this.traitContClass}s ${ppfx}one-bg ${ppfx}two-color`;
// @ts-ignore // @ts-ignore
this.collection = comp ? comp.traits : []; this.collection = comp ? comp.get('traits') : [];
this.render(); this.render();
} }
/**
* Add new model to the collection
* @param {Model} model
* @private
*/
addTo(model: Trait) {
this.add(model);
}
/**
* Render new model inside the view
* @param {Model} model
* @param {Object} fragment Fragment collection
* @private
* */
add(model: Trait, fragment?: DocumentFragment) {
const { config, renderedCategories } = this;
var itemView = this.itemView;
const typeField = model.get(this.itemType);
if (this.itemsView && this.itemsView[typeField]) {
itemView = this.itemsView[typeField];
}
const view = new itemView({
config,
model,
attributes: model.get('attributes'),
});
const rendered = view.render().el;
let category = model.get('category');
// Check for categories
if (category && this.categories && !config.ignoreCategories) {
if (isString(category)) {
category = {
id: category,
label: category,
};
} else if (isObject(category) && !category.id) {
category.id = category.label;
}
const catModel = this.categories.add(category);
const catId = catModel.get('id')!;
const categories = this.getCategoriesEl();
let catView = renderedCategories.get(catId);
//@ts-ignore
model.set('category', catModel, { silent: true });
if (!catView && categories) {
catView = new CategoryView(
{
model: catModel,
},
config,
'trait'
).render();
renderedCategories.set(catId, catView);
categories.appendChild(catView.el);
}
catView && catView.append(rendered);
return;
}
fragment ? fragment.appendChild(rendered) : this.append(rendered);
}
getCategoriesEl() {
if (!this.catsEl) {
this.catsEl = this.el.querySelector(`.${this.catsClass}`)!;
}
return this.catsEl;
}
getTraitsEl() {
if (!this.traitsEl) {
this.traitsEl = this.el.querySelector(`.${this.noCatClass} .${this.traitContClass}`)!;
}
return this.traitsEl;
}
append(el: HTMLElement | DocumentFragment) {
let traits = this.getTraitsEl();
traits && traits.appendChild(el);
}
render() {
const ppfx = this.ppfx;
const frag = document.createDocumentFragment();
delete this.catsEl;
delete this.traitsEl;
this.renderedCategories = new Map();
this.el.innerHTML = `
<div class="${this.catsClass}"></div>
<div class="${this.noCatClass}">
<div class="${this.traitContClass}"></div>
</div>
`;
if (this.collection.length) {
this.collection.each(model => this.add(model, frag));
}
this.append(frag);
const cls = `${this.traitContClass}s ${ppfx}one-bg ${ppfx}two-color`;
this.$el.addClass(cls);
this.rendered = true;
return this;
}
} }
// @ts-ignore // @ts-ignore

Loading…
Cancel
Save