Category Archives: Uncategorized

3d SVG Text Generator

This app generates 3d SVG text in various colors and with various fonts. Here is an example of how it appears:

This is the code:

<!DOCTYPE HTML >
<html>
<head><style>
body{}
input {position: relative}
</style></head>
<body>
<input type=”text” id=”t1″ style=”” placeholder=”text” /> <select id=”s2″><option>font</option><option>Georgia</option><option>Arial</option><option>Arial Black</option><option>Times New Roman</option><option>Courier New</option><option>Georgia</option><option>Verdana</option><option>Comic Sans MS</option></select> <select id=”s1″ onchange=’drw();’><option>color</option><option>red</option><option>green</option><option>blue</option><option>gold</option><option>orange</option><option>magenta</option><option>cyan</option><option>silver</option><option>brown</option><option>purple</option></select> <input type=”button” value = “Save” onclick=’sve();’ /> <input type=”checkbox” id=”ch1″ value=”” />small change
<svg id=”svg1″ style=”position:absolute;left:10px;top:50px;width:1500px;height:200px;background: #ffffaa”></svg>
<script>
var lft = 20; var tp = 70; var r = 55; var col = []; var oldURL = “3Dtext.svg”; var wd = 1500; var ht = 200; var s1 = document.getElementById(“s1”); var s2 = document.getElementById(“s2”);

document.onkeydown = rsize;

function rsize(e) {


if (e.key == “ArrowLeft”) {
if(document.getElementById(“ch1”).checked) {
wd -= 1;
} else {
wd -= 70;
}
document.getElementById(“svg1”).style.width= wd + “px”;
}

if (e.key == “ArrowRight”) {
if(document.getElementById(“ch1”).checked) {
wd += 1;
} else {
wd += 70;
}
document.getElementById(“svg1”).style.width= wd + “px”;
}

if (e.key == “ArrowUp”) {
ht –;
document.getElementById(“svg1”).style.height= ht + “px”;
}

if (e.key == “ArrowDown”) {
ht ++;
document.getElementById(“svg1”).style.height= ht + “px”;
}
}

