function b64encode(str) { return btoa(unescape(encodeURIComponent(str))); } function submitNewLetter(form) { var name = document.getElementById('filename_display').value; if (!/^[A-Za-z0-9_-]+$/.test(name)) { alert('File name may only contain letters, numbers, underscores and hyphens.'); return false; } form.filename.value = name; return true; } var mainpage; var control; var result; var mousedownx; var mousedowny; var dragHint = "move"; var data; var showGrid = false; var snapToGrid = false; var gridSize = 10; var selected; var firstSelected; var itemparameters; var grid; var context; var draggingHTML; var window_dragging = false; const undo = []; var undoIndex = 0; var lastRedo; var mode = 'MOUSEUP'; var textobj; var lastdragover; var pendingDragover; var dropIndicator; var sequence = 0; function showDropIndicator(target) { if(!dropIndicator) { dropIndicator = document.createElement('div'); dropIndicator.style.position = 'fixed'; dropIndicator.style.height = '4px'; dropIndicator.style.background = '#0088ff'; dropIndicator.style.zIndex = '99999'; dropIndicator.style.pointerEvents = 'none'; document.body.appendChild(dropIndicator); } let rect = target.getBoundingClientRect(); dropIndicator.style.left = rect.left + 'px'; dropIndicator.style.width = rect.width + 'px'; dropIndicator.style.top = (rect.top - 2) + 'px'; dropIndicator.style.display = 'block'; } function hideDropIndicator() { if(dropIndicator) { dropIndicator.style.display = 'none'; } } function saveUndo() { undo[undoIndex++] = mainpage.innerHTML; } function do_undo() { if(undoIndex > 0) { mainpage.innerHTML = undo[--undoIndex]; } return true; } function do_redo() { return true; } function init() { mainpage = document.getElementById("mainpage"); data = document.getElementById("data"); itemparameters = document.getElementById("itemparameters"); var gridsize = document.getElementById("gridsize"); gridsize.value = gridSize; grid = document.getElementById("grid"); context = grid.getContext("2d"); drawGrid(); buildToolbar(); document.designMode = 'off'; } function getLayerMap(element) { var map = ''; if(element.id != 'mainpage') { var curelem = element; while(curelem.id != 'mainpage') { map = '<' + curelem.nodeName + '>' + map; curelem = curelem.parentNode; } } document.getElementById('map').innerHTML = map; } function jetEscape(text) { return text.replace(/&/g, '&').replace(//g, '>'); } function buildToolbar() { let tbitems = [ { "label": "<div>", "html": "
" }, { "label": "<input>", "html": "" }, { "label": "<button>", "html": "" }, { "label": "<password>", "html": "" }, { "label": "<checkbox>", "html": "" }, { "label": "<label>", "html": "" }, { "label": "<p>", "html": "Type Here
" }, { "label": "<hr>", "html": "" + jetEscape("$" + "[varname]") + ""
},
{
"label": "Jet: <set>",
"html": "" + jetEscape("") + " "
},
{
"label": "Jet: <if>",
"html": "" + jetEscape("\ncontent\n ") + ""
}
];
tbitems.forEach(doit);
function doit(currentValue, index) {
let index2 = index + 1;
let toolbar = document.getElementById('toolbar');
var itemHTML = '';
toolbar.insertAdjacentHTML("beforeend", itemHTML);
let id = 'button' + index2;
let button = document.getElementById(id);
button.html = currentValue.html;
button.addEventListener("mousedown",
(e) => {
e.preventDefault();
saveUndo();
draggingHTML = currentValue.html;
mainpage.insertAdjacentHTML('beforeend', draggingHTML);
let newEl = mainpage.lastElementChild;
newEl.style.position = 'absolute';
newEl.style.zIndex = '10000';
newEl.style.left = '0px';
newEl.style.top = '0px';
startNewItemDrag(newEl);
}
, false);
}
}
function startNewItemDrag(el) {
let rect = mainpage.getBoundingClientRect();
function ndMove(e) {
el.style.left = (e.clientX - rect.left - el.offsetWidth / 2) + 'px';
el.style.top = (e.clientY - rect.top - el.offsetHeight / 2) + 'px';
}
function ndUp(e) {
document.removeEventListener('mousemove', ndMove);
document.removeEventListener('mouseup', ndUp);
draggingHTML = null;
if((typeof selected !== 'undefined') && selected) {
selected.style.outline = '';
}
selected = el;
selected.style.outline = '2px solid #0088ff';
getLayerMap(selected);
displayParameters();
mode = "MOUSEUP";
}
document.addEventListener('mousemove', ndMove);
document.addEventListener('mouseup', ndUp);
}
function window_mousedown(win, e) {
mousedownx = e.offsetX;
mousedowny = e.offsetY;
if(e.offsetX >= (win.clientWidth - 3)) {
win.style.cursor = 'ew-resize';
window_dragging = true;
}
else {
win.style.cursor = 'default';
window_dragging = false;
}
}
function window_mousemove(win, e) {
}
function window_mouseup(win, e) {
}
function drawGrid() {
if(showGrid == true) {
context.clearRect(0,0,grid.width,grid.height);
context.lineWidth = 0.5;
context.strokeStyle = "#808080";
for(var ix = 0; ix < grid.width; ix += gridSize) {
context.beginPath();
context.moveTo(ix, 0);
context.lineTo(ix, grid.height);
context.stroke();
context.beginPath();
context.moveTo(0, ix);
context.lineTo(grid.width, ix);
context.stroke();
}
} else {
context.clearRect(0,0,grid.width,grid.height);
}
}
function resetDragHint(e) {
if(!selected) {
return;
}
if(selected.style.position == 'absolute') {
if((e.offsetX >= (parseFloat(selected.style.width) - 10)) && (e.offsetY >= (parseFloat(selected.style.height) - 10))) {
selected.style.cursor = "nwse-resize";
dragHint = "rightbottomresize";
} else if((e.offsetY < 10) && (e.offsetX >= (parseFloat(selected.style.width) - 10))) {
selected.style.cursor = "nesw-resize";
dragHint = "righttopresize";
} else if((e.offsetX <= 10) && (e.offsetY >= (parseFloat(selected.style.height) - 10))) {
selected.style.cursor = "nesw-resize";
dragHint = "leftbottomresize";
} else if((e.offsetX <= 10) && (e.offsetY <= 10)) {
selected.style.cursor = "nwse-resize";
dragHint = "lefttopresize";
} else if(e.offsetX >= (parseFloat(selected.style.width) - 10)) {
selected.style.cursor = "ew-resize";
dragHint = "rightresize";
} else if(e.offsetY >= (parseFloat(selected.style.height) - 10)) {
selected.style.cursor = "ns-resize";
dragHint = "bottomresize";
} else if(e.offsetX <= 10) {
selected.style.cursor = "ew-resize";
dragHint = "leftresize";
} else if(e.offsetY <= 10) {
selected.style.cursor = "ns-resize";
dragHint = "topresize";
} else {
selected.style.cursor = "move";
dragHint = "move";
}
} else {
if((e.offsetX >= (parseFloat(selected.style.width) - 10)) && (e.offsetY >= (parseFloat(selected.style.height) - 10))) {
selected.style.cursor = "nwse-resize";
dragHint = "rightbottomresize";
} else if(e.offsetX >= (parseFloat(selected.style.width) - 10)) {
selected.style.cursor = "ew-resize";
dragHint = "rightresize";
} else if(e.offsetY >= (parseFloat(selected.style.height) - 10)) {
selected.style.cursor = "ns-resize";
dragHint = "bottomresize";
} else {
selected.style.cursor = "move";
dragHint = "move";
}
}
}
function mousedown(e) {
let mouseabove = document.elementFromPoint(e.clientX, e.clientY);
if((typeof selected === 'undefined') || (selected != mouseabove)) {
mode = 'NEWSELECTION';
if((typeof selected !== 'undefined') && (selected.nodeName == "DIV")) {
document.designMode = 'off';
selected.contentEditable = false;
selected.blur();
selected.style.userSelect = 'none';
}
if((typeof selected !== 'undefined') && selected) {
selected.style.outline = '';
}
selected = mouseabove;
selected.style.outline = '2px solid #0088ff';
getLayerMap(selected);
} else {
if(mode != "TEXT") {
mode = "DOWNONSELECTED";
}
}
if(mode != 'TEXT') {
resetDragHint(e);
}
mousedownx = e.clientX;
mousedowny = e.clientY;
displayParameters();
return true;
}
function mouseup(e) {
if(mode == "TEXT") {
return true;
}
if(mode == "DOWNONSELECTED") {
if((selected.nodeName == "DIV") || (selected.nodeName == "CODE")) {
document.designMode = 'on';
selected.style.userSelect = 'auto';
selected.contentEditable = true;
selected.style.cursor = 'text';
selected.focus();
mode = "TEXT";
return true;
}
}
if(draggingHTML) {
draggingHTML = null;
}
if(selected && (mode == 'MOVED') && (selected.style.position == 'absolute')) {
selected.style.pointerEvents = 'none';
let dragover = document.elementFromPoint(e.clientX, e.clientY);
selected.style.pointerEvents = 'auto';
if(dragover.nodeName == 'DIV') {
if(dragover.id != selected.parentElement.id) {
dragover.appendChild(selected);
selected.style.left = ((selected.getBoundingClientRect().x + e.offsetX - mousedownx) - dragover.getBoundingClientRect().x) + 'px';
selected.style.top = ((selected.getBoundingClientRect().y + e.offsetY - mousedowny) - dragover.getBoundingClientRect().y) + 'px';
}
}
} else if(selected && (mode == 'MOVED') && pendingDragover) {
pendingDragover.prepend(selected);
selected.style.left = parseFloat(pendingDragover.style.left) + "px";
selected.style.top = parseFloat(pendingDragover.style.top) + "px";
}
pendingDragover = null;
hideDropIndicator();
mode = "MOUSEUP";
return true;
}
function mousemove(e) {
if(mode == "MOUSEUP") {
resetDragHint(e);
} else {
if(mode == "TEXT") {
return true;
}
if((selected.style.position == 'static') ||
(typeof selected.style.position === 'undefined') ||
(selected.style.position == '')) {
if(dragHint == "move") {
if(mode != "MOVED") {
mode = "MOVED";
}
selected.style.pointerEvents = 'none';
let dragover = document.elementFromPoint(e.clientX, e.clientY);
selected.style.pointerEvents = 'auto';
if(dragover.nodeName == 'DIV') {
pendingDragover = dragover;
showDropIndicator(dragover);
}
return true;
} else if(dragHint == "rightbottomresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.width = (parseFloat(selected.style.width) + e.movementX) + "px";
selected.style.height = (parseFloat(selected.style.height) + e.movementY) + "px";
} else if(dragHint == "rightresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.width = (parseFloat(selected.style.width) + e.movementX) + "px";
} else if(dragHint == "bottomresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.height = (parseFloat(selected.style.height) + e.movementY) + "px";
}
} else if(selected.style.position == 'absolute') {
if(dragHint == "move") {
if(mode != "MOVED") {
saveUndo();
mode = "MOVED";
}
selected.style.left = (parseFloat(selected.style.left) + e.movementX) + "px";
selected.style.top = (parseFloat(selected.style.top) + e.movementY) + "px";
} else if(dragHint == "rightbottomresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.width = (parseFloat(selected.style.width) + e.movementX) + "px";
selected.style.height = (parseFloat(selected.style.height) + e.movementY) + "px";
} else if(dragHint == "lefttopresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.left = (parseFloat(selected.style.left) + e.movementX) + "px";
selected.style.top = (parseFloat(selected.style.top) + e.movementY) + "px";
selected.style.width = (parseFloat(selected.style.width) - e.movementX) + "px";
selected.style.height = (parseFloat(selected.style.height) - e.movementY) + "px";
} else if(dragHint == "leftbottomresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.left = (parseFloat(selected.style.left) + e.movementX) + "px";
selected.style.width = (parseFloat(selected.style.width) - e.movementX) + "px";
selected.style.height = (parseFloat(selected.style.height) + e.movementY) + "px";
} else if(dragHint == "righttopresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.top = (parseFloat(selected.style.top) + e.movementY) + "px";
selected.style.height = (parseFloat(selected.style.height) - e.movementY) + "px";
selected.style.width = (parseFloat(selected.style.width) + e.movementX) + "px";
} else if(dragHint == "rightresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.width = (parseFloat(selected.style.width) + e.movementX) + "px";
} else if(dragHint == "bottomresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.height = (parseFloat(selected.style.height) + e.movementY) + "px";
} else if(dragHint == "leftresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.left = (parseFloat(selected.style.left) + e.movementX) + "px";
selected.style.width = (parseFloat(selected.style.width) - e.movementX) + "px";
} else if(dragHint == "topresize") {
if(mode != "RESIZED") {
saveUndo();
mode = "RESIZED";
}
selected.style.top = (parseFloat(selected.style.top) + e.movementY) + "px";
selected.style.height = (parseFloat(selected.style.height) - e.movementY) + "px";
}
displayParameters();
}
return true;
}
}
function heading(name) {
let properties = document.getElementById('properties');
properties.insertAdjacentHTML('beforeend', "