JS File Database


This app uses a js file as a database and has several features.
A select element can be interactively populated.
The app can be instantly updated on modifications.
Multiple items can be added at once.

This is the interface with the select exposed:

This is an option selected:

The app consists of a html file:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;
<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head profile=”http://gmpg.org/xfn/11″&gt;
<title>HTML Editor</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 { }
#t2{width: 700px}
#t1, #t2, #s1 {font:normal normal 600 18px Arial;
</style>
</head>
<body>
<select id=”s1″></select> <input type=”text” id=”t1″ name=”t1″ value=”Add Option” /> <input type=”text” id=”t2″ name=”t2″ value=”Option Value” ondblclick=’addItems();’ /> <input type=”button” id=”b1″ name=”b1″ value=”Recall”onclick=’rcall();’ /> <input type=”button” id=”b2″ name=”b2″ value=”Save”onclick=’sve();’ />

http://tst1.js
<script type=”text/javascript”>
var oldURL = “tst1.js”; var textToSave = “”; var indx; var itemStr = “”; var cnt = -1;

for (var i = 1; i < dbindx; i ++) {
document.getElementById(“s1”).innerHTML += ‘<option>’ + selArr[i].join() + ‘</option>’;
}

function addItems() {
cnt ++;
document.getElementById(“s1”).innerHTML += ‘<option>’ + document.getElementById(“t1”).value + ‘</option>’;
document.getElementById(“s1”).value = document.getElementById(“t1″).value;
itemStr += ‘dbArr[‘ + (dbindx + cnt) + ‘] = [\” + document.getElementById(“t2″).value + ‘\’];\n’;
itemStr += ‘selArr[‘ + (dbindx + cnt) + ‘] = [\” + document.getElementById(“s1”).value + ‘\’];\n’;
}

function rcall() {
indx = document.getElementById(“s1”).selectedIndex + 1;
document.getElementById(“t2″).value = dbArr[indx].join();
}

function sve() {

if (dbindx == 1) {
textToSave += ‘dbArr[1] = [\” + document.getElementById(“t2″).value + ‘\’];\n’;
textToSave += ‘selArr[1] = [\” + document.getElementById(“s1”).value + ‘\’];\n’;
}

if (dbindx > 1 || dbindx + cnt > 1) {
textToSave = “”;

for (var i = 1; i < dbindx; i ++) {
textToSave += ‘dbArr[‘ + i + ‘] = [\” + dbArr[i].join() + ‘\’];\n’;
textToSave += ‘selArr[‘ + i + ‘] = [\” + selArr[i].join() + ‘\’];\n’;
}

textToSave += itemStr;
}

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);
setTimeout(“rload()”, 12000);
}

function rload() {
location.reload();
}

</script>

</body></html>


and a js file, which is used only as a database:

var dbindx = 4; selArr = new Array(); dbArr = new Array();
dbArr[1] = [‘this is a test’];
selArr[1] = [‘Option 1’];
dbArr[2] = [‘This is a second test’];
selArr[2] = [‘Option 2’];
dbArr[3] = [‘This is a third test’];
selArr[3] = [‘Option 3’];

dbindx is always set one greater than the highest array index, so the next array element will be incremented.
There are two arrays, one for the select options and one for the corresponding string.

On loading, the select element is populated from the array:
for (var i = 1; i < dbindx; i ++) {
document.getElementById(“s1”).innerHTML += ‘<option>’ + selArr[i].join() + ‘</option>’;
}

There are two text inputs. The first creates options to be added to the select:
The second both adds the select options and creates the associated strings:
function addItems() {
cnt ++;
document.getElementById(“s1”).innerHTML += ‘<option>’ + document.getElementById(“t1”).value + ‘</option>’;
document.getElementById(“s1”).value = document.getElementById(“t1″).value;
itemStr += ‘dbArr[‘ + (dbindx + cnt) + ‘] = [\” + document.getElementById(“t2″).value + ‘\’];\n’;
itemStr += ‘selArr[‘ + (dbindx + cnt) + ‘] = [\” + document.getElementById(“s1″).value + ‘\’];\n’;
}

Instead of adding the new array e;ements to the js file with each addition, they can be stored in a variable and be added at once, saving time.

The general method of saving has been discussed before, but I will go over some unique modifications.

if (dbindx == 1) {
textToSave += ‘dbArr[1] = [\” + document.getElementById(“t2″).value + ‘\’];\n’;
textToSave += ‘selArr[1] = [\” + document.getElementById(“s1”).value + ‘\’];\n’;
}

