Files
makemeahanzi/client/editor.js
2015-11-08 20:50:24 -05:00

152 lines
4.6 KiB
JavaScript

"use strict";
Session.set('editor.glyph', undefined);
const types = ['path', 'bridges', 'strokes', 'analysis', 'order', 'verified'];
let last_glyph = undefined;
let last_json = undefined;
let stage = new stages.AbstractStage;
const changeGlyph = (method, argument) => {
argument = argument || Session.get('editor.glyph');
Meteor.call(method, argument, function(error, data) {
assert(!error, error);
Session.set('editor.glyph', data);
window.location.hash = data.character;
});
}
const clearStageSessionKeys = (type) => {
Object.keys(Session.keys).filter((x) => x.startsWith(`stages.${type}.`))
.map((x) => Session.set(x, undefined));
}
const constructStage = (type) => {
const glyph = Session.get('editor.glyph');
const current = glyph.stages[type];
if (!current || current.sentinel) {
glyph.stages[type] = null;
}
clearStageSessionKeys(stage.type);
stage = new stages[type](glyph);
assert(stage.type === type);
stage.forceRefresh = forceRefresh;
stage.forceRefresh(true /* from_construct_stage */);
}
const forceRefresh = (from_construct_stage) => {
const glyph = Session.get('editor.glyph');
stage.refreshUI(glyph.character, glyph.metadata);
let output = stage.getStageOutput();
const current = glyph.stages[stage.type];
if (from_construct_stage && (!current || current.sentinel)) {
output = {sentinel: true};
}
if (!_.isEqual(output, current)) {
glyph.stages[stage.type] = output;
if (!output || !current || stage.clearLaterStages(output, current)) {
for (let i = types.indexOf(stage.type) + 1; i < types.length; i++) {
glyph.stages[types[i]] = null;
}
}
Session.set('editor.glyph', glyph);
}
}
const incrementStage = (amount) => {
const index = types.indexOf(stage.type);
if (index < 0) return;
const new_index = index + amount;
if (new_index < 0 || new_index >= types.length) return;
if (amount > 0) {
stage.validate();
stage.forceRefresh();
}
constructStage(types[new_index]);
}
const loadCharacter = () => {
const character = window.location.hash[1];
const glyph = Session.get('editor.glyph');
if (!character) {
changeGlyph('getNextGlyph');
} else if (!glyph || glyph.character !== character) {
changeGlyph('getGlyph', character);
}
}
const resetStage = () => {
const glyph = Session.get('editor.glyph');
glyph.stages[stage.type] = null;
Session.set('editor.glyph', glyph);
constructStage(stage.type);
}
const bindings = {
a: () => changeGlyph('getPreviousGlyph'),
A: () => changeGlyph('getPreviousUnverifiedGlyph'),
q: () => changeGlyph('getPreviousVerifiedGlyph'),
d: () => changeGlyph('getNextGlyph'),
D: () => changeGlyph('getNextUnverifiedGlyph'),
e: () => changeGlyph('getNextVerifiedGlyph'),
r: resetStage,
s: () => incrementStage(1),
w: () => incrementStage(-1),
};
// We avoid arrow functions in this map so that this is bound to the template.
Template.editor.events({
'click svg .selectable': function(event) {
stage.handleEvent(event, this);
stage.forceRefresh();
}
});
Template.editor.helpers({
paths: () => Session.get('stage.paths'),
lines: () => Session.get('stage.lines'),
points: () => Session.get('stage.points'),
animations: () => Session.get('stage.animations'),
});
Template.status.helpers({
stage: () => Session.get('stage.type'),
template: () => `${Session.get('stage.type')}_stage`,
lines: () => Session.get('stage.status'),
});
Tracker.autorun(() => {
const glyph = Session.get('editor.glyph');
const json = JSON.stringify(glyph);
if (!glyph || json === last_json) {
return;
} else if (!last_glyph || glyph.character !== last_glyph.character) {
let last_completed_stage = types[0];
types.map((x) => { if (glyph.stages[x]) last_completed_stage = x; });
constructStage(last_completed_stage);
} else {
Meteor.call('saveGlyph', glyph,
(error, data) => { if (error) console.error(error) });
if (!_.isEqual(glyph.metadata, last_glyph.metadata)) {
stage.refreshUI(glyph.character, glyph.metadata);
}
}
last_glyph = glyph;
last_json = json;
});
Meteor.startup(() => {
$('body').on('keypress', (event) => {
const key = String.fromCharCode(event.which);
if (bindings.hasOwnProperty(key)) {
bindings[key]();
} else if ('1' <= key && key <= '9') {
const index = key.charCodeAt(0) - '1'.charCodeAt(0);
const href = $('.metadata .reference')[index].href;
window.open(href, '_blank').focus();
}
});
$(window).on('hashchange', loadCharacter);
cjklib.promise.then(loadCharacter).catch(console.error.bind(console));
});