silex-website-builder-goodevent
Version:
Free and easy website builder for everyone.
176 lines (162 loc) • 5.3 kB
text/typescript
/**
* Silex, live web creation
* http://projects.silexlabs.org/?/silex/
*
* Copyright (c) 2012 Silex Labs
* http://www.silexlabs.org/
*
* Silex is available under the GPL license
* http://www.silexlabs.org/silex/silex-licensing/
*/
/**
* @fileoverview The Silex PageTool class displays the list of pages
* and let the user interact with them.
* @see silex.model.Page
*
*/
import { PageData } from '../model/page';
import { Controller, Model } from '../types';
import { Dom } from '../utils/dom';
import { InvalidationManager } from '../utils/invalidation-manager';
/**
*
* @param element container to render the UI
* @param model model class which holds
* the model instances - views use it for read
* operation only
* @param controller structure which holds
* the controller instances
*/
export class PageTool {
/**
* page list based on what is passed to redraw
* array of pages for the opened website
* @see silex.model.PageData
*/
pages: PageData[] = [];
/**
* invalidation mechanism
*/
invalidationManager: InvalidationManager;
constructor(public element: HTMLElement, public model: Model, public controller: Controller) {
this.invalidationManager = new InvalidationManager(500);
}
/**
* add listeners on the tool container
* called by the app constructor
*/
buildUi() {
// listen for the click on a page
this.element.addEventListener('click', (e) => {
if ((e.target as HTMLElement).classList.contains('delete')) {
// remove the page
this.removePageAtIndex(
this.getCellIndex((e.target as HTMLElement).parentElement.parentElement as HTMLElement));
} else {
if ((e.target as HTMLElement).classList.contains('label')) {
// rename the page
this.renamePageAtIndex(
this.getCellIndex((e.target as HTMLElement).parentElement.parentElement as HTMLElement));
} else {
// select page
const cellIndex = this.getCellIndex((e.target as HTMLElement).parentElement as HTMLElement);
if (cellIndex >= 0) {
this.setSelectedIndex(cellIndex, true);
}
}
}
e.preventDefault();
}, false);
function attach(className, cbk) {
Array.from(document.querySelectorAll(className))
.forEach((el) => el.onclick = cbk);
}
attach(
'.add-page', (e) => this.controller.insertMenuController.createPage());
attach(
'.remove-page', (e) => this.controller.pageToolController.removePage());
attach(
'.move-page-up',
(e) => this.controller.pageToolController.movePageUp());
attach(
'.move-page-down',
(e) => this.controller.pageToolController.movePageDown());
}
/**
* refresh the pages
* find all pages in the dom
* @param selectedElements the elements currently selected
* @param pageNames the names of the pages which appear in the current HTML file
* @param currentPageName the name of the current page
*/
redraw(
selectedElements: HTMLElement[], pageNames: string[],
currentPageName: string) {
this.invalidationManager.callWhenReady(() => {
// prepare the data for the template
// make an array with name, displayName, linkName and className
let idx = 0;
this.pages = pageNames.map((pageName) => {
const pageElement =
this.model.file.getContentDocument().getElementById(pageName);
if (!pageElement) {
// this happens while undoing or redoing
return null;
}
const res = {
name: pageName,
displayName: this.model.file.getContentDocument()
.getElementById(pageName)
.innerHTML,
linkName: '#!' + pageName,
idx: idx++,
className: '',
};
if (currentPageName === pageName) {
res.className = 'ui-selected';
}
return res;
});
// refresh the list with new pages
const container = this.element.getElementsByClassName('page-tool-container')[0];
const templateHtml = this.element.getElementsByClassName('page-tool-template')[0].innerHTML;
container.innerHTML = Dom.renderList(templateHtml, this.pages);
});
}
/**
* user wants to remove a page
* @param idx index of the page
*/
removePageAtIndex(idx: number) {
this.controller.pageToolController.removePage(this.pages[idx].name);
}
/**
* user wants to rename a page
* @param idx index of the page
*/
renamePageAtIndex(idx: number) {
this.controller.pageToolController.renamePage(this.pages[idx].name);
}
/**
* set the selection of pages
* @param opt_notify if true, then notify by calling the onChanged callback
*/
setSelectedIndex(idx: number, opt_notify?: boolean) {
// notify the controller
if (opt_notify) {
this.controller.pageToolController.openPage(this.pages[idx].name);
}
}
/**
* get the index of the given cell
* @param element which represents the cell in the dom
*/
getCellIndex(element: HTMLElement): number {
const pageIdx = element.getAttribute('data-page-idx');
if (pageIdx) {
return parseInt(pageIdx, 10);
} else {
return -1;
}
}
}