if (dbindx > 1 || dbindx + cnt > 1) {
textToSave = “”;

for (var i = 1; i < dbindx; i ++) {
textToSave += ‘dbArr[‘ + i + ‘] = [\” + dbArr[i].join() + ‘\’];\n’;
textToSave += ‘selArr[‘ + i + ‘] = [\” + selArr[i].join() + ‘\’];\n’;
}

textToSave += itemStr;
}

dbindx += cnt + 1;
textToSave = ‘var dbindx = ‘ + dbindx + ‘; selArr = new Array(); dbArr = new Array();\n’ + textToSave;

Since the js file must be replaced with each saving, the textToSave string must contain all previous content.
if (dbindx == 1) {
textToSave += ‘dbArr[1] = [\” + document.getElementById(“t2″).value + ‘\’];\n’;
textToSave += ‘selArr[1] = [\” + document.getElementById(“s1”).value + ‘\’];\n’;
}

if (dbindx > 1 || dbindx + cnt > 1) {
textToSave = “”;

for (var i = 1; i < dbindx; i ++) {
textToSave += ‘dbArr[‘ + i + ‘] = [\” + dbArr[i].join() + ‘\’];\n’;
textToSave += ‘selArr[‘ + i + ‘] = [\” + selArr[i].join() + ‘\’];\n’;
}

The new data is then appended:
textToSave += itemStr;

I said before that dbindx must 1 greater than the highest index.
Therefore, the headings are created after the arrays, with an incremented dbindx, and then placed before:
dbindx += cnt + 1;
textToSave = ‘var dbindx = ‘ + dbindx + ‘; selArr = new Array(); dbArr = new Array();\n’ + textToSave;

The last unique thing with the save is the aytomatic update.
A timer is started and calls a function to reload the page:

setTimeout(“rload()”, 12000);

function rload() {
location.reload();
}

The timer is set for twelve seconds to allow time to save the js file, before the page is reloaded.
The result is the page is automatically updated in twelve seconds, with all new data retrieved from the js file.

Finally, selecting an option and clicking Recall displays the string associated with that option:
function rcall() {
indx = document.getElementById(“s1”).selectedIndex + 1;
document.getElementById(“t2”).value = dbArr[indx].join();
}

This is a fairly simple example, but the same concept can be used for any arrays that can be set up.

Audio API Update – Automatic Scales


This further addition automatically plays entire scales.

Here is how the change looks:

To Try Click Here

Here is the code:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;
<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head profile=”http://gmpg.org/xfn/11″&gt;
<title>Beep</title>
<style>
body {margin-left:0;margin-right:0;font:normal normal normal 15px Arial; background: #f8f2aa}
a{ text-decoration: }:link { color: rgb(0, 0, 255) }:visited {color :rgb(100, 0,100) }:hover { }:active { }
input, button{font:normal normal 700 18px Arial}
#d1{font:normal normal 800 28px Georgia}
#b1,#b2, button{height: 25px}
</style>
</head>
<body>
volume
<input type=”range” id=”vIn” min=”0″ max=”100″ value = “100” oninput=”show()” />
<span id=”vOut”></span><br>
<br>
<button onclick=’beep(“a”);’>Play A</button>
<button onclick=’beep(“b”);’>Play</button>
<select id=”s1″ name=”s1″ onchange=’beep(“c”);’>
<option>Choose Note</option><option>C4</option>
<option>C&#9839 4 or D&#9837 4</option>
<option>D4</option>
<option>D&#9839 4 or E&#9837 4</option>
<option>E4</option>
<option>F4</option>
<option>F&#9839 4 or G&#9837 4</option>
<option>G4</option>
<option>G&#9839 4 or A&#9837 4</option>
<option>A4</option>
<option>A&#9839 4 or B&#9837 4</option>
<option>B4</option><option>C5</option>
<option>C&#9839 5 or D&#9837 5</option>
<option>D5</option>
<option>D&#9839 5 or E&#9837 5</option>
<option>E5</option>
<option>F5</option>
<option>F&#9839 5 or G&#9837 5</option>
<option>G5</option>
<option>G&#9839 5 or A&#9837 5</option>
<option>A5</option>
<option>A&#9839 5 or B&#9837 5</option>
<option>B5</option>
<option>C6</option>
</select>
<select id=”s2″ name=”s2″ onchange=’scle();’>
<option>Play Scale</option>
<option>C Major</option>
<option>C Minor</option>
<option>C&#9839 Major</option>
<option>C&#9839 Minor</option>
<option>D Major</option>
<option>D Minor</option>
<option>E&#9837 Major</option>
<option>E&#9837 Minor</option>
<option>E Major</option>
<option>E Minor</option>
<option>F Major</option>
<option>F Minor</option>
<option>G Major</option>
<option>G Minor</option>
<option>A&#9837 Major</option>
<option>A&#9837 Minor</option>
<option>A Major</option>
<option>A Minor</option>
<option>B&#9837 Major</option>
<option>B&#9837 Minor</option>
<option>B Major</option>
<option>B Minor</option>
</select>
<input type=”text” id=”t1″ name=”t1″ value=”” onclick=’document.getElementById(“t1”).value = “”;’ />
<button onclick=’chck();’>Check</button>
<input type=”button” id=”b1″ value=”&#9839″ onclick=’document.getElementById(“t1”).value += “&#9839”; document.getElementById(“t1″).focus();’ />
<input type=”button” id=”b2″ value=”&#9837″ onclick=’document.getElementById(“t1”).value += “&#9837”; document.getElementById(“t1”).focus();’ />
<button onclick=’document.getElementById(“d1″).style.visibility=”visible”; document.getElementById(“d1”).innerHTML = “<br/>” + nte[indx];’>Answer</button>
<di id=”d1″ style=”position: absolute; left:50%; top: 5%; width: 200px; height: 100px; border: 1px solid gray; background: #eefff2; text-align: center; visibility: hidden” onclick=’document.getElementById(“d1″).style.visibility=”hidden”;’></di>

var type = ‘sine’; var indx; var frequency; var cnt = 0; var si; var cnt = -1; var ini;
var v1 = document.getElementById(“b1”).value; var v2 = document.getElementById(“b2”).value; var v3; var t;
var freq = [“261.63″,”277.18″,”293.66″,”311.13″,”329.63″,”349.23″,”369.99″,”392″,”415.31″,”440″,”466.16″,”493.88″,”523.25″,”554.37”, “587.33”,”622.25″,”659.26″,”698.46″,”739.99″,”783.99″,”830.61″,”880″,”932.33″,”987.77″,”1046.50″];

var nte = [“C4″,”C” + v1 + “4 or D” + v2 + “4”,”D4″, “D” + v1 + “4 or E” + v2 + “4”,”E4″,”F4″,”F” + v1 + “4 or G” + v2 + “4”, “G4″,”G” + v1 + “4 or A” + v2 + “4”,”A4″,”A” + v1 + “4 or B” + v2 + “4”,”B4″,”C5″,”C” + v1 + “5 or D” + v2 + “5”,”D5″, “D” + v1 + “5 or E” + v2 + “5”,”E5″,”F5″,”F” + v1 + “5 or G” + v2 + “5”, “G5″,”G” + v1 + “5 or A” + v2 + “5”,”A5″,”A” + v1 + “5 or B” + v2 + “5”,”B5″,”C6″];

var majr = [0,2,4,5,7,9,11,12]; var minr = [0,2,3,5,7,8,10,12];

var cmaj = [“C”,”D”,”E”,”F”,”G”,”A”,”B”,”C”]; var cmin = [“C”,”D”,”E” + v2,”F”,”G”,”A” + v2,”B” + v2,”C”]; var csharp = [“C” + v1,”D” + v1,”F”,”F” + v1,”G” + v1,”A” + v1,”C”,”C” + v1]; var csharpmin = [“C” + v1,”D” + v1,”E”,”F” + v1,”G” + v1,”A” + v1,”B”,”C” + v1]; var dmaj = [“D”,”E”,”F” + v1,”G” + v1,”A”,”B”,”C” + v1,”D”]; var dmin = [“D”,”E”,”F”,”G”,”A”,”B” + v2,”C”,”D”]; var eflat = [“E” + v2,”F”,”G”,”A” + v2,”B” + v2,”C”,”D”,”E” + v2]; var eflatmin = [“E” + v2,”F”,”G” + v2,”A” + v2,”B” + v2,”C”,”D”,”E” + v2]; var emaj = [“E”,”F” + v1,”G” + v1,”A” + v1,”C”,”C” + v1,”D” + v1,”E”]; var emin = [“E”,”F” + v1,”G”,”A”,”B”,”C” + v1,”D”,”E”]; var fmaj = [“F”,”G”,”A”,”B” + v2,”C”,”D”,”E”,”F”]; var fmin = [“F”,”G”,”A” + v2,”B” + v2,”C”,”D” + v2,”E” + v2,”F”]; var gmaj = [“G”,”A”,”B”,”C” + v1,”D”,”E”,”F” + v1,”G”]; var gmin = [“G”,”A”,”B” + v2,”C”,”D”,”E” + v2,”F”,”G”]; var aflat = [“A” + v2,”B” + v2,”C”,”D” + v2,”E” + v2,”F”,”G”,”A”]; var aflatmin = [“A” + v2,”B” + v2,”B”,”D” + v2,”E” + v2,”E”,”G” + v2,”A” + v2]; var amaj = [“A”,”B”,”C” + v1,”D”,”E”,”F” + v1,”G” + v1,”A”]; var amin = [“A”,”B”,”C”,”D”,”E”,”F”,”G”,”A”]; var bflat = [“B” + v2,”C”,”D”,”E” + v2,”F”,”G”,”A”,”B” + v2]; var bflatmin = [“B” + v2,”C”,”D” + v2,”E”,”G” + v2,”G”,”A” + v2,”B” + v2]; var bmaj = [“B”,”D” + v2,”E” + v2,”E”,”F”,”G”,”B” + v2,”B”]; var bmin = [“B”,”C” + v1,”D”,”E”,”F” + v1,”G” + v1,”A”,”B”];

audioCtx = new(window.AudioContext || window.webkitAudioContext)();

show();

function show() {
type = ‘sine’
volume = document.getElementById(“vIn”).value / 100;
document.getElementById(“vOut”).innerHTML = volume;
duration = “500”;
}

function scle() {si = setInterval(“beep2()”, 2000);}

function beep2() {
cnt ++;
var k = document.getElementById(“s2”).value;
if (k == “C Major”) {ini = 0; t = cmaj[cnt];}
if (k == “C Minor”) {ini = 0; t = cmin[cnt];}
if (k == “C” + v1 + ” Major”) {ini = 1; t = csharp[cnt];}
if (k == “C” + v1 + ” Minor”) {ini = 1; t = csharpmin[cnt];}
if (k == “D Major” ) {ini = 2; t = dmaj[cnt];}
if (k == “D Minor” ) {ini = 2; t = dmin[cnt];}
if (k == “E” + v2 + ” Major”) {ini = 3; t = eflat[cnt];}
if (k == “E” + v2 + ” Minor”) {ini = 3; t = eflatmin[cnt];}
if (k == “E Major”) {ini = 4; t = emaj[cnt];}
if (k == “E Minor”) {ini = 4; t = emin[cnt];}
if (k == “F Major”) {ini = 5; t = fmaj[cnt];}
if (k == “F Minor”) {ini = 5; t = fmin[cnt];}
if (k == “G Major”) {ini = 7; t = gmaj[cnt];}
if (k == “G Minor”) {ini = 7; t = gmin[cnt];}
if (k == “A” + v2 + ” Major”) {ini = 8; t = aflat[cnt];}
if (k == “A” + v2 + ” Minor”) {ini = 8; t = aflatmin[cnt];}
if (k == “A Major” ) {ini = 9; t = amaj[cnt];}
if (k == “A Minor”) {ini = 9; t = amin[cnt];}
if (k == “B” + v2 + ” Major”) {ini = 10; t = bflat[cnt];}
if (k == “B” + v2 + ” Minor”) {ini = 10; t = bflatmin[cnt];}
if (k == “B Major”) {ini = 11; t = bmaj[cnt];}
if (k == “B Minor”) {ini = 11; t = bmin[cnt];}

if (k.indexOf(“Major”) > -1) indx = ini + majr[cnt];
if (k.indexOf(“Minor”) > -1) indx = ini + minr[cnt];

if (indx > ini + 11) {
clearInterval(si);
cnt = -1;
document.getElementById(“s2”).value = “Play Scale”;
}

//document.getElementById(“t1”).value = nte[indx];
document.getElementById(“t1”).value = t;
frequency = freq[indx];
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();

oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);

gainNode.gain.value = volume;
oscillator.type = type;
oscillator.frequency.value = frequency;
oscillator.start();
setTimeout(function() {oscillator.stop();}, duration);
}

function beep(val) {
clearInterval(si);
if (document.getElementById(“s2”).value == “Play Scale”) {
document.getElementById(“t1”).focus();
v3 = document.getElementById(“s1”).value;
indx= Math.floor(25 * Math.random());
if (val == “a”) indx = 9;
if (val == “c”) {
if (v3 == “C4”) indx = 0;
if (v3.indexOf(“C” + v1 + ” 4″) > -1) indx = 1;
if (v3 == “D4”) indx = 2;
if (v3.indexOf(“E” + v2 + ” 4″) > -1 ) indx = 3;
if (v3 == “E4”) indx = 4;
if (v3 == “F4”) indx = 5;
if (v3.indexOf(“F” + v1 + ” 4″) > -1) indx = 6;
if (v3 == “G4”) indx = 7;
if (v3.indexOf(“A” + v2 + ” 4″) > -1 ) indx = 8;
if (v3 == “A4”) indx = 9;
if (v3.indexOf(“B” + v2 + ” 4″) > -1) indx = 10;
if (v3 == “B4”) indx = 11;
if (v3 == “C5”) indx = 12;
if (v3.indexOf(“C” + v1 + ” 5″) > -1) indx = 13;
if (v3 == “D5”) indx = 14;
if (v3.indexOf(“E” + v2 + ” 5″) > -1) indx = 15;
if (v3 == “E5”) indx = 16;
if (v3 == “F5”) indx = 17;
if (v3.indexOf(“F” + v1 + ” 5″) > -1) indx = 18;
if (v3 == “G5”) indx = 19;
if (v3.indexOf(“A” + v2 + ” 5″) > -1) indx = 20;
if (v3 == “A5”) indx = 21;
if (v3.indexOf(“B” + v2 + ” 5″) > -1) indx = 22;
if (v3 == “B5”) indx = 23;
if (v3 == “C6”) indx = 24;
}
frequency = freq[indx];
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();

oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);

gainNode.gain.value = volume;
oscillator.type = type;
oscillator.frequency.value = frequency;
oscillator.start();
setTimeout(function() {oscillator.stop();}, duration);
}
}

