src/es6/presenter/base.es6
import {d3} from "nbpresent-deps";
import {SpeakerBase} from "../speaker/base";
import {ManualLayout} from "../layout/manual";
import {TreemapLayout} from "../layout/treemap";
import {PARTS, PART_SELECT} from "../parts";
import {SlabStyle} from "../style/slab";
let PREFIX = [
"-webkit-",
"-moz-",
"-ms-",
"-o-",
""
];
export class Presenter {
constructor(tree) {
this.tree = tree;
this.cellManager = this.makeCellManager();
this.speaker = this.makeSpeaker(this.tree);
this.initUI();
this.presenting = this.tree.select(["presenting"]);
this.current = this.tree.select(["selectedSlide"]);
this.tree.on("update", () => this.update());
this.presenting.on("update", () => this.present());
this.current.on("update", () => this.update());
}
makeCellManager() {
throw new Error("Not implemented");
}
makeSpeaker(tree){
return new SpeakerBase(tree);
}
initUI(){
this.$ui = d3.select("body")
.append("div")
.classed({nbpresent_presenter: 1})
.style({display: "none"});
}
layoutClass(slide){
return {
manual: ManualLayout,
treemap: TreemapLayout
}[slide.value.layout || "manual"];
}
updateLayout(slide){
let LayoutClass = this.layoutClass(slide);
if(this.layout &&
this.layout.key() == LayoutClass.clsKey() &&
this.layout.slide.key === slide.key
){
this.layout.slide = slide;
}else{
this.layout = new LayoutClass(
this.tree,
slide,
document.documentElement
);
}
this.layout.init();
}
present() {
this.update();
}
getCells() {
return this.cellManager.getCells();
}
update() {
let that = this;
let presenting = this.presenting.get();
d3.select("body").classed({nbpresent_presenting: presenting});
this.$ui
.style({
"display": presenting ? "block" : "none"
})
.style({
opacity: +presenting,
});
let current = this.current.get(),
slide = this.tree.get(["sortedSlides", (d) => d.key == current]);
// TODO: handle cleanup
// transition = this.layout && this.layout.destroy()
if(!slide){
return this.current.set(this.tree.get(["sortedSlides", 0, "key"]));
}
this.updateLayout(slide);
if(!presenting){
return this.clean(true);
}
let cells = this.getCells();
d3.selectAll(this.allPartSelect())
.classed({nbpresent_unpresent: 1, nbpresent_present: 0});
d3.entries(slide.value.regions)
.filter(({value}) => value.content)
.map((region) => {
let {content} = region.value,
cell = cells[content.cell];
if(!cell){
return;
}
let $el = d3.select(cell.element[0]),
part = $el.select(PART_SELECT[content.part]);
part
.classed({
nbpresent_unpresent: 0,
nbpresent_present: 1
})
.each(() => that.layout.update(region, part));
// TODO: now do styles
d3.entries(region.value.style).map((style) => {
// TODO: make this extensible
if(style.value && style.key === "slab"){
let styler = new SlabStyle();
styler.update(part);
}
})
});
this.clean();
}
allPartSelect(){
return d3.entries(PART_SELECT)
.map(({value}) => `.cell ${value}`)
.join(", ");
}
clean(force){
let that = this;
if(force){
d3.selectAll(this.allPartSelect())
.classed({nbpresent_unpresent: 1, nbpresent_present: 0});
}
d3.selectAll(".nbpresent_unpresent")
.call(that.layout && this.layout.clean || (() => 0))
.classed({nbpresent_unpresent: 0, nbpresent_present: 0});
}
}