function drw() {
document.getElementById(“svg1″).innerHTML = ”;
lft = 0;
tp = 70;
if(s2.value == “Comic Sans MS” || s2.value == “Verdana”) tp += 5;
if (s1.value == “red”) col = [“#553333″,”#773333″,”#993333″,”#bb4444″,”#dd4444″,”#ff4444”];
if (s1.value == “green”) col = [“#335533″,”#337733″,”#339933″,”#33aa33″,”#33bb33″,”#33cc33”];
if (s1.value == “blue”) col = [“#333355″,”#333377″,”#333399″,”#4444bb”,”#5555dd”,”#5555ff”];
if (s1.value == “gold”) col = [“#555500″,”#777700″,”#999900″,”#aaaa00″,”#bbbb00″,”#cccc00”];
if (s1.value == “orange”) col = [“#553300″,”#774400″,”#995500″,”#aa6600″,”#bb7700″,”#cc8800”];
if (s1.value == “magenta”) col = [“#550055″,”#770077″,”#990099″,”#aa00aa”,”#bb00bb”,”#cc00cc”];
if (s1.value == “cyan”) col = [“#005555″,”#007777″,”#009999″,”#00aaaa”,”#00bbbb”,”#00cccc”];
if (s1.value == “silver”) col = [“#555555″,”#777777″,”#999999″,”#bbbbbb”,”#dddddd”,”#eeeeee”];
if (s1.value == “brown”) col = [“#553311″,”#774422″,”#885533″,”#996644″,”#aa7755″,”#bb8866”];
if (s1.value == “purple”) col = [“#550044″,”#770066″,”#990088″,”#aa0099″,”#bb00aa”,”#cc00bb”];
s1.value = “color”;
for (var i = 0; i <= 5; i ++) {
lft += 2;
tp += 2;
document.getElementById(“svg1″).innerHTML += ‘<text x=”‘ + lft + ‘” y=”‘+ tp + ‘” fill=”‘ + col[i] + ‘” font-size=”100″ font-family=”‘ + document.getElementById(“s2″).value + ‘” font-style=”italic” >’ + document.getElementById(“t1”).value + ‘</text>’;
}
}

function sve() {
document.getElementById(“svg1”).style.backgroundColor = “white”;
var textToSave = ‘<?xml version=”1.0″ encoding=”UTF-8″ standalone=”no”?> <svg xmlns:svg=”http://www.w3.org/2000/svg&#8221; xmlns=”http://www.w3.org/2000/svg&#8221; width=”‘ + wd + ‘” height=”‘ + ht + ‘” id=”svg1″ >’ + document.getElementById(“svg1”).innerHTML + ‘</svg>’;
//alert(textToSave);
var textToSaveAsBlob = new Blob([textToSave], {type:”text/plain”});
var textToSaveAsURL = window.URL.createObjectURL(textToSaveAsBlob);
fileNameToSaveAs = prompt(“FileName to save as”,oldURL);
oldURL = fileNameToSaveAs;
var downloadLink = document.createElement(“a”);
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = “Download File”;
downloadLink.href = textToSaveAsURL;
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = “none”;
document.body.appendChild(downloadLink);
downloadLink.click();
}

function destroyClickedElement(event) {
document.body.removeChild(event.target);
}
</script>
</body></html>


The main function is named drw(). it sets up a series of svg text elements at incremented locations to give a gradient effect:
for (var i = 0; i <= 5; i ++) {
lft += 2;
tp += 2;
document.getElementById(“svg1″).innerHTML += ” + document.getElementById(“t1″).value + ”;
}

The chosen color is derived from a series of arrays:
if (s1.value == “purple”) col = [“#550044″,”#770066″,”#990088″,”#aa0099″,”#bb00aa”,”#cc00bb”];

The svg element was created larger than the string that would be embedded and then resized to fir te text. The reason for the slight color is to see it as igt resizes. The saved file has no color.

This is the resizing code:
function rsize(e) {

if (e.key == “ArrowLeft”) {
if(document.getElementById(“ch1”).checked) {
wd -= 1;
} else {
wd -= 70;
}
document.getElementById(“svg1”).style.width= wd + “px”;
}

if (e.key == “ArrowRight”) {
if(document.getElementById(“ch1”).checked) {
wd += 1;
} else {
wd += 70;
}
document.getElementById(“svg1”).style.width= wd + “px”;
}

if (e.key == “ArrowUp”) {
ht –;
document.getElementById(“svg1”).style.height= ht + “px”;
}

if (e.key == “ArrowDown”) {
ht ++;
document.getElementById(“svg1”).style.height= ht + “px”;
}
}

The code for the saved svg file has the following appearence:

The code for the saved svg file has the following appearence:

 

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”no”?> <svg xmlns:svg=”http://www.w3.org/2000/svg&#8221; xmlns=”http://www.w3.org/2000/svg&#8221; width=”147″ height=”200″ id=”svg1″ ><text x=”2″ y=”72″ fill=”#553333″ font-size=”100″ font-family=”Georgia” font-style=”italic”>res</text><text x=”4″ y=”74″ fill=”#773333″ font-size=”100″ font-family=”Georgia” font-style=”italic”>res</text><text x=”6″ y=”76″ fill=”#993333″ font-size=”100″ font-family=”Georgia” font-style=”italic”>res</text><text x=”8″ y=”78″ fill=”#bb3333″ font-size=”100″ font-family=”Georgia” font-style=”italic”>res</text><text x=”10″ y=”80″ fill=”#dd3333″ font-size=”100″ font-family=”Georgia” font-style=”italic”>res</text></svg>










The main function is named drw(). it sets up a series of svg text elements at incremented locations to give a gradient effect:
for (var i = 0; i <= 5; i ++) {
lft += 2;
tp += 2;
document.getElementById(“svg1″).innerHTML += ” + document.getElementById(“t1″).value + ”;
}

The chosen color is derived from a series of arrays:
if (s1.value == “purple”) col = [“#550044″,”#770066″,”#990088″,”#aa0099″,”#bb00aa”,”#cc00bb”];

The svg element was created larger than the string that would be embedded and then resized to fir te text. The reason for the slight color is to see it as igt resizes. The saved file has no color.

This is the resizing code:
function rsize(e) {

if (e.key == “ArrowLeft”) {
if(document.getElementById(“ch1”).checked) {
wd -= 1;
} else {
wd -= 70;
}
document.getElementById(“svg1”).style.width= wd + “px”;
}

if (e.key == “ArrowRight”) {
if(document.getElementById(“ch1”).checked) {
wd += 1;
} else {
wd += 70;
}
document.getElementById(“svg1”).style.width= wd + “px”;
}

if (e.key == “ArrowUp”) {
ht –;
document.getElementById(“svg1”).style.height= ht + “px”;
}

if (e.key == “ArrowDown”) {
ht ++;
document.getElementById(“svg1”).style.height= ht + “px”;
}
}

The code for the saved svg file has the following appearence:

resresresresres

Create points for Povray Surface of Revolution by tracing

This app takes a series of coordinates and converts them to the input for Povray’s splines and surfaces of revolution (, etc.

I generated the points by tracing an image of a head in another app I had written.

This is the output of that app which I copied and pasted into a text element of the current app:
342,656, 587,649, 529,615, 489,555, 491,494, 516,461, 540,416, 553,381, 558,337, 557,289, 540,242, 532,205, 519,170, 505,144, 490,117, 476,97, 461,90, 439,78, 392,55, 339,49

This is the conversion:
<0.1, 0.0>, <6.2, 0.2>, <4.8, 1.0>, <3.8, 2.5>, <3.8, 4.0>, <4.4, 4.9>, <5.0, 6.0>, <5.3, 6.9>, <5.5, 8.0>, <5.5, 9.2>, <5.0, 10.3>, <4.8, 11.3>, <4.5, 12.2>, <4.2, 12.8>, <3.8, 13.5>, <3.4, 14.0>, <3.0, 14.2>, <2.5, 14.4>, <1.3, 15.0>, <0.0, 15.2>

This is the pov file:
#include “colors.inc”
camera {
location <10, 7.5, -20>
look_at <0, 7.5, 0>
}
background { color rgb<0.2, 0.4, 0.8> }
light_source { <100, 100, -100> color rgb .8 }
sor {
20,
<0.1, 0.0>, <6.2, 0.2>, <4.8, 1.0>, <3.8, 2.5>, <3.8, 4.0>, <4.4, 4.9>, <5.0, 6.0>, <5.3, 6.9>, <5.5, 8.0>, <5.5, 9.2>, <5.0, 10.3>, <4.8, 11.3>, <4.5, 12.2>, <4.2, 12.8>, <3.8, 13.5>, <3.4, 14.0>, <3.0, 14.2>, <2.5, 14.4>, <1.3, 15.0>, <0.0, 15.2>
pigment {color rgb<0.6, 0.5, 0.2> }
}

This is how it appears:

<!DOCTYPE HTML >
<html>
<head>
<title>PRConvert</title>
<style>
body {margin-left:0;margin-right:0;font:normal normal normal 15px Arial;}
a{ text-decoration: }:link { color: rgb(0, 0, 255) }:visited {color :rgb(100, 0,100) }:hover { }:active { }

</style>
</head>
<body>
<input type="text" id="t1" style= "width: 80%" value = "329,49,402,61,469,98,505,146,525,191,543,262,554,329,536,410,481,530,578,652" />
 <input type="text" id="t2" style = "width: 100px" value = "" placeholder = "divide by" />
 <input type ="button" id="b1" value="convert" onclick='cnvrt() ;' />
<script>
var arrx = []; var arry = []; var cntx = -1; var cnty = -1; var arr = []; var xminxmin; var ymax;
document.getElementById("t1").value =  document.getElementById("t1").value.replace(new RegExp('new jsPoint', 'g'),'');

function cnvrt() {
  arr = document.getElementById("t1").value.split(",");
  document.getElementById("t1").value = "";
  xmin = parseInt(arr[0]);
  ymax = parseInt(arr[1]);
  for (var i = 0; i <= arr.length -1; i += 2) {
    arr[i] = parseInt(arr[i]);
    cntx ++;
    arrx[cntx] = arr[i];
    if (i % 2 == 0 && arr[i] < xmin) xmin = arr[i];
  }
  
    for (var i = 1; i <= arr.length -1; i += 2) {
      arr[i] = parseInt(arr[i]);
    cnty ++;
    arry[cnty] = arr[i];
    if (i % 2 == 1  && arr[i] > ymax) ymax = arr[i];
  }
  
  
  for (var i = 0; i <= arrx.length -1; i ++) {
   arrx[i] -= xmin;
   arrx[i] /= parseInt(document.getElementById("t2").value);
   arrx[i] = arrx[i].toFixed(1);
  }
  for (var i = arrx.length -1; i >= 0; i --) {
   arry[i] -= ymax;
   arry[i] /= parseInt(document.getElementById("t2").value);
   arry[i] = - arry[i];
   arry[i] = arry[i].toFixed(1);
  }
   for (var i = 0; i <= arrx.length -1; i ++) {
   document.getElementById("t1").value += "<" + arrx[i] + ", " + arry[i] + ">, ";
  }
  document.getElementById("t1").value = document.getElementById("t1").value.substr(0,document.getElementById("t1").value.length - 2);
}
</script>
</body></html>
I converted the string to an array and obtained the minimum x and maximum y values:
 arr = document.getElementById("t1").value.split(",");
  document.getElementById("t1").value = "";
  xmin = parseInt(arr[0]);
  ymax = parseInt(arr[1]);
  for (var i = 0; i <= arr.length -1; i += 2) {
    arr[i] = parseInt(arr[i]);
    cntx ++;
    arrx[cntx] = arr[i];
    if (i % 2 == 0 && arr[i] < xmin) xmin = arr[i];
  }
  
    for (var i = 1; i <= arr.length -1; i += 2) {
      arr[i] = parseInt(arr[i]);
    cnty ++;
    arry[cnty] = arr[i];
    if (i % 2 == 1  && arr[i] > ymax) ymax = arr[i];
  }
  
  I subtracted the minimum x value from each point and divided to get a scale consistent to the of Povray:
  for (var i = 0; i <= arrx.length -1; i ++) {
   arrx[i] -= xmin;
   arrx[i] /= parseInt(document.getElementById("t2").value);
   arrx[i] = arrx[i].toFixed(1);
  }
  
  I did something similar for the y values, but since html y increases downward and Povray increases upward, I had to reverse the sign:
  for (var i = arrx.length -1; i >= 0; i --) {
   arry[i] -= ymax;
   arry[i] /= parseInt(document.getElementById("t2").value);
   arry[i] = - arry[i];
   arry[i] = arry[i].toFixed(1);
  }
  
  I then created the final string and placed it in the text input to be copied and pasted in the pov code:
   for (var i = 0; i <= arrx.length -1; i ++) {
   document.getElementById("t1").value += "<" + arrx[i] + ", " + arry[i] + ">, ";
  }
  document.getElementById("t1").value = document.getElementById("t1").value.substr(0,document.getElementById("t1").value.length - 2);

AN SVG Sunrise

This extends the coming of dawn with a rising sun.

This is the code:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" id="svg1" >
<rect x = "0" y = "0" width = "100%" height = "100%" >
<animate attributeName = "fill" values = "rgb(0,0,30); rgb(0,0,100); rgb(0,0,100); rgb(70,0,140); rgb(120,40,140); rgb(80,80,200); rgb(100,100,255) ; rgb(100,100,255); rgb(100,100,255)" dur = "30s" repeatCount="indefinite"/>
</rect>
<ellipse cx="50%" cy="103%" rx="5%" ry = "8%" fill="#ffff00" >
<animate attributeName = "cy" values = "117% ; 103%" dur = "30s" repeatCount="indefinite"/>
<animate attributeName = "cx" values = "47% ; 53%" dur = "30s" repeatCount="indefinite"/>
</ellipse>
</svg>
The change is with the sun which has the following code:
<ellipse cx="50%" cy="103%" rx="5%" ry = "8%" fill="#ffff00" >
<animate attributeName = "cy" values = "117% ; 103%" dur = "30s" repeatCount="indefinite"/>
<animate attributeName = "cx" values = "47% ; 53%" dur = "30s" repeatCount="indefinite"/>
</ellipse>

The key is placing the sun initially below the screen, just beginning to show at the end of the animation:
<animate attributeName = "cy" values = "117% ; 103%" dur = "30s" repeatCount="indefinite"/>

A SVG Temporal Gradient – A Simulated Night To Dawn Image

This small file creates a svg temporal gradient, particularly a simulation of the conversion of night to dawn.

This is an example:


This is the code:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" id="svg1" >
<rect x = "0" y = "0" width = "100%" height = "100%" >
  <animate attributeName = "fill" values = "rgb(0,0,40); rgb(0,0,100); rgb(0,0,100); rgb(70,0,140); rgb(120,40,140);  rgb(80,80,200); rgb(100,100,255) ; rgb(100,100,255); rgb(100,100,255)" dur = "30s" repeatCount="indefinite"/>
  </rect>
</svg>

The effect is created with an animation tag, with the fill as the attribute:
<animate attributeName = "fill" values = "rgb(0,0,40); rgb(0,0,100); rgb(0,0,100); rgb(70,0,140); rgb(120,40,14

A WYSIWYG No-code Web page creator

This app is a wysywyg no-code web page creator. It does not do everything and will be appended in the future, but it is still possible to do quite a bit without entering anhy code. Elements can be interactively positioned and sized in real time and text can be interactively formatted in real time. The pages can be saved and reloaded at a later date for further work, which allows the creation of templates. Also to try to conform with different sized screens elements are set in % of the screen width and height. On loading instructions are shown which can be removed by clicking.

Here is an example of what can be done without any code being entered:

This is the code:

<!DOCTYPE HTML>
<html>
<head><style>
a{text-decoration:none; font:italic normal 800 24px Georgia}:link { }:visited { }:hover {}:active { }
#el0, #instr, #ta{position: absolute; width: 100%; height: 100%; left:0; top: 50px;border: 1px solid; font-size: 22px;font-weight:600}
#ta{top: 150%; width: screen.width; background: #e5e5e5;font-size: 18px;font-weight:600}
#instr{position: absolute; height: 150%; background: #dddddd; color:black; font-size: 22px}
</style>
</head>
<body>
<table id="cp" style = "position: absolute; width: 100%; height: 45px; top: 0"><tr>
<td style = "width 10%"><select id = "s1" onchange = 'appnd();'><option>choose</option><option>image</option><option>text</option><option>link</option><option>paragraph</option><option>division</option><option>add text</option><option>replace</option><option>open</option><option>overflow</option><option>padding</option><option>textcolor</option><option>bkcolor</option></select></td>
<td style = "width 10%;"><select id = "s2" onchange = 'getFont()'><option>text</option><option>normal</option><option>italic</option><option>Arial</option><option>Times New Roman</option><option>Courier New</option><option>Verdana</option><option>Comic Sans MS</option><option>Arial Black</option><option>Georgia</option><option>underline</option><option>textcolor</option><option>fontweight</option><option>fontsize</option><option>shadow-left</option><option>shadow-top</option><option>shadow-width</option><option>shadow-color</option></select></td>
<td style = "width 10%"><select id = "s3" onchange = 'setBorder();'><option>border</option><option>border-width</option><option>color</option><option>solid</option><option>ridge</option><option>groove</option><option>outset</option><option>radius</option><option>inset</option><option>tpadding</option><option>lpadding</option><option>shadow-left</option><option>shadow-top</option><option>shadow-width</option><option>shadow-color</option></select></td>
<td><select id = "s4"><option>choose folder</option><option>../My Pictures/A-E/</option><option>../My Pictures/F-J/</option><option>../My Pictures/K-O/</option><option>../My Pictures/P-R/</option><option>../My Pictures/S-T/</option><option>../My Pictures/Animated GIF/</option><option></option><option>../My Pictures/Nails/</option></select></td>
<td><input type="button" id = "b1" value = "<" /></td> <td><input type="button" id = "b2" value = ">" /></td>
<td style = "width:250px"><input type="file" id = "file1" multiple/></td>
<td><input type="color" id="clr1" value="#ffffff" /></td> <td><input type="checkbox" id="ch1" style="width: 15px">large change</td> <td><input type="checkbox" id="ch2" style="width: 15px">use pixels</td></tr></table>
<div id="el0" contenteditable="true"></div>
<div id="instr" onclick='clk();'>The keys used are b(bkgrnd color), c(text color), l(left), r(radius), s(save), t(top), u (remove last element), w(width), _/-(dec), +/=(inc), Alt(update textarea), Escape(add text)<br /><br />
The body or an added division can be a parent. once a division is added, clicking either the body or a division selects that as the parent, and that will remain until another element is clicked.<br /><br />
Before opening the textarea make sure the body is selected.<br /><br />
Division: Choose division from select. Optionally,text can be added before adding the division by pressing v and entering text.<br/><br />
Image: Select an image and choose image from the select.<br /><br />
Text: For a value, choose text from the select. Then enter the value in the box and choose replace from the select. For a placeholder press v, enter the placeholder name and choose text from the select.<br/><br />
Link: Enter a URL,~~ and value and choose link<br /><br />
Change colors: Click the element to change. Select a color and press b for background color, c for text color, or color from the border select for border color.<br /><br />
If further changes are to be made to the same element it is not necessary to click again. If a new element is to be adjusted it must be clicked.<br /><br />
text ur border: For shadow color, choose the color and select shadow-color from the appropriate select element. If values need resizing or moving, use the inc or dec keys after selection. Others, such as font face can be changed directly from the select element.<br /><br />
Moving and sizing: Click the element and press t for vertical movement, l for horizontal movement or w for size. Use _/- to decrease or +/= to increase.<br /><br />
After making a change, the textarea will show the current code. Press Alt to update it.<br/><br />
Checking the checkbox increases the rate of repositioning and sizing. Unchecking it reverts.<br/><br />
Add Text: Select text container. Use Escape to show textarea. Enter text. Select sections to be formatted and they will be placed in span tabs. Choose add text. Areas
to be formated wil be in red and can be selected and modified as other elements.
It is possible to continue work on a previously saved page. Choose the file and click open <br/><br />
For clipping, select overflow.<br/><br />
Click this page to remove it.
</div>
<textarea id="ta" onmouseup='addSpan();'></textarea>
<script>
var ta = document.getElementById("ta");
var cnt = 0; var act = ""; var lft = []; var tp = []; var wd = []; var El = []; var sel = document.getElementById("s1"); var str = ""; var str2 = ""; var fld = "";
var cnt; var a = 0; var b = 0; var wid = 100 * (150 / screen.width); var txt = ""; var oldURL = "html.html"; /*var lcnt = 0;*/ var clr = document.getElementById("clr1"); El[0] = document.getElementById("el0"); var bclr ="white"; var cclr = "black"; var istr = ["","","","",""]; var oldstr; var typ = [];
ta.style.top = "150%"; var oldUrl; var oldName; var fstyle = 0; var fweight = 400; var sel2 = document.getElementById("s2"); var fsize = 22; var bsize = 1; var rad = []; var sel3 = document.getElementById("s3"); var ht = []; var rx1 = []; var tpad = 10; var lpad = 10; var elem; var cnt2; lft[0] = 0; var imTop = -5; var imLeft = -5; var slft; var stp; var p; var swd; var sclr; var bshadow = false; var tshadow = false; var oldval; var prnt; var inc = 2; var cnt3; var bck; var prntstr = ''; var res; var sav = false; var opnd = false;
var files = document.getElementById("file1"); ta.style.width = .99 * screen.width;

function addSpan() {
if (! sav) {
var selectedText = "";
cnt ++;
var v1 = '<span id="el' + cnt + '" style = "color: red">';
var v2 = '</span>';
selectedText = ta.value.substr(ta.selectionStart,ta.selectionEnd - ta.selectionStart);
if (selectedText != "") ta.value = ta.value.replace(selectedText, v1 + selectedText + v2);
}
}


function clk() {
document.getElementById("instr").style.top = "150%";
El[0].click();
}
document.addEventListener('click', (e) => {
if (e.target.id.indexOf("el") != -1) {
if (e.target.id != "ta" && e.target.id != "s1") elem = document.getElementById(e.target.id);
// alert(elem.id);
cnt2 = elem.id.substr(2);
if (cnt2 == 0) prnt = El[0];
if (cnt2 > 0 && (typ[cnt2] == "division" || opnd)) prnt = elem;
if (typ[cnt2] != "text") document.activeElement.blur();
opnd = false;
}
});

document.addEventListener('mousedown', (ev) => {
if(ev.target.id == "b1") window.dispatchEvent(new KeyboardEvent('keydown', {'key': '-'}));
if(ev.target.id == "b2") window.dispatchEvent(new KeyboardEvent('keydown', {'key': '='}));
});


function setBorder() {
if (sel3.value != "text") act = sel3.value;
document.activeElement.blur();
elem.style.borderWidth = bsize + "px";

if (act == "solid" || act == "ridge" || act == "groove" || act == "outset" || act == "inset") elem .style.borderStyle = act;
if (act == "color") elem .style.borderColor = clr.value;
if (sel3.value == "shadow-left") act = "bshadow-left";
if (sel3.value == "shadow-top") act = "bshadow-top";
if (sel3.value == "shadow-width") act = "bshadow-width";
if (sel3.value == "border-width") act = "border-width";
if (sel3.value == "shadow-color") {
var r = parseInt(clr.value.substr(1,2),16);
var g = parseInt(clr.value.substr(3,2),16);
var b = parseInt(clr.value.substr(5,2),16);
sclr = "rgba(" + r + "," + g + "," + b + ",1)";
elem.style.boxShadow = slft + "px " + stp + "px " + swd + "px " + sclr;
}
sel3.value = "border";
document.activeElement.blur();
}
function getFont() {
if (sel2.value != "text") act = sel2.value;
document.activeElement.blur();
if (act == "italic" ||act == "normal" ) elem.style.fontStyle = act;
if (act == "Arial Black" || act == "Georgia" || act == "Arial" || act == "Times New Roman" || act == "Courier New" || act == "Verdana" || act == "Comic Sans MS") elem.style.fontFamily = act;
if (act == "underline") elem.innerHTML = "<u>" + elem.innerHTML + "</u>";
if (sel2.value == "shadow-left") act = "tshadow-left";
if (sel2.value == "shadow-top") act = "tshadow-top";
if (sel2.value == "shadow-width") act = "tshadow-width";
if (act == "textcolor") elem.style.color = clr.value;

if (act == "shadow-color") {
var r = parseInt(clr.value.substr(1,2),16);
var g = parseInt(clr.value.substr(3,2),16);
var b = parseInt(clr.value.substr(5,2),16);
sclr = "rgba(" + r + "," + g + "," + b + ",1)";
elem.style.textShadow = slft + "px " + stp + "px " + swd + "px " + sclr;
}
sel2.value = "text";
document.activeElement.blur();
}
function appnd() {
act = "";
bck = El[0].innerHTML;
cnt ++;
cnt2 = cnt;
//alert(cnt2);
cnt3 = cnt;

if (sel.value == "textcolor") elem.style.color = clr.value;
if (sel.value == "textcolor") cnt--;
if (sel.value == "bkcolor") elem.style.backgroundColor = clr.value;
if (sel.value == "bkcolor") cnt--;
if (sel.value == "padding") elem.style.padding = "10px";
if (sel.value == "padding") cnt --;
if (sel.value == "overflow") cnt --;
if (sel.value == "overflow") elem.style.overflow = "hidden";
if (sel.value == "add text") {
elem.innerHTML += ta.value;
ta.style.top = "150%";
elem.contenteditable = "true";
}

if (sel.value == "open") {
cnt = 0;
var loadFile = document.getElementById("file1").files[0];
var fileReader = new FileReader();
fileReader.onload = function(fileLoadedEvent) {
var textFromFile = fileLoadedEvent.target.result;
a = 0;
b = 0;
a = textFromFile.indexOf("<body") + 6;
if (textFromFile.indexOf("<script") != -1) b = textFromFile.indexOf("<script");
if (textFromFile.indexOf("<script") == -1) b = textFromFile.indexOf("</body");
ta.value = textFromFile.substr(a,b-a);
a = 0;
b = 0;
a = document.body.innerHTML.lastIndexOf("</div") + 5;
El[0].innerHTML = ta.value;
a = 0;
b = 0;
while (a != -1) {
a = ta.value.indexOf('id="el',a + 1);
b = ta.value.indexOf('"', a + 3);
if (parseInt(ta.value.substr(a + 6 , b-a - 2 )) > cnt) cnt = parseInt(ta.value.substr(a + 6 , b-a - 2 ));
}
cnt2 = cnt;
// alert(cnt2);
opnd = true;
for (var i = 1; i <= cnt; i ++) {
El[i] = document.getElementById("el" + i);
lft[i] = Math.round(parseFloat(El[i].style.left.substr(0,El[i].style.left.length - 1))) * (screen.width/100);
tp[i] = Math.round(parseFloat(El[i].style.top.substr(0,El[i].style.top.length - 1))) * (screen.height/100);
wd[i] = Math.round(parseFloat(El[i].style.width.substr(0,El[i].style.width.length - 1))) * (screen.width/100);
ht[i] = Math.round(parseFloat(El[i].style.height.substr(0,El[i].style.height.length - 1))) * (screen.height/100);
}
};
fileReader.readAsText(loadFile, "UTF-8");
ta.style.top = "150%";
document.getElementById("file1").value = "";
}

if (sel.value == "replace") {
ta.style.top = "150%";

if (typ[cnt] = "text") {
prnt.innerHTML = prnt.innerHTML.replace('value="' + oldval + '"', 'value="' + elem.value + '"');
prnt.innerHTML = prnt.innerHTML.replace(elem.placeholder, ta.value);
}

if (typ[cnt2] = "link") {
a = 0;
a = ta.value.indexOf("``");
var tx1 = ta.value.substr(0,a);
var tx2 = ta.value.substr(a + 2);
prnt.innerHTML = prnt.innerHTML.replace(oldUrl, tx1);
prnt.innerHTML = prnt.innerHTML.replace(oldName, tx2);
ta.value = "";
}

if (typ[cnt2] = "paragraph") {
prnt.innerHTML = prnt.innerHTML.replace(elem.innerHTML,ta.value);
prnt.innerHTML = prnt.innerHTML.replace(new RegExp('\\n', 'g'),'<br />');
}
ta.style.top = "150%";
prnt.innerHTML = prnt.innerHTML.replace(ta.value, '');
}


if (sel.value == "image") {
wd[cnt2] = 150;
lft[cnt2] = 5;
tp[cnt2] = 5;
typ[cnt2] = "image";
var fl = files.files[0].name;
fld = document.getElementById("s4").value;
if (fl.indexOf("fakepath") != -1) fl = fl.substr(12);
prnt.innerHTML += '<img id = "el' + cnt + '" src = "' + fld + fl + '" style = "position: absolute; left:5px; top: 5px; width: ' + wid + '%" />';
elem = document.getElementById("el" + cnt2);
ta.value = prnt.innerHTML;
ta.style.top = "150%";
}

if (sel.value == "text") {
typ[cnt2] = "text";
wd[cnt2] = 150;
lft[cnt2] = 5;
tp[cnt2] = 5;

prnt.innerHTML += '<br><input type="text" id = "el' + cnt + '" style = "position: absolute; width: 150px; left: 5px; top: 5px" value="" placeholder="" ></input>';
elem = document.getElementById("el" + cnt);
oldval = elem.value;

a = 0;
a = prnt.innerHTML.lastIndexOf('placeholder');
var sub2 = prnt.innerHTML.substr(a,14);
elem.placeholder = ta.value;
ta.style.top = "150%";
prnt.innerHTML = prnt.innerHTML.replace(sub2,'placeholder="' + elem.placeholder + '"');


document.getElementById("s1").value = "choose";

elem.focus();
}


if (sel.value == "link") {
alert(cnt2);
var ele = "el" + cnt2;
typ[cnt2] = "link"
wd[cnt2] = 150;
lft[cnt2] = 2;
tp[cnt2] = 2;
a = 0;
a = ta.value.indexOf("``");
var tx1 = ta.value.substr(0,a);
oldUrl = tx1;
var tx2 = ta.value.substr(a + 2);
oldName = tx2;
// lcnt ++;
prnt.innerHTML += '<a id = "el' + cnt2 + '" href= "' + tx1 + '" target = "_blank" style = "position: absolute; border: 1px solid; text-align: center; left: 2px; top: 2px; width: 100%; font-size: 15px; background-color:#cccccc" onmouseover = \'document.getElementById("' + ele + '").style.color = "red";\' onmouseout = \'document.getElementById("' + ele + '").style.color = "black";\'>' + tx2 + '</a>' ;
elem = document.getElementById("el" + cnt);
El[cnt2] = elem;
ta.value = "";
ta.style.top = "150%";
elem.focus();
document.getElementById("s1").value = "choose";
}

if (sel.value == "paragraph") {
typ[cnt2] = "paragraph;"
lft[cnt2] = 5;
tp[cnt2] = 5;
slft = 5;
stp = 5;
swd= 8;
prnt.innerHTML += '<p id = "el' + cnt + '" style = "position: absolute; left: 5px; top: 5px: font-size: 22px; font-weight:600; padding: 0;" > ' + ta.value + '</p>';
elem = document.getElementById("el" + cnt);
elem.innerHTML = elem.innerHTML.replace(new RegExp('\\n', 'g'), '<br />');
elem.innerHTML = elem.innerHTML.replace(/\s/g, '&nbsp;&nbsp;');
elem.style.backgroundColor = prnt.style.backgroundColor;
elem.style.font = prnt.style.font;
ta.style.top = "150%";
}

if (sel.value == "division") {
lft[cnt2] = 5;
tp[cnt2] = 5;
if (sel.value == "division") {
ta.style.top = "150%";
typ[cnt2] = "division";
wd[cnt2] = .99 * screen.width;
ht[cnt2] = .9 * screen.height;
rad[cnt2] = 5;
slft = 5;
stp = 5;
swd= 8;
bsize = 1;
}

//ht[cnt2] = screen.height;
tp[cnt2] = 5;
rad[cnt2] = 5;

if (sel.value == "division") {
prnt.innerHTML += '<div id = "el' + cnt + '" style = "position: absolute; left: 5px; top: 100px; width: 100%; height: 100%; font-size: 22px; font-weight: 600; border: 2px solid; border-radius: 5px; white-space: pre-wrap" contenteditable = "true" ></div>';
elem = document.getElementById("el" + cnt);
//elem.innerHTML = strd.replace('</span></span>','');
elem.innerHTML = ta.value;
elem.style.fontSize = "22px";

}

cnt2 = cnt;
ta.value = "";
}

document.getElementById("s1").value = "choose";

if (typ[cnt] != "ellipse") {
if (document.getElementById("ch2").checked) {
elem.style.left = lft[cnt2] + "px";
elem.style.top = tp[cnt2] + "px";
elem.style.width = wd[cnt2] + "px";
elem.style.height = ht[cnt2] + "px";
elem .style.borderRadius = rad[cnt2] + "px";
}

if (!document.getElementById("ch2").checked) {
var wid2 = 100 * (wd[cnt2] / screen.width);
var lft2 = 100 * (lft[cnt2] / screen.width);
var tp2 = 100 * (tp[cnt2] / screen.height);
var ht2 = 100 * (ht[cnt2] / screen.height);


elem.style.left = lft2 + "%";
elem.style.top = tp2 + "%";
elem.style.width = wid2 + "%";
elem.style.height = ht2 + "%";
if (typ[cnt2] == "link") elem.style.width = "150px";
}
ta.value = El[0].innerHTML;
}

// document.getElementById("s1").blur();
}
window.addEventListener('keydown', (e) => {
if (e.key == "Escape") {
ta.style.top = "50px";
ta.value = "";
ta.select();
ta.focus();
}
if (e.key == "Alt") ta.value = El[0].innerHTML;
if (document.getElementById("ch1").checked) inc = 10;
if (! document.getElementById("ch1").checked) inc = 2;
document.getElementById("ch1").blur();
document.getElementById("b1").blur();
document.getElementById("b2").blur();
if (document.activeElement.id == "") {

//document.activeElement.blur();
if (e.key == "l") act = "left";
if (e.key == "t") act = "top";
if (e.key == "h") {
act = "height";
}
if (e.key == "r") act = "radius";
if (e.key == "Alt") {
ta.style.top = "50px";
ta.select();
ta.focus();
ta.value = "";
}
if (e.key == "w") act = "width";
if (e.key == "s") {
sav = true;
sve();
}

if (e.key == "b") {
elem.style.backgroundColor = clr.value;
bclr = clr.value;
}
if (e.key == "c") {
elem.style.color = clr.value;
cclr = clr.value;
}
if (e.key == "u") {
El[0].innerHTML = bck;
cnt--;
}

if (e.key == "=") {
if (act == "left") lft[cnt2] += inc;
if (act == "top") tp[cnt2] += inc;
if (act == "width") wd[cnt2] += inc;
if (act == "height") ht[cnt2] += inc;

if (act == "radius") rad[cnt2] ++;

if(act == "fontweight") {
fweight += 100;
if (fweight > 900) fweight = 900;
elem.style.fontWeight = fweight ;
}

if(act == "fontsize") {
fsize ++;
elem.style.fontSize = fsize + "px" ;
}

if(act == "border-width") {
bsize ++;
elem.style.borderWidth = bsize + "px";
}

if(act == "bshadow-width" || act == "tshadow-width") {
swd ++;
if (act == "bshadow-width") bshadow = true;
if( act == "tshadow-width") tshadow = true;
}

if(act == "bshadow-left" || act == "tshadow-left") {
slft ++;
if (act == "bshadow-left") bshadow = true;
if( act == "tshadow-left") tshadow = true;
}

if(act == "bshadow-top" || act == "tshadow-top") {
stp ++;
if (act == "bshadow-top") bshadow = true;
if( act == "tshadow-top") tshadow = true;
}


if (bshadow) {
elem.style.boxShadow = slft + "px " + stp + "px " + swd + "px " + sclr;
bshadow = false;
}

if (tshadow) {
elem.style.textShadow = slft + "px " + stp + "px " + swd + "px " + sclr;
tshadow = false;
}

if(sel3.value == "tpadding") {
tpad ++;
elem.style.padding = tpad + "px 10px 10px 10px";
ht[cnt2] -= 2;
}

if(sel3.value == "lpadding") {
lpad ++;
elem.style.padding = "10px 10px 10px " + lpad + "px";
wd[cnt2] -= 2;
}

if (document.getElementById("ch2").checked) {
if (act != "" && typ[cnt2] != "") {
elem.style.left = lft[cnt2] + "px";
elem.style.top = tp[cnt2] + "px";
elem.style.width = wd[cnt2] + "px";
elem.style.height = ht[cnt2] + "px";
elem .style.borderRadius = rad[cnt2] + "px";
}
}


if (! document.getElementById("ch2").checked) {
if (act != "" && typ[cnt2] != "") {
var wid2 = 100 * (wd[cnt2] / screen.width);
var lft2 = 100 * (lft[cnt2] / screen.width);
var tp2 = 100 * (tp[cnt2] / screen.width);
var ht2 = 100 * (ht[cnt2] / screen.width);

if (act != "" && typ[cnt2] != "") {
elem.style.left = lft2 + "%";
elem.style.top = tp2 + "%";
elem.style.width = wid2 + "%";
elem.style.height = ht2 + "%";
elem .style.borderRadius = rad[cnt2] + "px";
if (typ[cnt2] == "link") elem.style.width = "150px";
}
}
}
}
}

if (e.key == "-") {
if (act == "left") lft[cnt2] -= inc;
if (act == "top") tp[cnt2] -= inc;
if (act == "width") wd[cnt2] -= inc;
if (act == "height") ht[cnt2] -= inc;
//document.getElementById("t2").value = ht[cnt2];

if (act == "radius") rad[cnt2] --;

if(act == "fontweight") {
fweight -= 100;
if (fweight > 900) fweight = 900;
elem.style.fontWeight = fweight ;
}

if(act == "fontsize") {
fsize --;
elem.style.fontSize = fsize + "px" ;
}

if(act == "border-width") {
bsize --;
elem.style.borderWidth = bsize + "px";
}

if(act == "bshadow-width" || act == "tshadow-width") {
swd --;
if (act == "bshadow-width") bshadow = true;
if( act == "tshadow-width") tshadow = true;
}

if(act == "bshadow-left" || act == "tshadow-left") {
slft --;
if (act == "bshadow-left") bshadow = true;
if( act == "tshadow-left") tshadow = true;
}

if(act == "bshadow-top" || act == "tshadow-top") {
stp --;
if (act == "bshadow-top") bshadow = true;
if( act == "tshadow-top") tshadow = true;
}


if (bshadow) {
elem.style.boxShadow = slft + "px " + stp + "px " + swd + "px " + sclr;
bshadow = false;
}

if (tshadow) {
elem.style.textShadow = slft + "px " + stp + "px " + swd + "px " + sclr;
tshadow = false;
}



if(sel3.value == "tpadding") {
tpad ++;
elem.style.padding = tpad + "px 10px 10px 10px";
ht[cnt2] += 2;
}

if(sel3.value == "lpadding") {
lpad ++;
elem.style.padding = "10px 10px 10px " + lpad + "px";
wd[cnt2] += 2;
}

if (document.getElementById("ch2").checked) {
if (act != "" && typ[cnt2] != "") {
elem.style.left = lft[cnt2] + "px";
elem.style.top = tp[cnt2] + "px";
elem.style.width = wd[cnt2] + "px";
elem.style.height = ht[cnt2] + "px";
elem .style.borderRadius = rad[cnt2] + "px";
}
}

if (! document.getElementById("ch2").checked) {
if (act != "" && typ[cnt2] != "") {
var wid2 = 100 * (wd[cnt2] / screen.width);
var lft2 = 100 * (lft[cnt2] / screen.width);
var tp2 = 100 * (tp[cnt2] / screen.width);
var ht2 = 100 * (ht[cnt2] / screen.width);

if (act != "" && typ[cnt2] != "") {
elem.style.left = lft2 + "%";
elem.style.top = tp2 + "%";
elem.style.width = wid2 + "%";
elem.style.height = ht2 + "%";
elem .style.borderRadius = rad[cnt2] + "px";
}
}
}
}

});
function sve() {
var textToSave = El[0].innerHTML;

txt = elem.value;
if (txt == "") txt = elem.placeholder;
for (var i = 1; i <= cnt; i ++) {
}
textToSave = '<!DOCTYPE HTML> <html> <head> <style> a{text-decoration:none; font:italic normal 800 24px Georgia}:link { }:visited { }:hover {}:active { } </style> </head> <body> <div id="' + El[0].id + '" style = "position: absolute; width: 100%; height: 100%; top: 0"> ' + textToSave + '</div> </body></html>';
ta.value = textToSave.replace(new RegExp('<br>', 'g'), '\n');;


var textToSaveAsBlob = new Blob([textToSave], {type:"text/plain"});
var textToSaveAsURL = window.URL.createObjectURL(textToSaveAsBlob);
fileNameToSaveAs = prompt("FileName to save as",oldURL);
oldURL = fileNameToSaveAs;
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
downloadLink.href = textToSaveAsURL;
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
downloadLink.click();
}


function destroyClickedElement(event) {
document.body.removeChild(event.target);
}

</script>
</body></html>
It is a little long to go over in detail so I will mention only a few things.
All elements are given an id of El plus a number, which is incremented with the creation of a new element.

document.addEventListener(‘click’, (e) => {
if (e.target.id.indexOf(“el”) != -1) {
if (e.target.id != “ta” && e.target.id != “s1”) elem = document.getElementById(e.target.id);
// alert(elem.id);
cnt2 = elem.id.substr(2);
if (cnt2 == 0) prnt = El[0];
if (cnt2 > 0 && (typ[cnt2] == “division” || opnd)) prnt = elem;
if (typ[cnt2] != “text”) document.activeElement.blur();
opnd = false;
}
});

This listener detemines the active element and sets divisions as containers.

if (sel.value == “open”) {
cnt = 0;
var loadFile = document.getElementById(“file1”).files[0];
var fileReader = new FileReader();
fileReader.onload = function(fileLoadedEvent) {
var textFromFile = fileLoadedEvent.target.result;
a = 0;
b = 0;
a = textFromFile.indexOf(“body”) + 6;
if (textFromFile.indexOf(“script”) != -1) b = textFromFile.indexOf(“script”);
if (textFromFile.indexOf(“script”) == -1) b = textFromFile.indexOf(“/body”);
ta.value = textFromFile.substr(a,b-a);
a = 0;
b = 0;
a = document.body.innerHTML.lastIndexOf(“/div”) + 5;
El[0].innerHTML = ta.value;
a = 0;
b = 0;
while (a != -1) {
a = ta.value.indexOf(‘id=”el’,a + 1);
b = ta.value.indexOf(‘”‘, a + 3);
if (parseInt(ta.value.substr(a + 6 , b-a – 2 )) > cnt) cnt = parseInt(ta.value.substr(a + 6 , b-a – 2 ));
}
cnt2 = cnt;
// alert(cnt2);
opnd = true;
for (var i = 1; i <= cnt; i ++) {
El[i] = document.getElementById(“el” + i);
lft[i] = Math.round(parseFloat(El[i].style.left.substr(0,El[i].style.left.length – 1))) * (screen.width/100);
tp[i] = Math.round(parseFloat(El[i].style.top.substr(0,El[i].style.top.length – 1))) * (screen.height/100);
wd[i] = Math.round(parseFloat(El[i].style.width.substr(0,El[i].style.width.length – 1))) * (screen.width/100);
ht[i] = Math.round(parseFloat(El[i].style.height.substr(0,El[i].style.height.length – 1))) * (screen.height/100);
}
};
fileReader.readAsText(loadFile, “UTF-8”);
ta.style.top = “150%”;
document.getElementById(“file1”).value = “”;
}

This function loads files and sets the index for adding new elements:
while (a != -1) {
a = ta.value.indexOf(‘id=”el’,a + 1);
b = ta.value.indexOf(‘”‘, a + 3);
if (parseInt(ta.value.substr(a + 6 , b-a – 2 )) > cnt) cnt = parseInt(ta.value.substr(a + 6 , b-a – 2 ));
}
cnt2 = cnt;

The slideshow was not directly entered. The page was created and saved without it. The slideshow was then created, the code between the body tags copied and pasted into the code of the saved page.

A Table Generator

This is a simple app that creates and copies the code for tables that can be pasted into web pages.

Here is an example:

This is the code:

!DOCTYPE HTML>
html>
head>style>
input{position: relative;width:60px}
table{position: relative}
/style>/head>
body>
div id= “frame” style= “position: absolute; width: 100%; height: 100%; top: 50px”>/div>
center>input type = “text” id=”t5″ value=”” placeholder=”width” /> input type = “text” id=”t1″ value=”” placeholder=”# rows” /> input type = “text” id=”t2″ value=”” placeholder=”# cols” /> select id=”s1″>option>table/option>option>cell/option>/select> select id=”s2″>option>border/option>option>solid/option>option>ridge/option>option>groove/option>option>outset/option>option>inset/option>/select> select id=”s3″>option>border width/option>option>0/option>option>1/option>option>2/option>option>3/option>option>4/option>option>5/option>option>6/option>option>7/option>option>8/option>option>9/option>option>10/option>/select> select id=”s4″ onchange=’op();’>option>operation/option>option>create/option>option>save/option>/select>/center>
textarea id=”ta” Style = “position: absolute; width: 100%; height: 100%; top: 101%; background-color: #dddddd”>/textarea>

script>
var wd = “”; var ht = “”; var rows; var cols; var bw;
function op() {
if (document.getElementById(“s4”).value == “save”) {
sve();
} else {
bw = document.getElementById(“s3”).value + “px”;
rows = document.getElementById(“t1”).value; cols = document.getElementById(“t2”).value;
wd = document.getElementById(“t5”).value; var bd = document.getElementById(“s2”).value; //ht = “300px”;
var str = ‘center>table id=”tb” style = “border: ‘ + bw + ‘ ‘ + bd + ‘; border-collapse: collapse; text-align: center; width: ‘ + wd + ‘; height: ‘ + ht + ‘”>’;
for (var j = 1; j = rows; j ++ ) {
str += ‘tr>’;
for (var i = 1; i = cols; i ++ ) {
str += ‘td id = “td’ + j + i + ‘” style= “position: relative;padding:2px 10px; height: 50px; border: ‘ + bw + ‘ ‘ + bd + ‘” contenteditable = “true”>cell’ + j + i + ‘/td> ‘;
if (i == cols) str += “/tr>”
}
}
str += ‘/table>/center>’;
document.getElementById(“frame”).innerHTML = str;
}
}

function sve() {
document.getElementById(“ta”).value = document.getElementById(“frame”).innerHTML;
document.getElementById(“ta”).focus();
document.getElementById(“ta”).select();
success = document.execCommand(“copy”);
}
/script>
/body>/html>

The main function is called op().
A select with two options links to it. If “save” is chosen sve() is called:
function sve() {
document.getElementById(“ta”).value = document.getElementById(“frame”).innerHTML;
document.getElementById(“ta”).focus();
document.getElementById(“ta”).select();
success = document.execCommand(“copy”);
}

The table code is copied to a textarea which is then selected and its contents copied to the clipboard.

If “create” is chosen the following code creates the table:
bw = document.getElementById(“s3”).value + “px”;
rows = document.getElementById(“t1”).value; cols = document.getElementById(“t2”).value;
wd = document.getElementById(“t5”).value; var bd = document.getElementById(“s2”).value; //ht = “300px”;
var str = ”; for (var j = 1; j <= rows; j ++ ) { str += ”; for (var i = 1; i <= cols; i ++ ) { str += ‘ ‘; if (i == cols) str += “” } } str += ‘

cell’ + j + i + ‘

‘;
document.getElementById(“frame”).innerHTML = str;

The cells are contenteditable, which is then saved.

A width can be set for either the table or the cells.

The border style and border width can be set from select elements.

HTML Slideshow

This app creates slideshows for web pages.
It can be moved on the page and the individual images can be independently resized. There is a frame around each image which is automatically resized to fit the image.

This is a example;

It can either be saved, or the text between the body tags can be copied and pasted into another web page to add a slideshow.

This is the code:

chooseA-E/F-J/K-O/P-R/S-T/Animated GIF/


large change

The file element is set for multiple selection:

The image files are set in an array:

for (var i = 0; i < files.files.length; i ++) {
vals[i] = fld + files.files[i].name;
}

changing the file element calls the function go() which starts the slideshow:
si = setInterval(“show()”, per);

per by default is 2 seconds but can be set.

show() loads the images:
if (cnt < vals.length) cnt ++; cnt = cnt % vals.length; cnt4 ++; if (cnt < vals.length) document.getElementById(“frame”).innerHTML = ‘‘;

the images cannot be sized until they are fully loaded so a slight delay is set by calling the function dummy():

setTimeout(“dummy()”,50);

The images are set once to their initial size:
if (cnt4 <= vals.length) setTimeout(“sz()”,100); function sz() { if (doc[cnt].clientWidth > doc[cnt].clientHeight) {
w[cnt] = 400;
h[cnt] = Math.round(400 * (doc[cnt].clientHeight/doc[cnt].clientWidth));
}
if (doc[cnt].clientHeight > doc[cnt].clientWidth){
h[cnt] = 400;
w[cnt] = Math.round(400 * (doc[cnt].clientWidth/doc[cnt].clientHeight));
}

}

show2() is then called which sizes the frame to fit:
setTimeout(‘show2()’,100);
function show2() {
doc[cnt].style.width = w[cnt] + “px”;
doc[cnt].style.height = h[cnt] + “px”;
var ml = doc.clientWidth/2;
ml = -ml;
document.getElementById(“frame”).style.width = doc[cnt].clientWidth + “px”;
document.getElementById(“frame”).style.height = doc[cnt].clientHeight + “px”;
document.getElementById(“frame”).style.top = t + “px”;
document.getElementById(“frame”).style.marginLeft = ml + “px”;
doc[cnt].style.visibility = “visible”;

}

There is a keydown listener to move and size the images:
document.addEventListener(‘keydown’, (e) => {
if (e.key == “t”) act = “top”;
if (e.key == “l”) act = “left”;
if (e.key == “w”) act = “width”;
if (e.key == “s”) sve();

 if (e.key == "=") {

   if (act == "top") {
     t ++ ;
     document.getElementById("frame").style.top = t + "px";
   }

   if (act == "left") {
    l ++ ;
     document.getElementById("frame").style.left = l + "px";
   }

   if (act == "width") {
     inc = 20;
 if (doc[cnt].clientWidth > doc[cnt].clientHeight) {
 w[cnt] += inc;
 h[cnt] = Math.round(w[cnt] * (doc[cnt].clientHeight/doc[cnt].clientWidth));
 }
 if (doc[cnt].clientHeight > doc[cnt].clientWidth) {
 h[cnt] +=Math.round(inc * (screen.height/screen.width));
 w[cnt] = Math.round(h[cnt] * (doc[cnt].clientWidth/doc[cnt].clientHeight));
 }
 w2 = w;
 h2 = h;
 }
 }

 if (e.key == "-") {
   if (act == "top") {
     t ++ ;
     document.getElementById("frame").style.top = t + "px";
   }

   if (act == "left") {
    l -- ;
     document.getElementById("frame").style.left = l + "px";
   }
    if (act == "width") {
     inc = -20;
 if (doc[cnt].clientWidth > doc[cnt].clientHeight) {
 w[cnt] += inc;
 h[cnt] = Math.round(w[cnt] * (doc[cnt].clientHeight/doc[cnt].clientWidth));
 }
 if (doc[cnt].clientHeight > doc[cnt].clientWidth) {
 h[cnt] +=Math.round(inc * (screen.height/screen.width));
 w[cnt] = Math.round(h[cnt] * (doc[cnt].clientWidth/doc[cnt].clientHeight));
 }
 w2 = w;
 h2 = h;
 }
 }

 });

The images are moved by moving the frame:
if (e.key == “=”) {

   if (act == "top") {
     t ++ ;
     document.getElementById("frame").style.top = t + "px";
   }

   if (act == "left") {
    l ++ ;
     document.getElementById("frame").style.left = l + "px";
   }

The images are resized individually by the keydown:
if (act == “width”) {
inc = 20;
if (doc[cnt].clientWidth > doc[cnt].clientHeight) {
w[cnt] += inc;
h[cnt] = Math.round(w[cnt] * (doc[cnt].clientHeight/doc[cnt].clientWidth));
}
if (doc[cnt].clientHeight > doc[cnt].clientWidth) {
h[cnt] +=Math.round(inc * (screen.height/screen.width));
w[cnt] = Math.round(h[cnt] * (doc[cnt].clientWidth/doc[cnt].clientHeight));
}
w2 = w;
h2 = h;
}
}

The frame is then resized when the show2() function is called evert 100ms.

The position can be changed by small or large amounts:
if (document.getElementById(“c1”).checked) inc = .5;
if (! document.getElementById(“c1”).checked) inc = .1;

The sve() function places the code for the slideshow into a textarea:
function sve() {
wd = ‘[‘;
for (var i = 0; i < w2.length; i ++) {
wd += w2[i] + ‘,’;
}
wd = wd.substr(0,wd.length – 1);
wd += ‘]’;

ht = '[';
for (var i = 0; i < h2.length; i ++) {
ht += h2[i] + ',';
}
ht = ht.substr(0,wd.length - 1);
ht += ']';

 ta.value = '<!DOCTYPE HTML><html><body>';
 ta.value +=  '<div id="frame" style = "position: absolute; width: 400px; height: 400px; margin-left: -200px; top: 40px; left: 50%;  border: 8px ridge"></div><script>\n';
 ta.value += 'var vals = [];var si; var cnt = -1; var doc;';

ta.value += ‘var fld = “‘ + fld + ‘”; var w = ‘ + wd + ‘; var i; var h = ‘ + ht + ‘; var sze = true; var t = ‘ + t + ‘; var l = ‘ + l + ‘;’;
ta.value += ‘ var cnt4 = -1; var act; var inc; var per = 2000; var oldURL = “tmp.html”; var ta = document.getElementById(“ta”); var pic; var val;’;
ta.value += ‘per = ‘ + per + ‘; clearInterval(si);’;

 val = '[';
for (var i = 0; i < vals.length; i ++) {
val += '"' + vals[i] + '",';
}
val = val.substr(0,val.length - 1);
val += ']';

ta.value += ‘vals = ‘ + val + ‘;’;
ta.value += ‘ si = setInterval(“show()”,’ + per + ‘);’;
ta . value += ‘function dummy() { } function sz() { }’;

 ta.value += 'function show() {      if (cnt < vals.length) cnt ++;      cnt = cnt % vals.length;      cnt4 ++;    if (cnt < vals.length) document.getElementById("frame").innerHTML = \'<img id="im\' + cnt + \'" + src = "\' + vals[cnt] + \'" />\';    setTimeout("dummy()",50);    doc = document.getElementById("im" + cnt);    if (cnt4 <= vals.length) setTimeout("sz()",100);    doc.style.visibility = "hidden";    setTimeout(\'show2()\',100); }    function show2() {      doc.style.width = w[cnt] + "px";      doc.style.height = h[cnt] + "px";      var ml = doc.clientWidth/2;      ml = -ml;     document.getElementById("frame").style.width =  doc.clientWidth + "px";     document.getElementById("frame").style.height =  doc.clientHeight + "px";     document.getElementById("frame").style.top =  t + "px";  document.getElementById("frame").style.left =  l + "px"; document.getElementById("frame").style.marginLeft = ml + "px";     doc.style.visibility = "visible";}';
 ta.value += '<\/script></body></html>';

}

Where it can be copied and pasted

A non dropdown “select”

This is a simulated “select” element in which the elements are not drop-down.

This is the code:

The options are set as items of an array. The “select” element is actually a layer in which the innerHTML is loaded by selecting an index of the array by means of keys:
var cnt = 0;
function setOption(e) {
if (e.keyCode == 187) cnt ++;
if (e.keyCode == 189) cnt –;

document.getElementById(“sel”).innerHTML = opt[cnt];

The indices recycle if the upper or lower limits of the array are exceeded:
if (document.getElementById(“sel”).innerHTML == “undefined” && cnt > opt.length -2) {
cnt = 0;
document.getElementById(“sel”).innerHTML = “item1”;
}
if (document.getElementById(“sel”).innerHTML == “undefined” && cnt < opt.length -2) {
cnt = 9;
document.getElementById(“sel”).innerHTML = “item10”;
}

In this example the choice of an “option” by either clicking the layer or hitting Enter lists the chosen value in an alert, but any other action could be programmed.

A non dropdown color chooser

This is a non dropdown color chooser.
Here is an example:

colorSelectText

This is the code:

<!DOCTYPE HTML>
<html>
<body style=”background:black”>

<div id = “frame2” style = “position: absolute; width: 100%; height: 100%”>
<div id=”d3″ style=”position: absolute; top:100px; left: 100px; width: 300px; height: 300px; border: 1px solid white; border-radius: 20px”></div>
<div id=”d4″ style=”position: absolute; top:100px; left: 500px; width: 300px; height: 300px; border: 1px solid white; border-radius: 20px”></div>
</div>

<center><div id=”frame” style=”position: relative; width: 210px”>
<div id=”d1″ style=”position: absolute; left: 10px;width:30px; height: 30px; background: red;” ></div><div id=”d2″ style=” position: absolute; left: 40px; width:30px; height: 30px; background: black;” ></div><input type = “text” id=”t1″ style = “position: absolute; left: 70px; width: 120px” value = “” ondblclick=’chngCol();’/>
</div></center>
<script>
var cnt1 = 0; var d1 = document.getElementById(“d1”); var d2 = document.getElementById(“d2”); var r = 0; var g = 0; var b = 0; var ccnt = -1; var clrs = []; var a = 0; var b = 0; var oldURL = “tmpColor.html”;
document.onkeydown = setOption;

function setOption(e) {
if (e.keyCode == 187) {
if (d1.style.backgroundColor == “red”) r += 2;
if (d1.style.backgroundColor == “green”) g += 2;
if (d1.style.backgroundColor == “blue”) b += 2;
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
d2.style.backgroundColor = “rgb(” + r + “,” + g + “,” + b + “)”;
document.getElementById(“t1”).value = d2.style.backgroundColor;
}

if (e.keyCode == 189) {
if (d1.style.backgroundColor == “red”) r -= 2;
if (d1.style.backgroundColor == “green”) g -= 2;
if (d1.style.backgroundColor == “blue”) b -= 2;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
d2.style.backgroundColor = “rgb(” + r + “,” + g + “,” + b + “)”;
document.getElementById(“t1”).value = d2.style.backgroundColor;
}

if (e.keyCode == 18) {
cnt1 ++;
if (cnt1 == 0) d1.style.backgroundColor = “red”;
if (cnt1 == 1) d1.style.backgroundColor = “green”;
if (cnt1 == 2) d1.style.backgroundColor = “blue”;
if (cnt1 == 2) cnt1 = -1;
}
if (e.keyCode== 13) makeColors();
if (e.keyCode== 17) setColors();
if (e.keyCode== 32) sve();
}

function makeColors() {
ccnt ++;
clrs[ccnt] = d2.style.backgroundColor;
}

function setColors() {
document.body.style.backgroundColor = clrs[0];
document.getElementById(“d3”).style.backgroundColor = clrs[1];
document.getElementById(“d4”).style.backgroundImage = ‘-webkit-linear-gradient(left,’ + clrs[2] + ‘,’ + clrs[3] + ‘,’ + clrs[2] + ‘)’;
document.getElementById(“d4”).style.backgroundColor = ‘linear-gradient(left,’ + clrs[2] + ‘,’ + clrs[3] + ‘,’ + clrs[2] + ‘)’;
}

function chngCol() {
d2.style.backgroundColor = document.getElementById(“t1”).value;
a = d2.style.backgroundColor.indexOf(“,”);
b = a + 2;
r = d2.style.backgroundColor.substr(4,a-4);
a = d2.style.backgroundColor.indexOf(“,”, b);
g = d2.style.backgroundColor.substr(b,a-b);
b = a + 2;
a = d2.style.backgroundColor.indexOf(“)”, b);
b = d2.style.backgroundColor.substr(b,a-b);
}

function sve() {
var textToSave = ‘<!DOCTYPE HTML> <html> <style> body{background-color: ‘ + clrs[0] + ‘} </style> <body> ‘ + document.getElementById(“frame2”).innerHTML;
textToSave += ‘</body></html>’;
document.getElementById(“t1”).value = textToSave;
alert(textToSave);
var textToSaveAsBlob = new Blob([textToSave], {type:”text/plain”});
var textToSaveAsURL = window.URL.createObjectURL(textToSaveAsBlob);
fileNameToSaveAs = prompt(“FileName to save as”,oldURL);
oldURL = fileNameToSaveAs;
var downloadLink = document.createElement(“a”);
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = “Download File”;
downloadLink.href = textToSaveAsURL;
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = “none”;
document.body.appendChild(downloadLink);
downloadLink.click();
}

function destroyClickedElement(event) {
document.body.removeChild(event.target);
}
</script>
</body></html>

There is a square that shows the active color. Clicking Alt cycles between red, green and blue. The = key increases the value and the – key decreases it. This can be done for red,green and blue. Another square show the composite square. A text box shows the rgb vale of the composite:
if (e.keyCode == 18) {
cnt1 ++;
if (cnt1 == 0) d1.style.backgroundColor = “red”;
if (cnt1 == 1) d1.style.backgroundColor = “green”;
if (cnt1 == 2) d1.style.backgroundColor = “blue”;
if (cnt1 == 2) cnt1 = -1;
}

function setOption(e) {
if (e.keyCode == 187) {
if (d1.style.backgroundColor == “red”) r += 2;
if (d1.style.backgroundColor == “green”) g += 2;
if (d1.style.backgroundColor == “blue”) b += 2;
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
d2.style.backgroundColor = “rgb(” + r + “,” + g + “,” + b + “)”;
document.getElementById(“t1”).value = d2.style.backgroundColor;
}

if (e.keyCode == 189) {
if (d1.style.backgroundColor == “red”) r -= 2;
if (d1.style.backgroundColor == “green”) g -= 2;
if (d1.style.backgroundColor == “blue”) b -= 2;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
d2.style.backgroundColor = “rgb(” + r + “,” + g + “,” + b + “)”;
document.getElementById(“t1”).value = d2.style.backgroundColor;
}

This can also be done by entering a value in the text box and doubleclicking it:
function chngCol() {
d2.style.backgroundColor = document.getElementById(“t1”).value;
a = d2.style.backgroundColor.indexOf(“,”);
b = a + 2;
r = d2.style.backgroundColor.substr(4,a-4);
a = d2.style.backgroundColor.indexOf(“,”, b);
g = d2.style.backgroundColor.substr(b,a-b);
b = a + 2;
a = d2.style.backgroundColor.indexOf(“)”, b);
b = d2.style.backgroundColor.substr(b,a-b);
}

Hitting Enter than adds the selected color to an array:
if (e.keyCode== 13) makeColors();
function makeColors() {
ccnt ++;
clrs[ccnt] = d2.style.backgroundColor;
}

Hitting Control then finishes the operation:
if (e.keyCode== 17) setColors();
function setColors() {
document.body.style.backgroundColor = clrs[0];
document.getElementById(“d3”).style.backgroundColor = clrs[1];
document.getElementById(“d4”).style.backgroundImage = ‘-webkit-linear-gradient(left,’ + clrs[2] + ‘,’ + clrs[3] + ‘,’ + clrs[2] + ‘)’;
document.getElementById(“d4”).style.backgroundColor = ‘linear-gradient(left,’ + clrs[2] + ‘,’ + clrs[3] + ‘,’ + clrs[2] + ‘)’;
}

Hitting s saves the result.

Simulating Key Events

I often find keys more convenient to use than buttons, but they can not be used on virtual keyboard devices.
To port apps to mobile devices touch events must be substituted, which can lead to much rewriting, greatly increasing file size.
This alternative is to use touch events to simulate key events.
I wrote this example on a keyboard, so I used mousedown, but it should work with touchdown. The click and change work on an Android phone.
Here is an example:

keytestText

 

This is the code:

<!DOCTYPE html>
<html lang=”en”>
<head>
<title>Simulate a Keypress Event</title>
</head>
<body>
<input type=”button” id=”b1″ value = “click” /> <select id=”s1″><option>choose</option><option>option1</option><option>option2</option></select> <select id=”s2″><option>choose</option><option>option1</option><option>option2</option></select> <input type=”button” id=”b2″ style = “font: normal normal 800 20px Georgia” value = “<” /> <input type=”button” id=”b3″ style = “font: normal normal 800 20px Georgia” value = “>” /> <input type = “text” id = “t1″style = “font: normal normal 800 20px Georgia” value = “” />
<script>
var txt = document.getElementById(“t1”); var cnt = 0;
window.addEventListener(‘keydown’, (e) => {
t1.value = e.key;
if (e.key == “-“) cnt –;
if (e.key == “=”) cnt ++;
t1.value += ” ” + cnt;
});

document.addEventListener(‘mousedown’, (ev) => {
if(ev.target.id == “b2”) window.dispatchEvent(new KeyboardEvent(‘keydown’, {‘key’: ‘-‘}));
if(ev.target.id == “b3”) window.dispatchEvent(new KeyboardEvent(‘keydown’, {‘key’: ‘=’}));
});

document.addEventListener(‘click’, (ev) => {
if(ev.target.id == “b1”) window.dispatchEvent(new KeyboardEvent(‘keydown’, {‘key’: ‘h’}));
});

document.addEventListener(‘change’, (ev) => {
if (ev.target.id == “s1”) {
if(ev.target.value == “option1”) window.dispatchEvent(new KeyboardEvent(‘keydown’, {‘key’: ‘Space’}));
if(ev.target.value == “option2”) window.dispatchEvent(new KeyboardEvent(‘keydown’, {‘key’: ‘Enter’}));
}
if (ev.target.id == “s2”) {
if(ev.target.value == “option1”) window.dispatchEvent(new KeyboardEvent(‘keydown’, {‘key’: ‘c’}));
if(ev.target.value == “option2”) window.dispatchEvent(new KeyboardEvent(‘keydown’, {‘key’: ‘d’}));
}
document.getElementById(“s1”).value = “choose”;
document.getElementById(“s2”).value = “choose”;
document.activeElement.blur();
});
</script>
</body>
</html>

The key is the use of dispatchEvent:
document.addEventListener(‘mousedown’, (ev) => {
if(ev.target.id == “b2”) window.dispatchEvent(new KeyboardEvent(‘keydown’, {‘key’: ‘-‘}));
if(ev.target.id == “b3”) window.dispatchEvent(new KeyboardEvent(‘keydown’, {‘key’: ‘=’}));
});

Pressing a button simulates pressing a key. In lines above the keys are – and =.
You can also combine that with a simultaneous control or alt by adding congrol = “true” or alt = “true”.

In the example above, the text box showed the simulated key as well as an incremented counter:
var cnt = 0;
window.addEventListener(‘keydown’, (e) => {
t1.value = e.key;
if (e.key == “-“) cnt –;
if (e.key == “=”) cnt ++;
t1.value += ” ” + cnt;
});