function chck() {
var vt = document.getElementById(“t1”).value;
vt = vt.replace(vt.substr(0,1), vt.substr(0,1).toUpperCase());
document.getElementById(“t1”).value = vt;
if (nte[indx].indexOf(vt) > -1 ) {
document.getElementById(“d1″).style.visibility=”visible”;
document.getElementById(“d1”).innerHTML = “
Correct!”;
}
document.getElementById(“t1”).focus();
document.getElementById(“t1”).value = “”;
}

</body></html>


I will discuss the scale addition.
A series of Arrays containing the notes of the scales is added:
var cmaj = [“C”,”D”,”E”,”F”,”G”,”A”,”B”,”C”]; var cmin = [“C”,”D”,”E” + v2,”F”,”G”,”A” + v2,”B” + v2,”C”]; var csharp = [“C” + v1,”D” + v1,”F”,”F” + v1,”G” + v1,”A” + v1,”C”,”C” + v1]; var csharpmin = [“C” + v1,”D” + v1,”E”,”F” + v1,”G” + v1,”A” + v1,”B”,”C” + v1]; var dmaj = [“D”,”E”,”F” + v1,”G” + v1,”A”,”B”,”C” + v1,”D”]; var dmin = [“D”,”E”,”F”,”G”,”A”,”B” + v2,”C”,”D”]; var eflat = [“E” + v2,”F”,”G”,”A” + v2,”B” + v2,”C”,”D”,”E” + v2]; var eflatmin = [“E” + v2,”F”,”G” + v2,”A” + v2,”B” + v2,”C”,”D”,”E” + v2]; var emaj = [“E”,”F” + v1,”G” + v1,”A” + v1,”C”,”C” + v1,”D” + v1,”E”]; var emin = [“E”,”F” + v1,”G”,”A”,”B”,”C” + v1,”D”,”E”]; var fmaj = [“F”,”G”,”A”,”B” + v2,”C”,”D”,”E”,”F”]; var fmin = [“F”,”G”,”A” + v2,”B” + v2,”C”,”D” + v2,”E” + v2,”F”]; var gmaj = [“G”,”A”,”B”,”C” + v1,”D”,”E”,”F” + v1,”G”]; var gmin = [“G”,”A”,”B” + v2,”C”,”D”,”E” + v2,”F”,”G”]; var aflat = [“A” + v2,”B” + v2,”C”,”D” + v2,”E” + v2,”F”,”G”,”A”]; var aflatmin = [“A” + v2,”B” + v2,”B”,”D” + v2,”E” + v2,”E”,”G” + v2,”A” + v2]; var amaj = [“A”,”B”,”C” + v1,”D”,”E”,”F” + v1,”G” + v1,”A”]; var amin = [“A”,”B”,”C”,”D”,”E”,”F”,”G”,”A”]; var bflat = [“B” + v2,”C”,”D”,”E” + v2,”F”,”G”,”A”,”B” + v2]; var bflatmin = [“B” + v2,”C”,”D” + v2,”E”,”G” + v2,”G”,”A” + v2,”B” + v2]; var bmaj = [“B”,”D” + v2,”E” + v2,”E”,”F”,”G”,”B” + v2,”B”]; var bmin = [“B”,”C” + v1,”D”,”E”,”F” + v1,”G” + v1,”A”,”B”];

