mirror of https://github.com/artf/grapesjs.git
14 changed files with 689 additions and 465 deletions
@ -1,4 +1,4 @@ |
|||||
export { default as Model } from './Model'; |
export { default as Model } from './Model'; |
||||
export { default as Collection } from './Collection'; |
export { default as Collection } from './Collection'; |
||||
export { default as View } from './View'; |
export { default as View } from './View'; |
||||
export { default as Module } from './moduleLegacy'; |
export { default as Module } from './Module'; |
||||
|
|||||
@ -1,47 +0,0 @@ |
|||||
import { bindAll } from 'underscore'; |
|
||||
import { Collection } from '../../common'; |
|
||||
import Frame from './Frame'; |
|
||||
|
|
||||
export default class Frames extends Collection { |
|
||||
initialize(models, config = {}) { |
|
||||
bindAll(this, 'itemLoaded'); |
|
||||
this.config = config; |
|
||||
this.on('reset', this.onReset); |
|
||||
this.on('remove', this.onRemove); |
|
||||
} |
|
||||
|
|
||||
onReset(m, opts = {}) { |
|
||||
const prev = opts.previousModels || []; |
|
||||
prev.map(p => this.onRemove(p)); |
|
||||
} |
|
||||
|
|
||||
onRemove(removed) { |
|
||||
removed && removed.onRemove(); |
|
||||
} |
|
||||
|
|
||||
itemLoaded() { |
|
||||
this.loadedItems++; |
|
||||
|
|
||||
if (this.loadedItems >= this.itemsToLoad) { |
|
||||
this.trigger('loaded:all'); |
|
||||
this.listenToLoadItems(0); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
listenToLoad() { |
|
||||
this.loadedItems = 0; |
|
||||
this.itemsToLoad = this.length; |
|
||||
this.listenToLoadItems(1); |
|
||||
} |
|
||||
|
|
||||
listenToLoadItems(on) { |
|
||||
this.forEach(item => item[on ? 'on' : 'off']('loaded', this.itemLoaded)); |
|
||||
} |
|
||||
|
|
||||
add(m, o = {}) { |
|
||||
const { config } = this; |
|
||||
return Collection.prototype.add.call(this, m, { ...o, config }); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
Frames.prototype.model = Frame; |
|
||||
@ -0,0 +1,45 @@ |
|||||
|
import { bindAll } from 'underscore'; |
||||
|
import { Collection } from '../../common'; |
||||
|
import Page from '../../pages/model/Page'; |
||||
|
import Frame from './Frame'; |
||||
|
|
||||
|
export default class Frames extends Collection<Frame> { |
||||
|
loadedItems = 0; |
||||
|
itemsToLoad = 0; |
||||
|
page?: Page; |
||||
|
|
||||
|
constructor(models?: Frame[]) { |
||||
|
super(models); |
||||
|
bindAll(this, 'itemLoaded'); |
||||
|
this.on('reset', this.onReset); |
||||
|
this.on('remove', this.onRemove); |
||||
|
} |
||||
|
|
||||
|
onReset(m: Frame, opts?: { previousModels?: Frame[] }) { |
||||
|
const prev = opts?.previousModels || []; |
||||
|
prev.map((p) => this.onRemove(p)); |
||||
|
} |
||||
|
|
||||
|
onRemove(removed?: Frame) { |
||||
|
removed?.onRemove(); |
||||
|
} |
||||
|
|
||||
|
itemLoaded() { |
||||
|
this.loadedItems++; |
||||
|
|
||||
|
if (this.loadedItems >= this.itemsToLoad) { |
||||
|
this.trigger('loaded:all'); |
||||
|
this.listenToLoadItems(false); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
listenToLoad() { |
||||
|
this.loadedItems = 0; |
||||
|
this.itemsToLoad = this.length; |
||||
|
this.listenToLoadItems(true); |
||||
|
} |
||||
|
|
||||
|
listenToLoadItems(on: boolean) { |
||||
|
this.forEach((item) => item[on ? 'on' : 'off']('loaded', this.itemLoaded)); |
||||
|
} |
||||
|
} |
||||
@ -1,299 +0,0 @@ |
|||||
/** |
|
||||
* You can customize the initial state of the module from the editor initialization |
|
||||
* ```js
|
|
||||
* const editor = grapesjs.init({ |
|
||||
* .... |
|
||||
* pageManager: { |
|
||||
* pages: [ |
|
||||
* { |
|
||||
* id: 'page-id', |
|
||||
* styles: `.my-class { color: red }`, // or a JSON of styles
|
|
||||
* component: '<div class="my-class">My element</div>', // or a JSON of components
|
|
||||
* } |
|
||||
* ] |
|
||||
* }, |
|
||||
* }) |
|
||||
* ``` |
|
||||
* |
|
||||
* Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance |
|
||||
* |
|
||||
* ```js
|
|
||||
* const pageManager = editor.Pages; |
|
||||
* ``` |
|
||||
* |
|
||||
* ## Available Events |
|
||||
* * `page:add` - Added new page. The page is passed as an argument to the callback |
|
||||
* * `page:remove` - Page removed. The page is passed as an argument to the callback |
|
||||
* * `page:select` - New page selected. The newly selected page and the previous one, are passed as arguments to the callback |
|
||||
* * `page:update` - Page updated. The updated page and the object containing changes are passed as arguments to the callback |
|
||||
* * `page` - Catch-all event for all the events mentioned above. An object containing all the available data about the triggered event is passed as an argument to the callback |
|
||||
* |
|
||||
* ## Methods |
|
||||
* * [add](#add) |
|
||||
* * [get](#get) |
|
||||
* * [getAll](#getall) |
|
||||
* * [getAllWrappers](#getallwrappers) |
|
||||
* * [getMain](#getmain) |
|
||||
* * [remove](#remove) |
|
||||
* * [select](#select) |
|
||||
* * [getSelected](#getselected) |
|
||||
* |
|
||||
* [Page]: page.html |
|
||||
* [Component]: component.html |
|
||||
* |
|
||||
* @module Pages |
|
||||
*/ |
|
||||
|
|
||||
import { isString, bindAll, unique, flatten } from 'underscore'; |
|
||||
import { createId } from '../utils/mixins'; |
|
||||
import { Model, Module } from '../common'; |
|
||||
import Pages from './model/Pages'; |
|
||||
import Page from './model/Page'; |
|
||||
|
|
||||
export const evAll = 'page'; |
|
||||
export const evPfx = `${evAll}:`; |
|
||||
export const evPageSelect = `${evPfx}select`; |
|
||||
export const evPageSelectBefore = `${evPageSelect}:before`; |
|
||||
export const evPageUpdate = `${evPfx}update`; |
|
||||
export const evPageAdd = `${evPfx}add`; |
|
||||
export const evPageAddBefore = `${evPageAdd}:before`; |
|
||||
export const evPageRemove = `${evPfx}remove`; |
|
||||
export const evPageRemoveBefore = `${evPageRemove}:before`; |
|
||||
const chnSel = 'change:selected'; |
|
||||
const typeMain = 'main'; |
|
||||
|
|
||||
export default () => { |
|
||||
return { |
|
||||
...Module, |
|
||||
|
|
||||
name: 'PageManager', |
|
||||
|
|
||||
storageKey: 'pages', |
|
||||
|
|
||||
Page, |
|
||||
|
|
||||
Pages, |
|
||||
|
|
||||
events: { |
|
||||
all: evAll, |
|
||||
select: evPageSelect, |
|
||||
selectBefore: evPageSelectBefore, |
|
||||
update: evPageUpdate, |
|
||||
add: evPageAdd, |
|
||||
addBefore: evPageAddBefore, |
|
||||
remove: evPageRemove, |
|
||||
removeBefore: evPageRemoveBefore, |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Initialize module |
|
||||
* @param {Object} config Configurations |
|
||||
* @private |
|
||||
*/ |
|
||||
init(opts = {}) { |
|
||||
bindAll(this, '_onPageChange'); |
|
||||
const { em } = opts; |
|
||||
const cnf = { ...opts }; |
|
||||
this.config = cnf; |
|
||||
this.em = em; |
|
||||
const pages = new Pages([], cnf); |
|
||||
this.pages = pages; |
|
||||
this.all = pages; |
|
||||
const model = new Model({ _undo: true }); |
|
||||
this.model = model; |
|
||||
pages.on('add', (p, c, o) => em.trigger(evPageAdd, p, o)); |
|
||||
pages.on('remove', (p, c, o) => em.trigger(evPageRemove, p, o)); |
|
||||
pages.on('change', (p, c) => { |
|
||||
em.trigger(evPageUpdate, p, p.changedAttributes(), c); |
|
||||
}); |
|
||||
pages.on('reset', coll => coll.at(0) && this.select(coll.at(0))); |
|
||||
pages.on('all', this.__onChange, this); |
|
||||
model.on(chnSel, this._onPageChange); |
|
||||
|
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
__onChange(event, page, coll, opts) { |
|
||||
const options = opts || coll; |
|
||||
this.em.trigger(evAll, { event, page, options }); |
|
||||
}, |
|
||||
|
|
||||
onLoad() { |
|
||||
const { pages } = this; |
|
||||
const opt = { silent: true }; |
|
||||
pages.add(this.config.pages || [], opt); |
|
||||
const mainPage = !pages.length ? this.add({ type: typeMain }, opt) : this.getMain(); |
|
||||
this.select(mainPage, opt); |
|
||||
}, |
|
||||
|
|
||||
_onPageChange(m, page, opts) { |
|
||||
const { em } = this; |
|
||||
const lm = em.get('LayerManager'); |
|
||||
const mainComp = page.getMainComponent(); |
|
||||
lm && mainComp && lm.setRoot(mainComp); |
|
||||
em.trigger(evPageSelect, page, m.previous('selected')); |
|
||||
this.__onChange(chnSel, page, opts); |
|
||||
}, |
|
||||
|
|
||||
postLoad() { |
|
||||
const { em, model } = this; |
|
||||
const um = em.get('UndoManager'); |
|
||||
um && um.add(model); |
|
||||
um && um.add(this.pages); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new page |
|
||||
* @param {Object} props Page properties |
|
||||
* @param {Object} [opts] Options |
|
||||
* @returns {[Page]} |
|
||||
* @example |
|
||||
* const newPage = pageManager.add({ |
|
||||
* id: 'new-page-id', // without an explicit ID, a random one will be created
|
|
||||
* styles: `.my-class { color: red }`, // or a JSON of styles
|
|
||||
* component: '<div class="my-class">My element</div>', // or a JSON of components
|
|
||||
* }); |
|
||||
*/ |
|
||||
add(props, opts = {}) { |
|
||||
const { em } = this; |
|
||||
props.id = props.id || this._createId(); |
|
||||
const add = () => { |
|
||||
const page = this.pages.add(props, opts); |
|
||||
opts.select && this.select(page); |
|
||||
return page; |
|
||||
}; |
|
||||
!opts.silent && em.trigger(evPageAddBefore, props, add, opts); |
|
||||
return !opts.abort && add(); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Remove page |
|
||||
* @param {String|[Page]} page Page or page id |
|
||||
* @returns {[Page]} Removed Page |
|
||||
* @example |
|
||||
* const removedPage = pageManager.remove('page-id'); |
|
||||
* // or by passing the page
|
|
||||
* const somePage = pageManager.get('page-id'); |
|
||||
* pageManager.remove(somePage); |
|
||||
*/ |
|
||||
remove(page, opts = {}) { |
|
||||
const { em } = this; |
|
||||
const pg = isString(page) ? this.get(page) : page; |
|
||||
const rm = () => { |
|
||||
pg && this.pages.remove(pg, opts); |
|
||||
return pg; |
|
||||
}; |
|
||||
!opts.silent && em.trigger(evPageRemoveBefore, pg, rm, opts); |
|
||||
return !opts.abort && rm(); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get page by id |
|
||||
* @param {String} id Page id |
|
||||
* @returns {[Page]} |
|
||||
* @example |
|
||||
* const somePage = pageManager.get('page-id'); |
|
||||
*/ |
|
||||
get(id) { |
|
||||
return this.pages.filter(p => p.get('id') === id)[0]; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get main page (the first one available) |
|
||||
* @returns {[Page]} |
|
||||
* @example |
|
||||
* const mainPage = pageManager.getMain(); |
|
||||
*/ |
|
||||
getMain() { |
|
||||
const { pages } = this; |
|
||||
return pages.filter(p => p.get('type') === typeMain)[0] || pages.at(0); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get all pages |
|
||||
* @returns {Array<[Page]>} |
|
||||
* @example |
|
||||
* const arrayOfPages = pageManager.getAll(); |
|
||||
*/ |
|
||||
getAll() { |
|
||||
return [...this.pages.models]; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get wrapper components (aka body) from all pages and frames. |
|
||||
* @returns {Array<[Component]>} |
|
||||
* @example |
|
||||
* const wrappers = pageManager.getAllWrappers(); |
|
||||
* // Get all `image` components from the project
|
|
||||
* const allImages = wrappers.map(wrp => wrp.findType('image')).flat(); |
|
||||
*/ |
|
||||
getAllWrappers() { |
|
||||
const pages = this.getAll(); |
|
||||
return unique(flatten(pages.map(page => page.getAllFrames().map(frame => frame.getComponent())))); |
|
||||
}, |
|
||||
|
|
||||
getAllMap() { |
|
||||
return this.getAll().reduce((acc, i) => { |
|
||||
acc[i.get('id')] = i; |
|
||||
return acc; |
|
||||
}, {}); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Change the selected page. This will switch the page rendered in canvas |
|
||||
* @param {String|[Page]} page Page or page id |
|
||||
* @returns {this} |
|
||||
* @example |
|
||||
* pageManager.select('page-id'); |
|
||||
* // or by passing the page
|
|
||||
* const somePage = pageManager.get('page-id'); |
|
||||
* pageManager.select(somePage); |
|
||||
*/ |
|
||||
select(page, opts = {}) { |
|
||||
const pg = isString(page) ? this.get(page) : page; |
|
||||
if (pg) { |
|
||||
this.em.trigger(evPageSelectBefore, pg, opts); |
|
||||
this.model.set('selected', pg, opts); |
|
||||
} |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get the selected page |
|
||||
* @returns {[Page]} |
|
||||
* @example |
|
||||
* const selectedPage = pageManager.getSelected(); |
|
||||
*/ |
|
||||
getSelected() { |
|
||||
return this.model.get('selected'); |
|
||||
}, |
|
||||
|
|
||||
destroy() { |
|
||||
this.pages.off().reset(); |
|
||||
this.model.stopListening(); |
|
||||
this.model.clear({ silent: true }); |
|
||||
['selected', 'config', 'em', 'pages', 'model'].map(i => (this[i] = 0)); |
|
||||
}, |
|
||||
|
|
||||
store() { |
|
||||
return this.getProjectData(); |
|
||||
}, |
|
||||
|
|
||||
load(data) { |
|
||||
return this.loadProjectData(data, { all: this.pages, reset: true }); |
|
||||
}, |
|
||||
|
|
||||
_createId() { |
|
||||
const pages = this.getAll(); |
|
||||
const len = pages.length + 16; |
|
||||
const pagesMap = this.getAllMap(); |
|
||||
let id; |
|
||||
|
|
||||
do { |
|
||||
id = createId(len); |
|
||||
} while (pagesMap[id]); |
|
||||
|
|
||||
return id; |
|
||||
}, |
|
||||
}; |
|
||||
}; |
|
||||
@ -0,0 +1,290 @@ |
|||||
|
/** |
||||
|
* You can customize the initial state of the module from the editor initialization |
||||
|
* ```js
|
||||
|
* const editor = grapesjs.init({ |
||||
|
* .... |
||||
|
* pageManager: { |
||||
|
* pages: [ |
||||
|
* { |
||||
|
* id: 'page-id', |
||||
|
* styles: `.my-class { color: red }`, // or a JSON of styles
|
||||
|
* component: '<div class="my-class">My element</div>', // or a JSON of components
|
||||
|
* } |
||||
|
* ] |
||||
|
* }, |
||||
|
* }) |
||||
|
* ``` |
||||
|
* |
||||
|
* Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance |
||||
|
* |
||||
|
* ```js
|
||||
|
* const pageManager = editor.Pages; |
||||
|
* ``` |
||||
|
* |
||||
|
* ## Available Events |
||||
|
* * `page:add` - Added new page. The page is passed as an argument to the callback |
||||
|
* * `page:remove` - Page removed. The page is passed as an argument to the callback |
||||
|
* * `page:select` - New page selected. The newly selected page and the previous one, are passed as arguments to the callback |
||||
|
* * `page:update` - Page updated. The updated page and the object containing changes are passed as arguments to the callback |
||||
|
* * `page` - Catch-all event for all the events mentioned above. An object containing all the available data about the triggered event is passed as an argument to the callback |
||||
|
* |
||||
|
* ## Methods |
||||
|
* * [add](#add) |
||||
|
* * [get](#get) |
||||
|
* * [getAll](#getall) |
||||
|
* * [getAllWrappers](#getallwrappers) |
||||
|
* * [getMain](#getmain) |
||||
|
* * [remove](#remove) |
||||
|
* * [select](#select) |
||||
|
* * [getSelected](#getselected) |
||||
|
* |
||||
|
* [Page]: page.html |
||||
|
* [Component]: component.html |
||||
|
* |
||||
|
* @module Pages |
||||
|
*/ |
||||
|
|
||||
|
import { isString, bindAll, unique, flatten } from 'underscore'; |
||||
|
import { createId } from '../utils/mixins'; |
||||
|
import { Model, Module } from '../abstract'; |
||||
|
import { ItemManagerModule, ModuleConfig } from '../abstract/Module'; |
||||
|
import Pages from './model/Pages'; |
||||
|
import Page from './model/Page'; |
||||
|
import EditorModel from '../editor/model/Editor'; |
||||
|
|
||||
|
export const evAll = 'page'; |
||||
|
export const evPfx = `${evAll}:`; |
||||
|
export const evPageSelect = `${evPfx}select`; |
||||
|
export const evPageSelectBefore = `${evPageSelect}:before`; |
||||
|
export const evPageUpdate = `${evPfx}update`; |
||||
|
export const evPageAdd = `${evPfx}add`; |
||||
|
export const evPageAddBefore = `${evPageAdd}:before`; |
||||
|
export const evPageRemove = `${evPfx}remove`; |
||||
|
export const evPageRemoveBefore = `${evPageRemove}:before`; |
||||
|
const chnSel = 'change:selected'; |
||||
|
const typeMain = 'main'; |
||||
|
const events = { |
||||
|
all: evAll, |
||||
|
select: evPageSelect, |
||||
|
selectBefore: evPageSelectBefore, |
||||
|
update: evPageUpdate, |
||||
|
add: evPageAdd, |
||||
|
addBefore: evPageAddBefore, |
||||
|
remove: evPageRemove, |
||||
|
removeBefore: evPageRemoveBefore, |
||||
|
}; |
||||
|
|
||||
|
interface Config extends ModuleConfig { |
||||
|
pages?: string[]; |
||||
|
} |
||||
|
export default class PageManager extends ItemManagerModule<Config, Pages> { |
||||
|
storageKey = 'pages'; |
||||
|
|
||||
|
get pages() { |
||||
|
return this.all; |
||||
|
} |
||||
|
|
||||
|
model: Model; |
||||
|
/** |
||||
|
* Initialize module |
||||
|
* @param {Object} config Configurations |
||||
|
* @private |
||||
|
*/ |
||||
|
constructor(em: EditorModel) { |
||||
|
super(em, 'PageManager', new Pages([]), events); |
||||
|
bindAll(this, '_onPageChange'); |
||||
|
const model = new Model({ _undo: true } as any); |
||||
|
this.model = model; |
||||
|
this.pages.on('reset', (coll) => coll.at(0) && this.select(coll.at(0))); |
||||
|
this.pages.on('all', this.__onChange, this); |
||||
|
model.on(chnSel, this._onPageChange); |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
__onChange(event: string, page: Page, coll: Pages, opts?: any) { |
||||
|
const options = opts || coll; |
||||
|
this.em.trigger(evAll, { event, page, options }); |
||||
|
} |
||||
|
|
||||
|
onLoad() { |
||||
|
const { pages } = this; |
||||
|
const opt = { silent: true }; |
||||
|
pages.add( |
||||
|
this.config.pages?.map( |
||||
|
(page) => new Page(page, { em: this.em, config: this.config }) |
||||
|
) || [], |
||||
|
opt |
||||
|
); |
||||
|
const mainPage = !pages.length |
||||
|
? this.add({ type: typeMain }, opt) |
||||
|
: this.getMain(); |
||||
|
mainPage && this.select(mainPage, opt); |
||||
|
} |
||||
|
|
||||
|
_onPageChange(m: any, page: Page, opts: any) { |
||||
|
const { em } = this; |
||||
|
const lm = em.get('LayerManager'); |
||||
|
const mainComp = page.getMainComponent(); |
||||
|
lm && mainComp && lm.setRoot(mainComp); |
||||
|
em.trigger(evPageSelect, page, m.previous('selected')); |
||||
|
this.__onChange(chnSel, page, opts); |
||||
|
} |
||||
|
|
||||
|
postLoad() { |
||||
|
const { em, model } = this; |
||||
|
const um = em.get('UndoManager'); |
||||
|
um && um.add(model); |
||||
|
um && um.add(this.pages); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Add new page |
||||
|
* @param {Object} props Page properties |
||||
|
* @param {Object} [opts] Options |
||||
|
* @returns {[Page]} |
||||
|
* @example |
||||
|
* const newPage = pageManager.add({ |
||||
|
* id: 'new-page-id', // without an explicit ID, a random one will be created
|
||||
|
* styles: `.my-class { color: red }`, // or a JSON of styles
|
||||
|
* component: '<div class="my-class">My element</div>', // or a JSON of components
|
||||
|
* }); |
||||
|
*/ |
||||
|
add( |
||||
|
props: any, //{ id?: string; styles: string; component: string },
|
||||
|
opts: any = {} |
||||
|
) { |
||||
|
const { em } = this; |
||||
|
props.id = props.id || this._createId(); |
||||
|
const add = () => { |
||||
|
const page = this.pages.add( |
||||
|
new Page(props, { em: this.em, config: this.config }), |
||||
|
opts |
||||
|
); |
||||
|
opts.select && this.select(page); |
||||
|
return page; |
||||
|
}; |
||||
|
!opts.silent && em.trigger(evPageAddBefore, props, add, opts); |
||||
|
return !opts.abort && add(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Remove page |
||||
|
* @param {String|[Page]} page Page or page id |
||||
|
* @returns {[Page]} Removed Page |
||||
|
* @example |
||||
|
* const removedPage = pageManager.remove('page-id'); |
||||
|
* // or by passing the page
|
||||
|
* const somePage = pageManager.get('page-id'); |
||||
|
* pageManager.remove(somePage); |
||||
|
*/ |
||||
|
remove(page: string | Page, opts: any = {}) { |
||||
|
const { em } = this; |
||||
|
const pg = isString(page) ? this.get(page) : page; |
||||
|
const rm = () => { |
||||
|
pg && this.pages.remove(pg, opts); |
||||
|
return pg; |
||||
|
}; |
||||
|
!opts.silent && em.trigger(evPageRemoveBefore, pg, rm, opts); |
||||
|
return !opts.abort && rm(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get page by id |
||||
|
* @param {String} id Page id |
||||
|
* @returns {[Page]} |
||||
|
* @example |
||||
|
* const somePage = pageManager.get('page-id'); |
||||
|
*/ |
||||
|
get(id: string) { |
||||
|
return this.pages.filter((p) => p.get(p.idAttribute) === id)[0]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get main page (the first one available) |
||||
|
* @returns {[Page]} |
||||
|
* @example |
||||
|
* const mainPage = pageManager.getMain(); |
||||
|
*/ |
||||
|
getMain() { |
||||
|
const { pages } = this; |
||||
|
return pages.filter((p) => p.get('type') === typeMain)[0] || pages.at(0); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get wrapper components (aka body) from all pages and frames. |
||||
|
* @returns {Array<[Component]>} |
||||
|
* @example |
||||
|
* const wrappers = pageManager.getAllWrappers(); |
||||
|
* // Get all `image` components from the project
|
||||
|
* const allImages = wrappers.map(wrp => wrp.findType('image')).flat(); |
||||
|
*/ |
||||
|
getAllWrappers() { |
||||
|
const pages = this.getAll(); |
||||
|
return unique( |
||||
|
flatten( |
||||
|
pages.map((page) => |
||||
|
page.getAllFrames().map((frame) => frame.getComponent()) |
||||
|
) |
||||
|
) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Change the selected page. This will switch the page rendered in canvas |
||||
|
* @param {String|[Page]} page Page or page id |
||||
|
* @returns {this} |
||||
|
* @example |
||||
|
* pageManager.select('page-id'); |
||||
|
* // or by passing the page
|
||||
|
* const somePage = pageManager.get('page-id'); |
||||
|
* pageManager.select(somePage); |
||||
|
*/ |
||||
|
select(page: string | Page, opts = {}) { |
||||
|
const pg = isString(page) ? this.get(page) : page; |
||||
|
if (pg) { |
||||
|
this.em.trigger(evPageSelectBefore, pg, opts); |
||||
|
this.model.set('selected', pg, opts); |
||||
|
} |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the selected page |
||||
|
* @returns {[Page]} |
||||
|
* @example |
||||
|
* const selectedPage = pageManager.getSelected(); |
||||
|
*/ |
||||
|
getSelected() { |
||||
|
return this.model.get('selected'); |
||||
|
} |
||||
|
|
||||
|
destroy() { |
||||
|
this.pages.off().reset(); |
||||
|
this.model.stopListening(); |
||||
|
this.model.clear({ silent: true }); |
||||
|
//@ts-ignore
|
||||
|
['selected', 'model'].map((i) => (this[i] = 0)); |
||||
|
} |
||||
|
|
||||
|
store() { |
||||
|
return this.getProjectData(); |
||||
|
} |
||||
|
|
||||
|
load(data: any) { |
||||
|
return this.loadProjectData(data, { all: this.pages, reset: true }); |
||||
|
} |
||||
|
|
||||
|
_createId() { |
||||
|
const pages = this.getAll(); |
||||
|
const len = pages.length + 16; |
||||
|
const pagesMap = this.getAllMap(); |
||||
|
let id; |
||||
|
|
||||
|
do { |
||||
|
id = createId(len); |
||||
|
} while (pagesMap[id]); |
||||
|
|
||||
|
return id; |
||||
|
} |
||||
|
} |
||||
@ -1,26 +0,0 @@ |
|||||
import { Collection } from '../../common'; |
|
||||
import Page from './Page'; |
|
||||
|
|
||||
export default class Pages extends Collection { |
|
||||
initialize(models, config = {}) { |
|
||||
this.config = config; |
|
||||
this.on('reset', this.onReset); |
|
||||
this.on('remove', this.onRemove); |
|
||||
} |
|
||||
|
|
||||
onReset(m, opts = {}) { |
|
||||
const prev = opts.previousModels || []; |
|
||||
prev.map(p => this.onRemove(p)); |
|
||||
} |
|
||||
|
|
||||
onRemove(removed) { |
|
||||
removed && removed.onRemove(); |
|
||||
} |
|
||||
|
|
||||
add(m, o = {}) { |
|
||||
const { config } = this; |
|
||||
return Collection.prototype.add.call(this, m, { ...o, config }); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
Pages.prototype.model = Page; |
|
||||
@ -0,0 +1,18 @@ |
|||||
|
import { Collection } from '../../common'; |
||||
|
import Page from './Page'; |
||||
|
|
||||
|
export default class Pages extends Collection<Page> { |
||||
|
constructor(models: any) { |
||||
|
super(models); |
||||
|
this.on('reset', this.onReset); |
||||
|
this.on('remove', this.onRemove); |
||||
|
} |
||||
|
|
||||
|
onReset(m: Page, opts?: { previousModels?: Pages }) { |
||||
|
opts?.previousModels?.map((p) => this.onRemove(p)); |
||||
|
} |
||||
|
|
||||
|
onRemove(removed?: Page) { |
||||
|
removed?.onRemove(); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue