@sutton-signwriting/signmaker
Version:
Create and edit signs using Formal SignWriting in ASCII (FSW) or SignWriting in Unicode (SWU)
1,170 lines (1,117 loc) • 40.7 kB
JavaScript
/**
* Sutton SignWriting SignMaker 2022
* https://github.com/sutton-signwriting/signmaker
* Copyright (c) 2007-2021, Steve Slevinski
* SignMaker is released under the MIT License.
*/
var isApp = false;
var isiFrame = (window.location !== window.parent.location);
function receiveMessage(event) {
setS(event.data);
}
// event listener for message event
window.addEventListener("message", receiveMessage, false);
//translations
var t;
var allSignLang = {};
allSignLang['alphabet']=Object.keys(defmessages).filter(function(key){return (key.slice(0,4)=="sgn_");});
var signLang={};
signLang['alphabet'] = allSignLang['alphabet'].slice(0);
function checkSignLang(type) {
//type=alphabet or other
if (!allSignLang[type].length) return;
var key = allSignLang[type].shift();
var url = 'config/' + type + "/" + type + '-' + key.slice(4) + '.js';
var xhr = new XMLHttpRequest();
xhr.open('HEAD', url, true);
xhr.onload = function (e) {
if (xhr.status == 404) {
var index = signLang[type].indexOf(key);
if (index > -1) {
signLang[type].splice(index, 1);
}
}
checkSignLang(type);
};
xhr.onerror = function (e) {
var index = signLang[type].indexOf(key);
if (index > -1) {
signLang[type].splice(index, 1);
}
checkSignLang(type);
};
xhr.send(null);
}
function tt(args){
text = t.apply(this,arguments);
text = text.replace(/@@/g,'');
return m.trust(ssw.svg(text) || '<p>' + text + '</p>');
}
window.onresize = function (){
m.redraw();
}
function setS(obj){
Object.keys(obj).map( key => {
val = obj[key];
if (S[key] == val) return;
switch (key) {
case 'ui':
if(t && val==S['ui']) return;
var msg = messages[val];
if (!msg) {
val='en';
msg = messages[val];
}
S['ui']=val;
for (var attr in defmessages) { if(!msg[attr]) msg[attr]=defmessages[attr];}
t = libTranslate.getTranslationFunction(msg);
break;
case 'alphabet':
S['alphabet']=val;
classie.addClass(document.body,"waiting");
var js = document.createElement("script");
js.type = "text/javascript";
delete window.alphabet;
if (val == 'iswa' || val == ''){
js.src = "config/alphabet.js?" + Date.now();
} else {
js.src = "config/alphabet/alphabet-" + val + ".js?" + Date.now();
}
document.getElementsByTagName('head')[0].appendChild(js);
var jsCheck = setInterval(function(){
if (window.alphabet && palette){
classie.removeClass(document.body,"waiting");
palette.vm.init();
palette.vm.select();
m.redraw();
clearInterval(jsCheck);
}
},100);
break;
case 'fsw':
S['fsw'] = val;
signmaker && signmaker.vm.fsw(val);
break;
case 'charsets':
S['charsets'] = val;
console.log("charset to hash?");
break;
case 'swu':
val = decodeURI(val)
S['swu'] = val;
signmaker && signmaker.vm.swu(val);
break;
case 'styling':
S['styling'] = val;
break;
case 'grid':
S['grid'] = val;
break;
case 'skin':
S['skin'] = val;
document.body.className=val;
break;
case 'tab':
S['tab'] = val;
break;
}
})
m.redraw();
}
//state
var S = { // state
'ui': undefined,
'alphabet': undefined,
'fsw': undefined,
'charsets': undefined,
'swu': undefined,
'styling': undefined,
'grid': undefined,
'skin': undefined,
'tab': undefined
}
var D = { // defaults
'ui': 'en',
'alphabet': 'iswa',
'grid': '1',
'tab': ''
}
function hash(){
S['fsw'] = signmaker.vm.fswnorm();
if (S['charsets']) S['swu'] = signmaker.vm.swunorm();
return "?" + Object.keys(S).map(function(key){
return (S[key] && (D[key] != S[key]))?key+"="+S[key]:undefined
}).filter(item => item !== undefined).join("&");
}
function hashSet(){
// history.replaceState(null, null, document.location.pathname + '#' + hash);
history.pushState(null, null, document.location.pathname + '#' + hash());
// window.location.hash = hash;
}
window.onhashchange = hashChange;
function hashChange(event){
var parts;
var hashed = {}
var iloc = window.location.href.indexOf('#?');
if (iloc>-1) {
var hashes = decodeURI(window.location.href.slice(iloc + 2)).split('&');
for(var i = 0; i < hashes.length; i++) {
parts = hashes[i].split('=');
if (parts[0]) hashed[parts[0]] = parts[1];
}
}
hashed = {...D, ...hashed}
Object.keys(hashed).forEach(key => {
if (!(key in S)) {
hashed[key] = undefined;
}
})
setS(hashed);
}
hashChange();
// SIGNMAKER
////////////
var dlFile = null;
var spatials = {};
spatials.Symbol = function(data) {
this.key = m.prop(data.key);
this.x = m.prop(data.x);
this.y = m.prop(data.y);
this.selected = m.prop(true);
};
spatials.List = Array;
var signmaker = {};
// vm
signmaker.vm = {
midWidth: 125,
midHeight: 125,
new: function(){
signmaker.vm.list=new spatials.List();
signmaker.vm.sort=[];
signmaker.vm.history = ['{"list":[],"sort":[]'];
signmaker.vm.cursor = 0;
},
save: function(){
if (isiFrame){
parent.postMessage({'signmaker': 'save', 'swu': signmaker.vm.swunorm(), 'fsw': signmaker.vm.fswnorm()},"*")
} else {
hashSet();
console.log(window.location.href)
}
},
share: function(){
if (navigator.share) {
navigator.share({'url': document.location.href})
} else {
console.log(window.location.href);
}
},
demo: function(){
window.location = "./demo.html#" + hash();
},
cancel: function(){
if (isiFrame){
parent.postMessage({'signmaker': 'cancel'},"*")
}
//signmaker.vm.clear();
palette.vm.action = false;
},
fswlive: function(){
var fsw = 'M500x500';
if (signmaker.vm.sort.length) fsw = "A" + signmaker.vm.sort.join('') + fsw;
if (signmaker.vm.list.length){
for (var i=0; i < signmaker.vm.list.length; i++) {
fsw += signmaker.vm.list[i].key() + signmaker.vm.list[i].x() + 'x' + signmaker.vm.list[i].y();
}
var bbox = ssw.bbox(ssw.max(fsw)).split(' ');
fsw = fsw.replace("M500x500","M" + bbox[1] + 'x' + bbox[3]);
}
return fsw=="M500x500"?'':fsw;
},
swulive: function(){
return ssw.fsw2swu(signmaker.vm.fswlive());
},
swunorm: function(){
return ssw.fsw2swu(signmaker.vm.fswnorm());
},
fswnorm: function(){
return ssw.norm(signmaker.vm.fswlive());
},
fsw: function(fsw,silent){
if (typeof(fsw)!='undefined') {
fsw = ssw.sign(fsw);
var syms = fsw.match(/S[1-3][0-9a-f]{2}[0-5][0-9a-f][0-9]{3}x[0-9]{3}/g) || [];
signmaker.vm.list = new spatials.List();
for (var i=0; i < syms.length; i++) {
signmaker.vm.list.push(new spatials.Symbol({key:syms[i].slice(0,6),x:parseInt(syms[i].slice(6,9)),y:parseInt(syms[i].slice(10,13))}))
}
syms = fsw.match(/A(S[1-3][0-9a-f]{2}[0-5][0-9a-f])+/) || [];
if (syms.length) {
signmaker.vm.sort= syms[0].slice(1).match(/.{6}/g);
} else {
signmaker.vm.sort = [];
}
signmaker.vm.addhistory(silent);
signmaker.vm.selnone();
}
return signmaker.vm.fswlive();
},
fswraw: '',
fswview: function(fsw){
if (typeof(fsw)!='undefined') {
signmaker.vm.fswraw = fsw;
signmaker.vm.swuraw = '';
fsw = ssw.parse(fsw,"fsw")["fsw"];
signmaker.vm.fsw(fsw,true);
if (fsw==signmaker.vm.fswraw) {
signmaker.vm.fswraw = '';
} else {
fsw = signmaker.vm.fswraw;
}
} else {
fsw = signmaker.vm.fswraw || signmaker.vm.fswnorm();
}
return fsw;
},
swu: function(swu,silent){
if (swu!='undefined') {
signmaker.vm.fsw(ssw.swu2fsw(swu),silent);
} else {
fsw = 'M500x500';
if (signmaker.vm.sort.length) fsw = "A" + signmaker.vm.sort.join('') + fsw;
for (var i=0; i < signmaker.vm.list.length; i++) {
fsw += signmaker.vm.list[i].key() + signmaker.vm.list[i].x() + 'x' + signmaker.vm.list[i].y();
}
}
},
swuraw: '',
swuview: function(swu){
if (typeof(swu)!='undefined') {
signmaker.vm.swuraw = swu;
signmaker.vm.fswraw = '';
swu = ssw.parse(swu,"swu")["swu"];
signmaker.vm.swu(swu,true);
if (swu==signmaker.vm.swuraw) {
signmaker.vm.swuraw = '';
} else {
swu = signmaker.vm.swuraw;
}
} else {
swu = signmaker.vm.swuraw || signmaker.vm.swunorm();
}
return swu;
},
styling: m.prop(''),
dlpng: function(){
var canvas = ssw.canvas(signmaker.vm.fswnorm()+signmaker.vm.styling(),{size: signmaker.vm.size(), pad: signmaker.vm.pad(), line: signmaker.vm.linecolor(), fill: signmaker.vm.fillcolor(), back: signmaker.vm.backcolor(), colorize: signmaker.vm.colorize()});
var data = canvas.toDataURL("image/png");
var link = document.getElementById('downloadlink');
link.href = data;
link.download=("sign") + ".png" ;
link.click();
},
dlsvg: function(){
var svg = ssw.svg(signmaker.vm.fswnorm()+signmaker.vm.styling(),{
size: signmaker.vm.size(),
pad: signmaker.vm.pad(),
line: signmaker.vm.linecolor(),
fill: signmaker.vm.fillcolor(),
back: signmaker.vm.backcolor(),
colorize: signmaker.vm.colorize(),
copy: (signmaker.vm.chars == "swu")?"opt":''
});
var data = new Blob([svg], {type: 'image/svg+xml'});
if (dlFile !== null) {
window.URL.revokeObjectURL(dlFile);
}
dlFile = window.URL.createObjectURL(data);
var link = document.getElementById('downloadlink');
link.href = dlFile;
link.download=("sign") + ".svg" ;
link.click();
},
size: m.prop('1'),
pad: m.prop('0'),
linecolor: m.prop('black'),
fillcolor: m.prop('white'),
backcolor: m.prop(''),
colorize: m.prop(''),
center: function(){
signmaker.vm.fsw(ssw.norm(signmaker.vm.fsw()));
},
list: new spatials.List(),
sort: [],
history: ['{"list":[],"sort":[]'],
cursor: 0,
addhistory: function(silent){
if (!silent) {
signmaker.vm.fswraw = '';
signmaker.vm.swuraw = '';
}
var history ={list:signmaker.vm.list,sort:signmaker.vm.sort};
var newhist = JSON.stringify(history).replace(/true/g,'false');
if (newhist != signmaker.vm.history[signmaker.vm.cursor]){
signmaker.vm.cursor++;
signmaker.vm.history = signmaker.vm.history.slice(0,signmaker.vm.cursor);
signmaker.vm.history.push(newhist);
hashSet();
}
},
undo: function(){
if (signmaker.vm.cursor<=0) return;
signmaker.vm.cursor--;
var history = JSON.parse(signmaker.vm.history[signmaker.vm.cursor]);
var syms = history['list'];
signmaker.vm.list = new spatials.List();
for (var i=0; i < syms.length; i++) {
signmaker.vm.list.push(new spatials.Symbol({key:syms[i]['key'],x:syms[i]['x'],y:syms[i]['y']}))
}
signmaker.vm.selnone();
signmaker.vm.sort = history['sort'];
m.redraw();
},
redo: function(){
if ((signmaker.vm.cursor+1)>=signmaker.vm.history.length) return;
signmaker.vm.cursor++;
var history = JSON.parse(signmaker.vm.history[signmaker.vm.cursor]);
var syms = history['list'];
signmaker.vm.list = new spatials.List();
for (var i=0; i < syms.length; i++) {
signmaker.vm.list.push(new spatials.Symbol({key:syms[i]['key'],x:syms[i]['x'],y:syms[i]['y']}))
}
signmaker.vm.selnone();
signmaker.vm.sort = history['sort'];
m.redraw();
},
add: function(symbol) {
signmaker.vm.selnone();
if (symbol) {
signmaker.vm.list.push(new spatials.Symbol(symbol));
}
signmaker.vm.addhistory();
m.redraw();
},
addSeq: function(key,position) {
signmaker.vm.sort.splice(position, 0, key);
signmaker.vm.addhistory();
m.redraw();
},
selnone: function() {
for (var i=0; i < signmaker.vm.list.length; i++) {
signmaker.vm.list[i].selected(false);
}
},
copy: function() {
var len = signmaker.vm.list.length;
for (var i=0; i < len; i++) {
if (signmaker.vm.list[i].selected()){
var symbol = signmaker.vm.list[i];
signmaker.vm.add({key:symbol.key(),x:symbol.x()+10,y:symbol.y()+10});
}
}
signmaker.vm.addhistory();
m.redraw();
},
delete: function() {
for (var i=0; i < signmaker.vm.list.length; i++) {
if (signmaker.vm.list[i].selected()){
signmaker.vm.list.splice(i,1);
}
}
signmaker.vm.addhistory();
m.redraw();
},
clear: function() {
signmaker.vm.list = new spatials.List();
signmaker.vm.sort=[];
signmaker.vm.addhistory();
m.redraw();
},
variation: function(step) {
for (var i=0; i < signmaker.vm.list.length; i++) {
if (signmaker.vm.list[i].selected()){
signmaker.vm.list[i].key(ssw.scroll(signmaker.vm.list[i].key(),step));
}
}
signmaker.vm.addhistory();
m.redraw();
},
mirror: function() {
for (var i=0; i < signmaker.vm.list.length; i++) {
if (signmaker.vm.list[i].selected()){
signmaker.vm.list[i].key(ssw.mirror(signmaker.vm.list[i].key()));
}
}
signmaker.vm.addhistory();
m.redraw();
},
fill: function(step) {
for (var i=0; i < signmaker.vm.list.length; i++) {
if (signmaker.vm.list[i].selected()){
signmaker.vm.list[i].key(ssw.fill(signmaker.vm.list[i].key(),step));
}
}
signmaker.vm.addhistory();
m.redraw();
},
over: function() {
var len = signmaker.vm.list.length;
for (var i=0; i < len; i++) {
if (signmaker.vm.list[i].selected()){
var symbol = signmaker.vm.list[i];
signmaker.vm.add({key:symbol.key(),x:symbol.x(),y:symbol.y()});
signmaker.vm.list.splice(i,1);
len--;
}
}
signmaker.vm.addhistory();
m.redraw();
},
rotate: function(step) {
for (var i=0; i < signmaker.vm.list.length; i++) {
if (signmaker.vm.list[i].selected()){
signmaker.vm.list[i].key(ssw.rotate(signmaker.vm.list[i].key(),step));
}
}
signmaker.vm.addhistory();
m.redraw();
},
select: function(step) {
if (!signmaker.vm.list.length) return;
var sel = 0;
for (var i=0; i < signmaker.vm.list.length; i++) {
if (signmaker.vm.list[i].selected()){
sel = i;
}
}
sel += step;
if (sel<0) sel = signmaker.vm.list.length-1;
if (sel>=signmaker.vm.list.length) sel = 0;
signmaker.vm.selnone();
signmaker.vm.list[sel].selected(true);
m.redraw();
},
move: function(x,y) {
for (var i=0; i < signmaker.vm.list.length; i++) {
if (signmaker.vm.list[i].selected()){
signmaker.vm.list[i].x(signmaker.vm.list[i].x()+x);
signmaker.vm.list[i].y(signmaker.vm.list[i].y()+y);
}
}
signmaker.vm.addhistory();
m.redraw();
}
};
signmaker.controller = function(){
// signmaker.vm.init();
};
function sbDragEnd( draggie,e,p ) {
var sb = document.getElementById("signbox");
var drag = draggie.dragPoint;
if (overlap(draggie.element,sb)){
signmaker.vm.list[draggie.element.index].x(signmaker.vm.list[draggie.element.index].x() + drag.x);
signmaker.vm.list[draggie.element.index].y(signmaker.vm.list[draggie.element.index].y() + drag.y);
signmaker.vm.addhistory();
m.redraw();
} else {
var seq = document.getElementById("sequence");
if (overlap(draggie.element,seq)){
var position = parseInt(draggie.position.y / (window.innerHeight/20));
var key = signmaker.vm.list[draggie.element.index].key();
signmaker.vm.addSeq(key,position);
}
draggie.element.style.left = (parseInt(draggie.element.style.left) - drag.x) + 'px';
draggie.element.style.top = (parseInt(draggie.element.style.top) - drag.y) + 'px';
}
}
function sbDragStart( draggie ){
signmaker.vm.selnone();
signmaker.vm.list[draggie.element.index].selected(true);
}
function seqDragEnd( draggie,e,p ) {
var position1 = parseInt(draggie.startPoint.y / (window.innerHeight/20));
var position2 = parseInt((draggie.startPoint.y+draggie.dragPoint.y) / (window.innerHeight/20));
draggie.element.style.left = (parseInt(draggie.element.style.left) - draggie.dragPoint.x) + 'px';
draggie.element.style.top = (parseInt(draggie.element.style.top) - draggie.dragPoint.y) + 'px';
if (position1<signmaker.vm.sort.length){
if (position1!=position2){
signmaker.vm.sort.splice(position2, 0, signmaker.vm.sort.splice(position1, 1)[0]);
} else {
signmaker.vm.sort.splice(position1,1);
}
signmaker.vm.addhistory();
m.redraw();
}
}
signmaker.view = function(ctrl){
var clientWidth = document.getElementById('signmaker').clientWidth*.90
var clientHeight = document.getElementById('signmaker').clientHeight*.5;
signmaker.vm.midWidth = parseInt(clientWidth/2);
signmaker.vm.midHeight = parseInt(clientHeight/2);
var bbox = ssw.bbox(ssw.max(signmaker.vm.fsw())).split(" ");
//check if bbox is outside of display
if (bbox.length==4){
if (bbox[0]<510-signmaker.vm.midWidth || bbox[1]>490+signmaker.vm.midWidth) { // left or right
signmaker.vm.midWidth = signmaker.vm.midWidth + 500 - parseInt((parseInt(bbox[0])+parseInt(bbox[1]))/2);
}
if (bbox[2]<510-signmaker.vm.midHeight || bbox[3]>490+signmaker.vm.midHeight) { // top or bottom
signmaker.vm.midHeight = signmaker.vm.midHeight + 500 - parseInt((parseInt(bbox[2])+parseInt(bbox[3]))/2);
}
}
var grid = '';
switch (S['grid'] || "0") {
case "0":
break;
case "1":
grid = '<svg width="' + clientWidth + '" height="' + clientHeight + '" viewBox="0 0 ' + clientWidth + ' ' + clientHeight + '" xmlns="http://www.w3.org/2000/svg" version="1.1">';
grid += '<g stroke="gray" >';
grid += '<line x1="0" y1="' + signmaker.vm.midHeight + '" x2="' + clientWidth + '" y2="' + signmaker.vm.midHeight + '" stroke-width="1" />';
grid += '<line y1="0" x1="' + signmaker.vm.midWidth + '" y2="' + clientHeight + '" x2="' + signmaker.vm.midWidth + '" stroke-width="1" />';
grid += '</g>';
grid += '</svg>';
break;
case "2":
grid = '<svg width="' + clientWidth + '" height="' + clientHeight + '" viewBox="0 0 ' + clientWidth + ' ' + clientHeight + '" xmlns="http://www.w3.org/2000/svg" version="1.1">';
grid += '<g stroke="lightgray" >';
var startH = signmaker.vm.midHeight % 10;
var startW = signmaker.vm.midWidth % 10;
for (var w=startW;w<clientWidth;w+=10){
grid += '<line y1="0" x1="' + w + '" y2="' + clientHeight + '" x2="' + w + '" stroke-width="1" />';
}
for (var h=startH;h<clientHeight;h+=10){
grid += '<line x1="0" y1="' + h + '" x2="' + clientWidth + '" y2="' + h + '" stroke-width="1" />';
}
grid += '</g>';
grid += '<g stroke="gray" >';
grid += '<line x1="0" y1="' + signmaker.vm.midHeight + '" x2="' + clientWidth + '" y2="' + signmaker.vm.midHeight + '" stroke-width="1" />';
grid += '<line y1="0" x1="' + signmaker.vm.midWidth + '" y2="' + clientHeight + '" x2="' + signmaker.vm.midWidth + '" stroke-width="1" />';
grid += '</g>';
grid += '</svg>';
break;
}
var editor = [m('div',{id:"signbox"},[
m("div",m.trust(grid)),
signmaker.vm.list.map(function(symbol, index) {
return m("div"
, {
"class": symbol.selected() ? "selected" : "",
style:{
left: (parseInt(symbol.x())-500+signmaker.vm.midWidth).toString() + 'px',
top: (parseInt(symbol.y())-500+signmaker.vm.midHeight).toString() + 'px'
},
config: function(element, isInitialized) {
element.index=index;
if (!isInitialized) {
var draggie = new Draggabilly(element,{containment:"#signmaker"});
draggie.on( 'dragStart', sbDragStart );
draggie.on( 'dragEnd', sbDragEnd );
}
}
},m.trust(ssw.svg(symbol.key())));
})
]),
m('div',{id:"sequence"},
signmaker.vm.sort.concat('').map(function(key) {
return m("div.sort"
, {
config: function(element, isInitialized) {
element.key=key;
if (!isInitialized) {
var draggie = new Draggabilly(element,{containment:"#sequence"});
draggie.on( 'dragEnd', seqDragEnd );
}
}
},m.trust(ssw.svg(key)));
}))
];
var currentTab;
switch (S['tab']) {
case '': // signmaker commands
currentTab = [
m("div.cmdslim.clickable.",{onclick: signmaker.vm.move.bind(signmaker.vm,-1,0)},tt('moveLeft')),
m('div.cmdslim.clickable',{onclick: signmaker.vm.move.bind(signmaker.vm,0,-1)},tt('moveUp')),
m('div.cmdslim.clickable',{onclick: signmaker.vm.move.bind(signmaker.vm,0,1)},tt('moveDown')),
m('div.cmdslim.clickable',{onclick: signmaker.vm.move.bind(signmaker.vm,1,0)},tt('moveRight')),
m('div',{style:"clear:both;height:0%"}),
m('div.cmd.clickable',{onclick: signmaker.vm.copy},tt("copy")),
m('div.cmd.clickable',{onclick: signmaker.vm.mirror},tt('mirror')),
m('div.cmd.clickable',{onclick: signmaker.vm.center},tt('center')),
m('div.cmd.clickable',{onclick: signmaker.vm.delete},tt('delete')),
m('div.cmd.clickable',{onclick: signmaker.vm.rotate.bind(signmaker.vm,-1)},tt('rotateCCW')),
m('div.cmd.clickable',{onclick: signmaker.vm.rotate.bind(signmaker.vm,1)},tt('rotateCW')),
m('div.cmd.clickable',{onclick: signmaker.vm.select.bind(signmaker.vm,1)},tt('selectNext')),
m('div.cmd',{"class": (signmaker.vm.cursor<=0)?"disabled":"clickable",onclick: signmaker.vm.undo}, tt('undo')),
m('div.cmd.clickable',{onclick: signmaker.vm.fill.bind(signmaker.vm,-1)},tt('fillPrev')),
m('div.cmd.clickable',{onclick: signmaker.vm.fill.bind(signmaker.vm,1)},tt('fillNext')),
m('div.cmd.clickable',{onclick: signmaker.vm.select.bind(signmaker.vm,-1)},tt('selectPrev')),
m('div.cmd',{"class": ((signmaker.vm.cursor+1)>=signmaker.vm.history.length)?"disabled":"clickable",onclick: signmaker.vm.redo},tt('redo')),
m('div.cmd.clickable',{onclick: signmaker.vm.variation.bind(signmaker.vm,-1)},tt('variationPrev')),
m('div.cmd.clickable',{onclick: signmaker.vm.variation.bind(signmaker.vm,1)},tt('variationNext')),
m('div.cmd.clickable',{onclick: signmaker.vm.over},tt('placeOver')),
m('div.cmd.clickable',{onclick: signmaker.vm.clear},tt('clearAll'))
];
break;
case 'png':
currentTab = [
m('div.cmd',{"class": (S['tab'] == 'png') ? "selected" : "unselected",onclick: () => setS({'tab':'png'})},tt("pngImage")),
m('div.cmd',{"class": (S['tab'] == 'svg') ? "selected" : "unselected",onclick: () => setS({'tab':'svg'})},tt("svgImage")),
m('div.cmdslim',tt('size')
),
m('div.cmdslim',
m("input",{id:"size",value:signmaker.vm.size(),oninput:m.withAttr('value',signmaker.vm.size)})
),
m('div.cmdslim',tt('pad')
),
m('div.cmdslim',
m("input",{id:"pad",value:signmaker.vm.pad(),oninput:m.withAttr('value',signmaker.vm.pad)})
),
m('div.cmdslim',tt('line')
),
m('div.cmdslim',
m("input",{id:"line",value:signmaker.vm.linecolor(),oninput:m.withAttr('value',signmaker.vm.linecolor)})
),
m('div.cmdslim',tt('fill')
),
m('div.cmdslim',
m("input",{id:"fill",value:signmaker.vm.fillcolor(),oninput:m.withAttr('value',signmaker.vm.fillcolor)})
),
m('div.cmdslim',tt('background')
),
m('div.cmdslim',
m("input",{id:"back",value:signmaker.vm.backcolor(),oninput:m.withAttr('value',signmaker.vm.backcolor)})
),
m('div.cmdslim',tt('colorize')
),
m('div.cmdslim',
m("input",{id:"colorize",type:"checkbox",checked:signmaker.vm.colorize(),onclick:m.withAttr('checked',signmaker.vm.colorize)})
),
m('div.cmdrow',
m("p.fsw","Styling: "),
m("input",{id:"styling",value:signmaker.vm.styling(),oninput:m.withAttr("value",signmaker.vm.styling)})
),
isApp?'':m('div.cmd.clickable',{onclick: signmaker.vm.dlpng},tt('download')),
];
var canvas = ssw.canvas(signmaker.vm.fswnorm()+signmaker.vm.styling(),{size: signmaker.vm.size(), pad: signmaker.vm.pad(), line: signmaker.vm.linecolor(), fill: signmaker.vm.fillcolor(), back: signmaker.vm.backcolor(), colorize: signmaker.vm.colorize()});
var data = canvas?canvas.toDataURL("image/png"):"";
editor = m('div',{id:"signbox"},
m('div.mid',
m('img',{src:data,value:("sign") + ".png"})
)
);
break;
case "svg":
currentTab = [
m('div.cmd',{"class": (S['tab'] == 'png') ? "selected" : "unselected",onclick: () => setS({'tab':'png'})},tt("pngImage")),
m('div.cmd',{"class": (S['tab'] == 'svg') ? "selected" : "unselected",onclick: () => setS({'tab':'svg'})},tt("svgImage")),
m('div.cmdslim',tt('size')
),
m('div.cmdslim',
m("input",{id:"size",value:signmaker.vm.size(),oninput:m.withAttr('value',signmaker.vm.size)})
),
m('div.cmdslim',tt('pad')
),
m('div.cmdslim',
m("input",{id:"pad",value:signmaker.vm.pad(),oninput:m.withAttr('value',signmaker.vm.pad)})
),
m('div.cmdslim',tt('line')
),
m('div.cmdslim',
m("input",{id:"line",value:signmaker.vm.linecolor(),oninput:m.withAttr('value',signmaker.vm.linecolor)})
),
m('div.cmdslim',tt('fill')
),
m('div.cmdslim',
m("input",{id:"fill",value:signmaker.vm.fillcolor(),oninput:m.withAttr('value',signmaker.vm.fillcolor)})
),
m('div.cmdslim',tt('background')
),
m('div.cmdslim',
m("input",{id:"back",value:signmaker.vm.backcolor(),oninput:m.withAttr('value',signmaker.vm.backcolor)})
),
m('div.cmdslim',tt('colorize')
),
m('div.cmdslim',
m("input",{id:"colorize",type:"checkbox",checked:signmaker.vm.colorize(),onclick:m.withAttr('checked',signmaker.vm.colorize)})
),
m('div.cmdrow',
m("p.fsw","Styling: "),
m("input",{id:"styling",value:signmaker.vm.styling(),oninput:m.withAttr("value",signmaker.vm.styling)})
),
isApp?'':m('div.cmd.clickable',{onclick: signmaker.vm.dlsvg},tt('download')),
];
var svg = ssw.svg(signmaker.vm.fswnorm()+signmaker.vm.styling(),{
size: signmaker.vm.size(),
pad: signmaker.vm.pad(),
line: signmaker.vm.linecolor(),
fill: signmaker.vm.fillcolor(),
back: signmaker.vm.backcolor(),
colorize: signmaker.vm.colorize(),
copy: (signmaker.vm.chars == "swu")?"opt":''
});
editor = m('div',{id:"signbox"},
m('div.mid',
m.trust(svg)
)
);
break;
case "more":
var alphaSignLang = signLang['alphabet'].map(function(key){
return t(key) + '\t' + key.slice(4);
});
alphaSignLang.sort();
currentTab = [
m('div.cmd',{"class": (S['tab'] == 'png') ? "selected" : "unselected",onclick: () => setS({'tab':'png'})},tt("pngImage")),
m('div.cmd',{"class": (S['tab'] == 'svg') ? "selected" : "unselected",onclick: () => setS({'tab':'svg'})},tt("svgImage")),
m('div.cmdslim',tt('userInterface')
),
m('div.cmdlong',
m('select', {id: 'language',onchange:function(e){setS({'ui':e.target.value});}},
m('optgroup',
Object.keys(messages).map(function(key){
return m('option',{value: key,selected:(key==S['ui'])},messages[key]['language']);
})
)
)
),
m('div.cmdslim',tt('alphabet')
),
m('div.cmdlong',
m('select', {id: 'alphaLang',onchange:function(e){setS({'alphabet':e.target.value});}},
m('optgroup',
m('option',{value:''},t('iswa2010')),
alphaSignLang.map(function(val){
var vals = val.split('\t');
return m('option',{value: vals[1],selected:(vals[1]==S['alphabet'])},vals[0]);
})
)
)
),
m('div.cmdslim',tt('grid')
),
m('div.cmdslim.clickable',{"class": (S['grid']=="0") ? "checked" : "unchecked",onclick: function(){setS({'grid':"0"});}},tt('grid0')),
m('div.cmdslim.clickable',{"class": (S['grid']=="1") ? "checked" : "unchecked",onclick: function(){setS({'grid':"1"});}},tt('grid1')),
m('div.cmdslim.clickable',{"class": (S['grid']=="2") ? "checked" : "unchecked",onclick: function(){setS({'grid':"2"});}},tt('grid2')),
m('div.cmdslim',tt('skin')
),
m('div.cmdslim.clickable',{"class": (S['skin']=="" || S['skin']==undefined) ? "checked" : "unchecked",onclick: function(){setS({'skin': ''});}},tt('blackOnWhite')),
m('div.cmdslim.clickable',{"class": (S['skin']=="inverse") ? "checked" : "unchecked",onclick: function(){setS({'skin': 'inverse'});}},tt('whiteOnBlack')),
m('div.cmdslim.clickable',{"class": (S['skin']=="colorful") ? "checked" : "unchecked",onclick: function(){setS({'skin': 'colorful'});}},tt('colorful')),
m('div.cmdrow',
m("p.fsw","FSW:"),
m("input",{"class": (signmaker.vm.fswraw && (signmaker.vm.fswraw != signmaker.vm.fswlive()))?'warning':'',id:"fsw",value:signmaker.vm.fswview(),oninput:m.withAttr("value",signmaker.vm.fswview)})
),
m('div', {"class":(signmaker.vm.chars=="fsw")?'cmdrow':'cmdfull'},
m("p.swu","SWU:"),
m("input",{"class": (signmaker.vm.swuraw && (signmaker.vm.swuraw != signmaker.vm.swulive()))?'warning':'',id:"swu",value:signmaker.vm.swuview(),oninput:m.withAttr("value",signmaker.vm.swuview)})
),
m('div.cmdrow',
m("p.fsw","Styling: "),
m("input",{id:"styling",value:signmaker.vm.styling(),oninput:m.withAttr("value",signmaker.vm.styling)})
),
]
break;
}
return [
editor,
m('div',{id:"command"},[
m('div.cmd.edit',{"class": (S['tab'] == '') ? "selected" : "unselected",onclick: () => setS({'tab':''})},tt("editTab")),
m('div.cmd',{"class": (S['tab'] =='more') ? "selected" : "unselected",onclick: () => setS({'tab':'more'})},tt("moreTab")),
currentTab
])
]
};
// PALETTE
//////////
var palette = {}; //app namespace
//model
palette.structure = function(){
return window.alphabet;
};
palette.vm = {};
palette.vm.init = function(){
this.source = palette.structure();
this.action = false;
}
palette.vm.select = function(group,base,lower){
var key;
this.group = group || '';
this.base = base || '';
this.lower = !!lower;
if (this.base && !this.lower){
var key1 = this.base.slice(0,4) + "08";
var key2 = this.base.slice(0,4) + "18";
this.mirror = (ssw.size(key1) || ssw.size(key2))
this.grid=[[],[],[],[],[],[],[],[]];
for (var f=0;f<6;f++){
for (var r=0;r<8;r++){
key=this.base.slice(0,4) + f + r;
this.grid[r].push(key);
}
}
} else if (this.base && this.lower){
this.mirror = true;
this.grid=[[],[],[],[],[],[],[],[]];
for (var f=0;f<6;f++){
for (var r=8;r<16;r++){
key=this.base.slice(0,4) + f + r.toString(16);
this.grid[(r-8)].push(key);
}
}
} else if (this.group){
this.mirror = false;
this.grid=[[],[],[],[],[],[],[],[],[],[]];
var cnt=0;
for (var i=0; i<this.source[this.group].length;i++){
key = this.source[this.group][i];
this.grid[(cnt++%10)].push(key);
}
for (var i=cnt; i<60;i++){
this.grid[(i%10)].push('');
}
} else {
this.mirror=false;
this.grid=[[],[],[],[],[],[],[],[],[],[]];
var cnt=0;
for (key in this.source){
if (palette.vm.dialing){
var start = window.alphabet[key][0];
var end = window.alphabet[key].slice(-1)[0]
if (!ssw.results(query+"R" + start.slice(1,4) + 't' + end.slice(1,4),text).length) {
key='';
}
}
this.grid[(cnt++%10)].push(key);
}
for (var i=cnt; i<60;i++){
this.grid[(i%10)].push('');
}
}
}
palette.controller = function(){
palette.vm.init();
palette.vm.select();
}
palette.click = function(key){
if (palette.vm.base){
return;
} else if (palette.vm.group){
palette.vm.select(palette.vm.group,key);
} else {
palette.vm.select(key);
}
};
palette.undo = function(){
return {
"class": palette.vm.dialhist.length || palette.vm.group?"clickable":"disabled",
onclick: function(){
if (palette.vm.base){
palette.vm.select(palette.vm.group);
} else if (palette.vm.group){
palette.vm.select();
}
}
}
}
palette.top = function(){
return {
onclick: function(){
palette.vm.select();
}
};
};
palette.previous = function(){
return {
onclick: function(){
if (palette.vm.base){
palette.vm.select(palette.vm.group);
} else {
palette.vm.select();
}
}
};
};
palette.mirror = function(){
return {
"class": palette.vm.dialing==3?"smaller":'',
onclick: function(){
palette.vm.select(palette.vm.group,palette.vm.base,!palette.vm.lower);
}
};
};
//view
// gets the offset of an element relative to the document
function getOffset( el ) {
var offset = el?el.getBoundingClientRect():{top:0,left:0};
return { top : offset.top + (window.pageYOffset || window.document.documentElement.scrollTop), left : offset.left + (window.pageXOffset || window.document.documentElement.scrollLeft) }
}
function overlap(el1, el2){
if (!el2) return false;
var offset1 = getOffset( el1 ), width1 = el1.offsetWidth, height1 = el1.offsetHeight,
offset2 = getOffset( el2 ), width2 = el2.offsetWidth, height2 = el2.offsetHeight;
if (!(offset2.left > offset1.left + width1 - width1/2 || offset2.left + width2 < offset1.left + width1/2 || offset2.top > offset1.top + height1 - height1/2 || offset2.top + height2 < offset1.top + height1/2 )){
return true;
} else {
return false;
}
}
function palDragEnd( draggie,e,p ) {
var sb = document.getElementById("signbox");
if (overlap(draggie.element,sb)){
var offset1 = getOffset( draggie.element ),
offset2 = getOffset( sb );
var symbol = {key:draggie.element.key,x: parseInt(500-signmaker.vm.midWidth+1+offset1.left-offset2.left),y: parseInt(500-signmaker.vm.midHeight+offset1.top-offset2.top)};
signmaker.vm.add(symbol);
} else {
var seq = document.getElementById("sequence");
if (overlap(draggie.element,seq)){
var position = parseInt((draggie.startPoint.y+draggie.dragPoint.y) / (window.innerHeight/20));
var key = draggie.element.key;
signmaker.vm.addSeq(key,position);
}
}
draggie.element.style.top=0;
draggie.element.style.left=0;
draggie.element.topleft=false;
classie.remove(draggie.element,"topleft");
var drag = draggie.dragPoint;
if ( drag.x === 0 && drag.y === 0 ) {
palette.click(draggie.element.key);
m.redraw();
}
}
function palDragMove( draggie ){
if (!draggie.element.topleft){
draggie.element.topleft=true;
classie.add(draggie.element,"topleft");
}
}
palette.view = function(ctrl){
var tooltip = palette.vm.base?'':palette.vm.group?'base_':'group_';
return [
palette.vm.action?[
m('div.btn.clickable.save',{onclick: signmaker.vm.save},tt("save")),
navigator.share?m('div.btn.clickable.share',{onclick: signmaker.vm.share},tt("share")):'',
m('div.btn.clickable.demo',{onclick: signmaker.vm.demo},tt("demo")),
m('div.btn.clickable.cancel',{onclick: signmaker.vm.cancel},tt("cancel")),
]:[
m('div.btn.clickable.save',{onclick: signmaker.vm.save},tt("save")),
palette.vm.mirror?'':m("div.btn.clickable",palette.top(),tt("top")),
m("div.btn.clickable",palette.previous(),tt("previous")),
palette.vm.mirror?m("div.btn",palette.mirror(),tt("mirror")):'',
m('div.btn.clickable.save',{onclick: () => palette.vm.action = !palette.vm.action},tt("...")),
],
palette.vm.grid.map(function(row){
return m("div.row",{"class":palette.vm.dialing?"smaller":''},row.map(function(key){
return m("div"
, {
title: tooltip?t(tooltip + key.slice(0,4)):'',
config: function(element, isInitialized) {
element.key=key;
if (!isInitialized) {
var draggie = new Draggabilly(element);
draggie.on( 'dragMove', palDragMove );
draggie.on( 'dragEnd', palDragEnd );
}
}
},m.trust(ssw.svg(key)));
}));
})
];
};
addEventListener("keydown", function(event){
if (event.target==document.body){
var code = event.charCode || event.keyCode;
for (var i=0; i<keyboard['prevent'].length; i++){
if (code === keyboard['prevent'][i]){
event.preventDefault();
}
}
return false;
}
});
function initApp(){
m.mount(document.getElementById("palette"), palette);
m.mount(document.getElementById("signmaker"), signmaker);
}
var cssCheck;
window.onload = function () {
if (S['swu']) {
signmaker.vm.swu(S['swu'])
} else if (S['fsw']) {
signmaker.vm.fsw(S['fsw'])
}
var cnt = 0;
if (!!ssw.size("S10000")){
initApp();
} else {
classie.addClass(document.body,"waiting");
var page = document.body.innerHTML;
cssCheck = setInterval(function(){
if (ssw.size("S10000")){
classie.removeClass(document.body,"waiting");
document.body.innerHTML = page;
clearInterval(cssCheck);
initApp();
//secondary call for Android default browser
//setTimeout(function(){ initApp(); }, 100);
} else {
document.getElementById('dots').innerHTML=Array(1+parseInt(((cnt++)%40)/10)).join('.');
}
},100);
document.body.innerHTML = '<h2>' + t('loadFont') + ' <span id="dots"></span>' + '</h2>';
}
}
// https://keycode.info
checkKeyboard = function (event,name){
if (event.target==document.body){
var code = event.charCode || event.keyCode;
var checks = keyboard[name];
var checking;
var act;
if (!(checks[0] instanceof Array)){
checks = [checks];
}
for (var i=0; i < checks.length; i++) {
checking = checks[i]
if (checking[0] == code){
act = true;
checking = checking.slice(1);
for (check in checking){
if (!event[checking[check]]){
act = false;
break;
}
}
if (act) return true;
}
}
return false;
}
}
addEventListener("keyup", function(event) {
var x = event.charCode || event.keyCode;
if (checkKeyboard(event,"left10")){ signmaker.vm.move(-10,0);} else
if (checkKeyboard(event,"up10")){ signmaker.vm.move(0,-10);} else
if (checkKeyboard(event,"right10")){ signmaker.vm.move(10,0);} else
if (checkKeyboard(event,"down10")){ signmaker.vm.move(0,10);} else
if (checkKeyboard(event,"left")){ signmaker.vm.move(-1,0);} else
if (checkKeyboard(event,"up")){ signmaker.vm.move(0,-1);} else
if (checkKeyboard(event,"right")){ signmaker.vm.move(1,0);} else
if (checkKeyboard(event,"down")){ signmaker.vm.move(0,1);} else
if (checkKeyboard(event,"selectBack")){ signmaker.vm.select(-1);} else
if (checkKeyboard(event,"selectNext")){ signmaker.vm.select(1);} else
if (checkKeyboard(event,"escape")){ if (S['tab'] == 'more') {setS({'tab':''});} else {setS({'tab':'more'})} }else
if (checkKeyboard(event,"delete")){ signmaker.vm.delete();} else
if (checkKeyboard(event,"redo")){ signmaker.vm.redo();} else
if (checkKeyboard(event,"undo")){ signmaker.vm.undo();} else
if (checkKeyboard(event,"rotateBack")){ signmaker.vm.rotate(-1);} else
if (checkKeyboard(event,"rotateNext")){ signmaker.vm.rotate(1);} else
if (checkKeyboard(event,"variationBack")){ signmaker.vm.variation(-1);} else
if (checkKeyboard(event,"variationNext")){ signmaker.vm.variation(1);} else
if (checkKeyboard(event,"mirror")){ signmaker.vm.mirror();} else
if (checkKeyboard(event,"fillBack")){ signmaker.vm.fill(-1);} else
if (checkKeyboard(event,"fillNext")){ signmaker.vm.fill(1);} else
if (checkKeyboard(event,"recenter")){ signmaker.vm.center();}
if (event.preventDefault) event.preventDefault();
return false;
});