Changing the select calls the function scale to play the notes ar two second intervals:
function scle() {si = setInterval(“beep2()”, 2000);}

function beep2() {
cnt ++;
var k = document.getElementById(“s2”).value;
if (k == “C Major”) {ini = 0; t = cmaj[cnt];}
if (k == “C Minor”) {ini = 0; t = cmin[cnt];}
if (k == “C” + v1 + ” Major”) {ini = 1; t = csharp[cnt];}
if (k == “C” + v1 + ” Minor”) {ini = 1; t = csharpmin[cnt];}
if (k == “D Major” ) {ini = 2; t = dmaj[cnt];}
if (k == “D Minor” ) {ini = 2; t = dmin[cnt];}
if (k == “E” + v2 + ” Major”) {ini = 3; t = eflat[cnt];}
if (k == “E” + v2 + ” Minor”) {ini = 3; t = eflatmin[cnt];}
if (k == “E Major”) {ini = 4; t = emaj[cnt];}
if (k == “E Minor”) {ini = 4; t = emin[cnt];}
if (k == “F Major”) {ini = 5; t = fmaj[cnt];}
if (k == “F Minor”) {ini = 5; t = fmin[cnt];}
if (k == “G Major”) {ini = 7; t = gmaj[cnt];}
if (k == “G Minor”) {ini = 7; t = gmin[cnt];}
if (k == “A” + v2 + ” Major”) {ini = 8; t = aflat[cnt];}
if (k == “A” + v2 + ” Minor”) {ini = 8; t = aflatmin[cnt];}
if (k == “A Major” ) {ini = 9; t = amaj[cnt];}
if (k == “A Minor”) {ini = 9; t = amin[cnt];}
if (k == “B” + v2 + ” Major”) {ini = 10; t = bflat[cnt];}
if (k == “B” + v2 + ” Minor”) {ini = 10; t = bflatmin[cnt];}
if (k == “B Major”) {ini = 11; t = bmaj[cnt];}
if (k == “B Minor”) {ini = 11; t = bmin[cnt];}

if (k.indexOf(“Major”) > -1) indx = ini + majr[cnt];
if (k.indexOf(“Minor”) > -1) indx = ini + minr[cnt];

ini sets the note to be played and t the note to be displayed.

When the scale is completed the timer is stopped and values are reset:
if (indx > ini + 11) {
clearInterval(si);
cnt = -1;
document.getElementById(“s2”).value = “Play Scale”;
}

The note is displayed in the text input:
document.getElementById(“t1”).value = t;

The sounding is the same as before.

Sorting HTML Tables


This app makes a table editable and allows the rows to be sorted.

The current post introduces the concept, so most things are fixed; the matrix is 4×2, the column headings are set and the order of sorting is fixed at Last Name and then First Name.

This is similar to a spreadsheet, with a difference:
A spreadsheet is initiated with a fixed size, although it can be later varied.

Future postings will elaborate.

This is the appearance:

With some names added:

and sorted:

<

To Try Click Here

Here is the code:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;
<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head profile=”http://gmpg.org/xfn/11″&gt;
<title>HTML Editor</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 { }
table{position: relative; left: 200px; empty-cells: show; border-collapse: collapse}
td{position: relative; width: 100px; height: 25px; border: 1px solid black; padding: 2px 10px}
</style>
</head>
<body>
<table id= “tb1″ contenteditable=”true”>
<tr><td contenteditable=”false”>First Name</td><td contenteditable=”false”>Last Name</td><td id=”td1″>Sort1</td></td><td id=”td2″>Sort2</td></td><td><input type=”button” id=”b1″ name=”b1″ value=”Sort” onclick=’srt();’ /></td></tr>
</table><br/>
<table id= “tb2″ contenteditable=”true”></table>

var tmp = “”;
for (var i =1; i

‘;
}

function srt() {
for (var j = 1; j
</body></html>


The Interface consists of two contenteditable tables; the first contains the headings, sorting and controls, while the second contains the names to be sorted.

The Headings are not editable and the sorting names, although editable, do not do anything. In future versions they will be used.

The second table is created from code:
for (var i =1; i <= 5; i ++) {
document.getElementById(“tb2″).innerHTML += ‘<tr><td id=”td’ + i + ‘1″></td><td id=”td’ + i + ‘2”></td></tr>’;
}

Clicking Sort calls the function srt().
The first part does a bubble sort with the values of the second columns:
function srt() {
for (var j = 1; j <= 4; j ++) {
for (var i= j + 1; i <= 5; i ++) {
if (document.getElementById(“td” + i + “2”).innerHTML < document.getElementById(“td” + j + “2”).innerHTML) {
tmp = document.getElementById(“td” + j + “2”).innerHTML;
document.getElementById(“td” + j + “2”).innerHTML = document.getElementById(“td” + i + “2”).innerHTML;
document.getElementById(“td” + i + “2”).innerHTML = tmp;

tmp = document.getElementById(“td” + j + “1”).innerHTML;
document.getElementById(“td” + j + “1”).innerHTML = document.getElementById(“td” + i + “1”).innerHTML;
document.getElementById(“td” + i + “1”).innerHTML = tmp;
}
}
}

The second takes the result of the first sort and sorts with the first column;
for (var j = 1; j <= 4; j ++) {
for (var i= j + 1; i <= 5; i ++) {
if (document.getElementById(“td” + i + “2”).innerHTML == document.getElementById(“td” + j + “2”).innerHTML && document.getElementById(“td” + i + “1”).innerHTML < document.getElementById(“td” + j + “1”).innerHTML) {
tmp = document.getElementById(“td” + j + “2”).innerHTML;
document.getElementById(“td” + j + “2”).innerHTML = document.getElementById(“td” + i + “2”).innerHTML;
document.getElementById(“td” + i + “2”).innerHTML = tmp;

tmp = document.getElementById(“td” + j + “1”).innerHTML;
document.getElementById(“td” + j + “1”).innerHTML = document.getElementById(“td” + i + “1”).innerHTML;
document.getElementById(“td” + i + “1”).innerHTML = tmp;
}
}
}

}

This is done only if two Last Names are identical:
if (document.getElementById(“td” + i + “2”).innerHTML == document.getElementById(“td” + j + “2”).innerHTML && document.getElementById(“td” + i + “1”).innerHTML < document.getElementById(“td” + j + “1”).innerHTML) {

HTML “Cash Register”


I have, on occasion been asked to handle a cashbox at a charity event. I therefore wrote this app, which can be run on a phone, to keep track of the income.

It has two lists, one for cash and one for checks, With each entry, sums are calculated for total incomes of cash, checks and the two values are summed for the total income.

After all income is taken in, thd tally can be saved as a HTML file.

Here is the appearance.

To Try Click Here

Here is the code:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;
<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head profile=”http://gmpg.org/xfn/11″&gt;
<title>HTML Editor</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 { }
#table1, #table2{position: absolute; left:10px ; top:10px ; height: 24px }
#table2{top:50px; empty-cells: show}
input{position: absolute; top:10px}
#b1{left: 480px}
#b2{left: 530px}
#b3{left: 580px}
td{width: 100px}
</style>
</head>
<body>
<table id= “table1″>
<tr><td id=”td11″>Cash</td><td id=”td12″>Check</td><td id=”td13″>Cash Total</td><td id=”td14″>Check Total</td><td id=”td15″>Total</td></tr>
<tr><td> </td><td> </td><td id=”tda3″>0</td><td id=”tda4″>0</td><td id=”tda5″>0</td></tr>
</table>
<input type=”button” id=”b1″ name=”b1″ value=”Sum” onclick=’newTot();’ /><input type=”button” id=”b2″ name=”b2″ value=”New” onclick=’location.reload();’/><input type=”button” id=”b3″ name=”b3″ value=”Save” onclick=’sve();’/>

<table id= “table2” contenteditable = “true” >
<tr><td id=”td21″ onclick=’rset(“td21″);’>0</td><td id=”td22” onclick=’rset(“td22”);’>0</td></tr>
</table>

var r = 2; var str = “”; var l1; var l2; var sum1 = 0; var sum2 = 0; var sum3 = 0; var j = 1; var str2 = “”; var oldURL = “newTally.html”;

function newRow() {
for (var i = 2; i

‘ + l1 + ‘ ‘ + l2 + ‘

‘;
str2 = str;
}
r ++;
str += ‘

‘;
for (var i = 1; i 0

‘;
}
str += ‘

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

function newTot() {
j ++;
l1 = document.getElementById(“td” + j + “1”).innerHTML;
l2 = document.getElementById(“td” + j + “2”).innerHTML;
sum1 += parseFloat(l1);
document.getElementById(“tda3”).innerHTML = sum1.toFixed(2);
sum2 += parseFloat(l2);
document.getElementById(“tda4”).innerHTML = sum2.toFixed(2);
sum3 = sum1 + sum2;
document.getElementById(“tda5”).innerHTML = sum3.toFixed(2);
newRow();
}

function rset(el) {
document.getElementById(el).innerHTML = “”;
}

function sve() {
var sav = ‘Tallybody {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 { }#table1, #table2{position: absolute; left:10px ; top:10px ; height: 24px }#table2{top:50px; empty-cells: show}input{position: absolute; top:10px}td{width: 100px}

‘ + document.getElementById(“table1”).innerHTML + ‘
‘ + str2 + ‘

‘;
var textToSaveAsBlob = new Blob([sav], {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);
}

</body></html>


There are two tables:
<table id= “table1″>
<tr><td id=”td11″>Cash</td><td id=”td12″>Check</td><td id=”td13″>Cash Total</td><td id=”td14″>Check Total</td><td id=”td15″>Total</td></tr>
<tr><td> </td><td> </td><td id=”tda3″>0</td><td id=”tda4″>0</td><td id=”tda5″>0</td></tr>
</table>
<input type=”button” id=”b1″ name=”b1″ value=”Sum” onclick=’newTot();’ /><input type=”button” id=”b2″ name=”b2″ value=”New” onclick=’location.reload();’/><input type=”button” id=”b3″ name=”b3″ value=”Save” onclick=’sve();’/>

<table id= “table2” contenteditable = “true” >
<tr><td id=”td21″ onclick=’rset(“td21″);’>0</td><td id=”td22” onclick=’rset(“td22”);’>0</td></tr>
</table>

There are three buttons. On clicking the Sum button the function newTot() is called:
function newTot() {
j ++;
l1 = document.getElementById(“td” + j + “1”).innerHTML;
l2 = document.getElementById(“td” + j + “2”).innerHTML;
sum1 += parseFloat(l1);
document.getElementById(“tda3”).innerHTML = sum1.toFixed(2);
sum2 += parseFloat(l2);
document.getElementById(“tda4”).innerHTML = sum2.toFixed(2);
sum3 = sum1 + sum2;
document.getElementById(“tda5”).innerHTML = sum3.toFixed(2);
newRow();
}

variables l1 and l2 are for the cash and check values:
l1 = document.getElementById(“td” + j + “1”).innerHTML;
l2 = document.getElementById(“td” + j + “2”).innerHTML;

Each one is summed and displayed in a table cell, fixed at two decimal places:
sum1 += parseFloat(l1);
document.getElementById(“tda3”).innerHTML = sum1.toFixed(2);
sum2 += parseFloat(l2);
document.getElementById(“tda4”).innerHTML = sum2.toFixed(2);

sum3 = sum1 + sum2;
document.getElementById(“tda5”).innerHTML = sum3.toFixed(2);
The two totals are summed and placed in a cell with the overall total:

The function newRow() is then called to permit new entries:
function newRow() {
for (var i = 2; i <= r; i ++) {
l1 = document.getElementById(“td” + i + “1”).innerHTML;
l2 = document.getElementById(“td” + i + “2”).innerHTML;
str += ‘<tr><td id=”td’ + i + ‘1″>’ + l1 + ‘</td><td id=”td’ + i + ‘2″>’ + l2 + ‘</td></tr>’;
str2 = str;
}
r ++;
str += ‘<tr>’;
for (var i = 1; i <= 2; i ++) {
str += ‘<td id=”td’ + r.toString() + i + ‘” onclick=\’rset(“td’ + r.toString() + i + ‘”);\’>0</td>’;
}
str += ‘</tr>’;
document.getElementById(“table2”).innerHTML = str;
str = “”;
}

You cannot add new rows directly; on opening a new row it is automatically closed. Therefore everything must be placed in a string and the table given the value of the string.

First, the previous values must be placed in the string:
for (var i = 2; i <= r; i ++) {
l1 = document.getElementById(“td” + i + “1”).innerHTML;
l2 = document.getElementById(“td” + i + “2”).innerHTML;
str += ‘<tr><td id=”td’ + i + ‘1″>’ + l1 + ‘</td><td id=”td’ + i + ‘2″>’ + l2 + ‘</td></tr>’;
str2 = str;
}
str2 is used for saving the tally.

A new row is then added, the new cells being given the value 0:
r ++;
str += ‘<tr>’;
for (var i = 1; i <= 2; i ++) {
str += ‘<td id=”td’ + r.toString() + i + ‘” onclick=\’rset(“td’ + r.toString() + i + ‘”);\’>0</td>’;
}
str += ‘</tr>’;
document.getElementById(“table2”).innerHTML = str;
str = “”;
}

Clicking the New button reloads the page for a new tally:
<input type=”button” id=”b2″ name=”b2″ value=”New” onclick=’location.reload();’/>

The procedure to save has been discussed before.