Use SVG to Create Boxes


This app draws boxes in any shape with four sided faces and with any fill with a few exceptions.
First, a few tips on how to use:
To draw any new figure you must first click the New button:

Click Image for larger view

grid

The New button must be green and the count box must read 0 for any new object to be drawn.
With the help of the grid, coordinates for the front face must be placed by clicking.
Seven points are required to define a box.
After the first four points are set, the front face is drawn and filled with the color selected from a color input box.
The fill is that chosen with two exceptions:
The default black of the input creates a gray fill and checking wireframe chooses no fill, instead, a wireframe is drawn.
The next two clicks create the box top and the final click finishes the figure with a total of three faces being visible.
Here is how a standared box may appear:

Click Image for larger view

box

You notice that the sample image does not have the grid. Selecting a background color and clicking Clear Grid removes the grid and highlights the box against the selected background.
This procedure should only be done as the last step, since to return to the drawing mode, the Undo button must be clicked, which removes anything drawn and turns the New button reddish as a warning that it must be clicked to draw anything new.
It is also possible to place multiple objects in the same drawing, as in this image, which also demonstrates a box with a non-rectangular face;

Click Image for larger view

boxillusion

This is an interesting optical illusion; If you focus on only one box, you see it as a box. But if you look at both boxes simultaneously, only one at a time can appear as a box, the other being a concave figure, and it flips back and forth between the two boxes as to which seems to be a box.

Here is a box made from parallelograms:

Click Image for larger view

parallel

Wireframes can be drawn with a limitation; either the first and second point must have the same y value or the first and fourth point must have the same x value. Here is a wireframe example:

wireframe

This restriction does not occur in a filled box. In this example the first point is the upper right one:

rotatedpar

Here is an Escher like figure:

Click Image for larger view

escher

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>Box</title>
<style>
body {margin-left:0;margin-right:0;font:normal normal normal 12pt Arial;}a{ text-decoration: }:link { color: rgb(0, 0, 255) }:visited {color :rgb(100, 0,100) }:hover { }:active { }
input{position: relative; top; 5px; height: 20px}
#t1 {font-size: 12pt; text-align: center}
#b1{background: #aaffaa}
</style>
</head>
<body>
<input type=”text” id=”t1″ name=”t1″ value=”Count” /> <input type=’color’ id=’color’ value= simple color /> <input type=”button” id=”b1″ name=”b1″ value=”New” onclick=’init();’ /> <input type=”button” id=”b2″ name=”b2″ value=”Undo” onclick=’undo();’ /> <input type=”button” id=”b3″ name=”b3″ value=”Clear Grid” onclick=’clar();’ /> <input type=”checkbox” id = “cb” name=”cb” value=”wireframe” />Wireframe

lbracket div class=”d1″ rbracket
<svg id=”svg1″ style=”cursor: crosshair” width=”100%” height=”100%” xmlns=”http://www.w3.org/2000/svg”&gt;
<defs>
<pattern id=”smallGrid” width=”8″ height=”8″ patternUnits=”userSpaceOnUse”>
<path d=”M 8 0 L 0 0 0 8″ fill=”none” stroke=”black” stroke-width=”0.5″/>
</pattern>
<pattern id=”grid” width=”80″ height=”80″ patternUnits=”userSpaceOnUse”>
<rect width=”80″ height=”80″ fill=”url(#smallGrid)”/>
<path d=”M 80 0 L 0 0 0 80″ fill=”none” stroke=”black” stroke-width=”1″/>
</pattern>
</defs>
<rect width=”100%” height=”100%” fill=”url(#grid)” />
</svg>
</div>

lbracket script type=”text/javascript” rbracket

var posX;var posY; var cnt; var oldX; var oldY; var fl = “#dddddd”; var clr = “”;
var IE; Xpos = new Array(); Ypos = new Array();

function init() {
document.getElementById(“b1”).style.backgroundColor = “#aaffaa”;
for (var i = 1; i <= 10; i ++) {
Xpos[i] = 0;
Ypos[i] = 0;
}

if (document.getElementById(“color”).value != “#000000”) {
fl = document.getElementById(“color”).value;
cnt –;
} else {
fl = “#dddddd”;
cnt –;
}

if (document.getElementById(“cb”).checked) {
fl = “none”
cnt –;
}

cnt = -1;
oldX = 0;
oldY = 0;
IE = document.all?true:false;
if (!IE) document.captureEvents(Event.MOUSEMOVE)
document.onclick = getMouse2;
// document.onmousemove = getMouseXY;
}

function getMouse2(e) {
cnt ++;
document.getElementById(“t1”).value = cnt ;
if (IE) {
if (cnt > 0) {
posX = event.clientX + document.body.scrollLeft;
posY = event.clientY + document.body.scrollTop;
}
}
else {
if (cnt > 0) {
posX = e.pageX ;
posY = e.pageY – 35;
Xpos[cnt] = posX;
Ypos[cnt] = posY;
}

if (cnt < 8) document.getElementById(“svg1”) .innerHTML += ‘ <ellipse cx = ‘ + posX + ‘ cy = ‘ + posY + ‘ rx = “2” ry = “2” fill = “black” />’;
clr += ‘ <ellipse cx = ‘ + posX + ‘ cy = ‘ + posY + ‘ rx = “2” ry = “2” fill = “black” />’;

if (cnt == 4) {
document.getElementById(“svg1″) .innerHTML += ‘<polygon points= ” ‘ + Xpos[1] + ‘ ,’ + Ypos[1] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[2] + ‘ ‘ + Xpos[3] + ‘,’ + Ypos[3] + ‘ ‘ + Xpos[4] + ‘,’ + Ypos[4] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[1] + ‘ ,’ + Ypos[1] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[2] + ‘ ‘ + Xpos[3] + ‘,’ + Ypos[3] + ‘ ‘ + Xpos[4] + ‘,’ + Ypos[4] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
}

if (cnt == 6) {
document.getElementById(“svg1″) .innerHTML += ‘<polygon points= ” ‘ + Xpos[1] + ‘ ,’ + Ypos[1] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[5] + ‘ ‘ + Xpos[6] + ‘,’ + Ypos[6] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[2] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[1] + ‘ ,’ + Ypos[1] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[5] + ‘ ‘ + Xpos[6] + ‘,’ + Ypos[6] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[2] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
}

if (cnt == 7) {
document.getElementById(“svg1″) .innerHTML += ‘<polygon points= ” ‘ + Xpos[3] + ‘ ,’ + Ypos[3] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[2] + ‘ ‘ + Xpos[6] + ‘,’ + Ypos[6] + ‘ ‘ + Xpos[7] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[3] + ‘ ,’ + Ypos[3] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[2] + ‘ ‘ + Xpos[6] + ‘,’ + Ypos[6] + ‘ ‘ + Xpos[7] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
}

if (document.getElementById(“cb”).checked && cnt == 7) {
fl = “none”;
if ( Math.abs(Xpos[1] – Xpos[4]) < 5 ) {
document.getElementById(“svg1″) .innerHTML += ‘<polygon points= ” ‘ + Xpos[4] + ‘ ,’ + Ypos[4] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[1] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[5] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
document.getElementById(“svg1″).innerHTML += ‘<polygon points= ” ‘ + Xpos[5] + ‘ ,’ + Ypos[5] + ‘ ‘ + Xpos[6] + ‘,’ + Ypos[6] + ‘ ‘ + Xpos[7] + ‘,’ + Ypos[7] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[4] + ‘ ,’ + Ypos[4] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[1] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[5] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[5] + ‘ ,’ + Ypos[5] + ‘ ‘ + Xpos[6] + ‘,’ + Ypos[6] + ‘ ‘ + Xpos[7] + ‘,’ + Ypos[7] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
} else if (Xpos[1] > Xpos[4]) {
document.getElementById(“svg1″) .innerHTML += ‘<polygon points= ” ‘ + Xpos[4] + ‘ ,’ + Ypos[4] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[1] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[5] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
document.getElementById(“svg1″).innerHTML += ‘<polygon points= ” ‘ + Xpos[5] + ‘ ,’ + Ypos[5] + ‘ ‘ + Xpos[6] + ‘,’ + Ypos[6] + ‘ ‘ + Xpos[7] + ‘,’ + Ypos[7] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[4] + ‘ ,’ + Ypos[4] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[1] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[5] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[5] + ‘ ,’ + Ypos[5] + ‘ ‘ + Xpos[6] + ‘,’ + Ypos[6] + ‘ ‘ + Xpos[7] + ‘,’ + Ypos[7] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
} else {
document.getElementById(“svg1″) .innerHTML += ‘<polygon points= ” ‘ + Xpos[4] + ‘ ,’ + Ypos[4] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[1] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[5] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
document.getElementById(“svg1″).innerHTML += ‘<polygon points= ” ‘ + Xpos[5] + ‘ ,’ + Ypos[5] + ‘ ‘ + Xpos[6] + ‘,’ + Ypos[6] + ‘ ‘ + Xpos[7] + ‘,’ + Ypos[7] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
document.getElementById(“svg1″) .innerHTML += ‘<polygon points= ” ‘ + Xpos[4] + ‘ ,’ + Ypos[4] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[1] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[5] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[4] + ‘ ,’ + Ypos[4] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[1] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[5] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[5] + ‘ ,’ + Ypos[5] + ‘ ‘ + Xpos[6] + ‘,’ + Ypos[6] + ‘ ‘ + Xpos[7] + ‘,’ + Ypos[7] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[4] + ‘ ,’ + Ypos[4] + ‘ ‘ + Xpos[1] + ‘,’ + Ypos[1] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[5] + ‘ ‘ + Xpos[5] + ‘,’ + Ypos[7] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
}
}
}
if (posY > 35) {
document.getElementById(“t1”).value = cnt ;

}
}

function clar() {
document.getElementById(“svg1”).style.backgroundColor = document.getElementById(“color”).value;
document.getElementById(“svg1”) .innerHTML = clr;
}

function undo() {
document.getElementById(“svg1”).style.backgroundColor = “white”;
document.getElementById(“b1”).style.backgroundColor = “#ffaaaa”;
clr = “”;
cnt = -3;
for (var i = 1; i <= 10; i ++) {
Xpos[i] = 0;
posX = 0;
posY = 0;
Ypos[i] = 0;
}
document.getElementById(“svg1″) .innerHTML = ‘<defs>\n<pattern id=”smallGrid” width=”8″ height=”8″ patternUnits=”userSpaceOnUse”>\n<path d=”M 8 0 L 0 0 0 8″ fill=”none” stroke=”black” stroke-width=”0.5″/>\n </pattern>\n <pattern id=”grid” width=”80″ height=”80″ patternUnits=”userSpaceOnUse”>\n<rect width=”80″ height=”80″ fill=”url(#smallGrid)”/>\n<path d=”M 80 0 L 0 0 0 80″ fill=”none” stroke=”black” stroke-width=”1″/>n</pattern>\n </defs>\n<rect width=”100%” height=”100%” fill=”url(#grid)” />’;
}

/* function getMouseXY(e) {
if (IE) {
posX = event.clientX + document.body.scrollLeft;
posY = event.clientY + document.body.scrollTop;
}
else {
posX = e.pageX -10;
posY = e.pageY – 50;
}

document.getElementById(“t1”).value = posX;
}*/
</script>
</body></html>

The points are made from ellipses:
if (cnt < 8) document.getElementById(“svg1”) .innerHTML += ‘ <ellipse cx = ‘ + posX + ‘ cy = ‘ + posY + ‘ rx = “2” ry = “2” fill = “black” />’;
clr += ‘ <ellipse cx = ‘ + posX + ‘ cy = ‘ + posY + ‘ rx = “2” ry = “2” fill = “black” />’;

The boxes are created from a series of polygons when the point count reaches 4 6 or 7:
if (cnt == 4) {
document.getElementById(“svg1″) .innerHTML += ‘<polygon points= ” ‘ + Xpos[1] + ‘ ,’ + Ypos[1] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[2] + ‘ ‘ + Xpos[3] + ‘,’ + Ypos[3] + ‘ ‘ + Xpos[4] + ‘,’ + Ypos[4] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
clr += ‘<polygon points= ” ‘ + Xpos[1] + ‘ ,’ + Ypos[1] + ‘ ‘ + Xpos[2] + ‘,’ + Ypos[2] + ‘ ‘ + Xpos[3] + ‘,’ + Ypos[3] + ‘ ‘ + Xpos[4] + ‘,’ + Ypos[4] + ‘ ” fill = ‘ + fl + ‘ stroke = “black” stroke-width=”2″ />’;
}

The grid is set up with the following code:
<div class=”d1″>
<svg id=”svg1″ style=”cursor: crosshair” width=”100%” height=”100%” xmlns=”http://www.w3.org/2000/svg”&gt;
<defs>
<pattern id=”smallGrid” width=”8″ height=”8″ patternUnits=”userSpaceOnUse”>
<path d=”M 8 0 L 0 0 0 8″ fill=”none” stroke=”black” stroke-width=”0.5″/>
</pattern>
<pattern id=”grid” width=”80″ height=”80″ patternUnits=”userSpaceOnUse”>
<rect width=”80″ height=”80″ fill=”url(#smallGrid)”/>
<path d=”M 80 0 L 0 0 0 80″ fill=”none” stroke=”black” stroke-width=”1″/>
</pattern>
</defs>
<rect width=”100%” height=”100%” fill=”url(#grid)” />
</svg>
</div&gt

Clicking the New button calls thew init() function, part of which sets up mouse input:
IE = document.all?true:false;
document.onclick = getMouse2;
}

function getMouse2(e) {
cnt ++;
document.getElementById(“t1”).value = cnt ;
if (IE) {
if (cnt > 0) {
posX = event.clientX + document.body.scrollLeft;
posY = event.clientY + document.body.scrollTop;
}
}
else {
if (cnt > 0) {
posX = e.pageX ;
posY = e.pageY – 35;
Xpos[cnt] = posX;
Ypos[cnt] = posY;
}

Any click will trigger a mouse event, so the following is needed to draw the points only within the confines of the grid:
if (posY > 35) {
document.getElementById(“t1”).value = cnt ;
}

HTML App for Custom Spreadsheet Sorting


Spreadsheets can be sorted according to ascending or descending criteria, either numerical or alphabetical. But what if you want a custom order that is neither?
I originally wrote an app specifically for doing race results. Runners wear bibs with unique numbers that have detachable tags with the bib number listed.
As a runner crosses the finish line the tag is collected and kept in order, to determine the finish position. A registration spreadsheet also has the bib number and is usually sorted by that number.
My original app sorted by matching the registration bib number with the finish bib number, so the registration rows were sorted in order of finish. The finish bib row was then converted into a finish place, from 1 up.
I then realized that it could be made more general, so any spreadsheet could be sorted to a custom order. The difference is that while race bib numbers are unique, most other categories are not.
However, it turns out that is not a problem, so long as there is a sorting category name for every row.
The first image shows a hypothetical list of 3 universities with students and their majors that will ultimately sorted by major,with the majors not in alphabetical order:

Click Image for larger view

customsort1

The first step would be to sort by major the standard way :

Click Image for larger view

customsort2

The standard method would then be to cut the rows of the first category, insert an equal number of blank rows at the top of the spreadsheet and paste the cut data.
This would be repeated for each category, inserting each set of blank rows immediately below the previously inserted row.
This could become very tedious for a large number of rows, as blank rows are generally inserted one at a time.
An easier procedure would be to move the sorting category to the first column, insert a new blank first column, copy the members of the first sorting category, paste into the first column and repeat for each category of the sorting order.
A macro could be written to sort by matching the first column, but each spreadsheet application would have its own macro. I therefore wrote an app from html and javascript that could be used with any spreadsheet application.
The first step of this procedure is to save the spreadsheet as a csv file and open the file in a text editor.
The text would be copied and pasted into the sorting app, making certain there is no line feed at the end.
Clicking Sort then performs the matching and sorting and highlights the sorted text:

Click Image for larger view

customsort3

The highlighted text is then pasted back into the spreadsheet:

Click Image for larger view

customsort4

If desired, a standard sort can further rearrange the spreadsheet, being sure the primary sorting is on the first column:

Click Image for larger view

customsort5

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>CSV Sort</title>
<style>
body {margin-left:0;margin-right:0;font:normal normal normal 15pt Arial;}a{ text-decoration: }:link { color: rgb(0, 0, 255) }:visited {color :rgb(100, 0,100) }:hover { }:active { }
#csv{position: relative;left: 20%; width: 60%; height: 600px}

</style>
</head>
<body>
<input type=”button” id=”b1″ name=”b1″ value=”Sort” onclick=’go();’ /> <input type=”button” id=”b2″ name=”b2″ value=”LocalSave” onclick=’lstore(“s”);’ /> <input type=”button” id=”b3″ name=”b3″ value=”Open” onclick=’lstore(“o”);’ /><br />
<textarea id=”csv” name=”csv” rows=”” cols=””></textarea>

var a = 0; str1 = new Array(); str2 = new Array(); strrem = new Array(); strline = new Array; var cnt = 0; var b = 0; var c = 0; var strrem; var d = 0;

function lstore(type) {
if (type == “s”) {
localStorage.setItem(“csvsort”,document.getElementById(“csv”).value);
} else {
document.getElementById(“csv”).value = localStorage.getItem(“csvsort”);
}
}

function go() {

document.getElementById(“csv”).value += “\n”;

for (var i=1;i less=500;i++ ){
a = document.getElementById(“csv”).value.indexOf(“\n”, b);
if (a == -1) {
break;
}
strline[i] = document.getElementById(“csv”).value.substr(b,a-b);
c = strline[i].indexOf(“,”);
str1[i] = strline[i].substr(0,c);
b = a + 1;
d = strline[i].indexOf (“,”, c + 1);
strrem[i] = strline[i].substr (c+ 1, strline[i].length – c – 1);
str2[i] = strline[i].substr (c + 1, d – c – 1) ;d = strline[i].indexOf (“,”, c + 1);
strrem[i] = strline[i].substr (c+ 1, strline[i].length – c – 1);
str2[i] = strline[i].substr (c + 1, d – c – 1) ;
cnt ++;
}

for (var k = 1; k less= cnt; k ++) {
for (var l = k+1; l less= cnt; l ++) {
if (str2[l] == str1[k]) {
var tmp = strrem[l];
var tmp2 = str2[l];
strrem[l] = strrem[k];
str2[l] = str2[k];
strrem[k] = tmp;
str2[k] = tmp2;
}
}
}

document.getElementById(“csv”).value = “”;
for (var i=1;i less=500;i++ ){
if (str1[i] != ” “) document.getElementById(“csv”).value += str1[i] + “,” + strrem[i] + “\n”;
}

document.getElementById(“csv”).focus();
document.getElementById(“csv”).select();
success = document.exec(‘copy’);
alert(success);
}

</body></html>


The textarea is searched for a newline character and an array of individual lines strline[] is populated:
for (var i=1; i <=500;i++ ){
a = document.getElementById(“csv”).value.indexOf(“\n”, b);
if (a == -1) {
break;
}
strline[i] = document.getElementById(“csv”).value.substr(b,a-b);

The line is then searched for the first occurrence of a comma and another array str1[] is populated by a substring of the line:
c = strline[i].indexOf(“,”);
str1[i] = strline[i].substr(0,c);

The next comma is then found and two arrays are populated, strrem[], which is the remainder of the line and str2[], which will be matched with str1[]:
d = strline[i].indexOf (“,”, c + 1);
strrem[i] = strline[i].substr (c+ 1, strline[i].length – c – 1);
str2[i] = strline[i].substr (c + 1, d – c – 1) ;
Additionally, a variable, cnt is incremented:
cnt ++

The file is then sorted by matching str1[] and str2[]:
for (var k = 1; k <= cnt; k ++) {
for (var l = 1; l <= cnt; l ++) {
if (str2[l] == str1[k]) {
var tmp = strrem[l];
var tmp2 = str2[l];
strrem[l] = strrem[k];
str2[l] = str2[k];
strrem[k] = tmp;
str2[k] = tmp2;
}
}
}

Finally, the csv is reassembled, inserted into the textarea and the text of the textarea highlighted so it can be inserted into the spreadsheet:
document.getElementById("csv").value = "";
for (var i = 1; i <= cnt; i ++) {
if (str1[i] != " ") document.getElementById("csv").value += str1[i] + "," + strrem[i] + "\n";
}

document.getElementById("csv").focus();
document.getElementById("csv").select();

document.exec('copy'); automatically copies any selected text on the page

In the javascript code I had to use less= because WordPress would not accept either < or the substitute for <

HTML Base Converter


There are many bases other than 10 used. Some of the more common are 2 and 16, used with computers and scientific or exponential notation, used by numerous sciences. This cross-platform app allows the conversion between bases from 2 to 36 to other bases and to and from scientific notation.

Here is the interface:

Click Image for larger view

conversion-interface

Here is a conversion from base 16 to scientific notation:

Click Image for larger view

16-e_conversion
and here is a conversion from scientific notation to base 16:

Click Image for larger view

e-16conv

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>Base Converter</title>
<style type=’text/css’>
body {margin-left:0;margin-right:0;font:normal normal normal 12px Arial; background: #fffacc}
a{ text-decoration: }
:link { color: rgb(0, 0, 255) }
:visited {color :rgb(100, 0,100) }
:hover { }
:active { }
input{font:normal normal normal 12pt Arial; text-align: center;}
#t1{width: 22%}
#res{width: 100%; font-size: 15pt}
</style>
</head>
<body>
<input type=”text” id=”t1″ name=”t1″ value =”number or number + e + exponent” ondblclick=’document.getElementById(“t1”).value = “”;’ /> <input type=”text” id=”t2″ name=”t2″ value=”from,2-36,e” ondblclick=’document.getElementById(“t2”).value = “”;’ /> <input type=”text” id=”t3″ name=”t3″ value=”to,2-36,e” ondblclick=’document.getElementById(“t3”).value = “”;’ /><br /><br />
<input type=”button” id=”b1″ name=”b1″ value=”convert” onclick=’convert();’ /><br /><br .>
<input type=”text” id=”res” name=”res” value =”” />

var no; var rmn;
function convert() {
if (document.getElementById(“t2”).value != “10” && document.getElementById(“t2″).value !=”e”) no = parseInt(document.getElementById(“t1”).value,document.getElementById(“t2”).value );

if (document.getElementById(“t1”).value.indexOf(“.”) != -1) {
var a = document.getElementById(“t1”).value.indexOf(“.”);
rmn = document.getElementById(“t1”).value.substr(a+1,2 );
rmn = parseInt(rmn, document.getElementById(“t2”).value ) * (10/document.getElementById(“t2”).value);
no += rmn/10;
}

if (document.getElementById(“t2”).value == “e”) {
var a = document.getElementById(“t1”).value.indexOf(“e”);
var l = document.getElementById(“t1”).value.substr(0,a);
var m = parseInt(document.getElementById(“t1”).value.substr(a+1));
m = Math.pow(10,m);
no = l*m;
if (Math.abs(no – 255) 10000000) document.getElementById(“res”).value = no.toExponential();
if(document.getElementById(“t3”).value == “e”) document.getElementById(“res”).value = no.toExponential();
}

</body></html>


there are three types of numbers to consider; 10, bases other than 10 and exponential, all saved in the variable no.
base 10:
from
if (document.getElementById(“t2”).value == “10”) no = parseFloat(document.getElementById(“t1”).value);

to
if(document.getElementById(“t3”).value == “10”) document.getElementById(“res”).value = no.toString();
I also converted base 10 code greater than 10000000 to scientific, to make it easier to read
if(document.getElementById(“t3”).value == “10” && no > 10000000) document.getElementById(“res”).value = no.toExponential();

other base:
from
if (document.getElementById(“t2”).value != “10” && document.getElementById(“t2″).value !=”e”) no = parseInt(document.getElementById(“t1”).value,document.getElementById(“t2”).value );

if (document.getElementById(“t1”).value.indexOf(“.”) != -1) {
var a = document.getElementById(“t1”).value.indexOf(“.”);
rmn = document.getElementById(“t1”).value.substr(a+1,2 );
rmn = parseInt(rmn, document.getElementById(“t2”).value ) * (10/document.getElementById(“t2”).value);
no += rmn/10;
}
There is special code necessary to handle decimals in bases other than 10.

to
if (document.getElementById(“t3”).value != “10” && document.getElementById(“t3″).value !=”e”) document.getElementById(“res”).value = no.toString(document.getElementById(“t3”).value);

e
from
if (document.getElementById(“t2”).value == “e”) {
var a = document.getElementById(“t1”).value.indexOf(“e”);
var l = document.getElementById(“t1”).value.substr(0,a);
var m = parseInt(document.getElementById(“t1”).value.substr(a+1));
m = Math.pow(10,m);
no = l*m;
if (Math.abs(no – 255) < .0000001) no = 255;
}
the number is parsed to get the exponent as m and everything else as l, 10 is raised to the power of the exponent and multiplied by l
The last line is to correct a rounding error.

to
if(document.getElementById(“t3”).value == “e”) document.getElementById(“res”).value = no.toExponential();

A caveat: there is an error in the conversion from a number with a fraction in a base other than 10 if more than one decimal place is used. Here is an example of a coversion from a number with a fraction in base 16:

Click Image for larger view

16frac210

There is not this problem in converting from a number in base 10:

Click Image for larger view

10frac2-16

Something Completely Different: Curing Cancers With a Combination of Diet Modification and Chemotherapy

Writing computer code is something I picked up on my own, largely after my retirement. Occupationally, I was a cancer researcher.

A biochemical defect in most cancer cells, called Methionine Dependence, can be exploited to make them susceptible to non-toxic doses of specific chemotherapeutic agents.

Methionine is an essential amino acid, so it must be in the diet. If a diet is made totally free of Methionine, but an amino acid known as Homocysteine is supplied, together with the vitamins Folic Acid and B12, normal cells can salvage the Methionine.

Most cancer cells, however, cannot and their growth is arrested. The way it is arrested makes them highly susceptible to chemotherapy and they can be eliminated at doses that leave normal cells untouched.

This post will show a couple of examples of selectively eliminating cancer cells co-cultured with normal cells.

The first image shows the original culture; The normal cells are elongated while the cancer cells are compact:

Click Image for larger view

3a

The second image shows the same plate after some days. The cancer cells are gone while the normal cells are growing well:

Click Image for larger view

3b

The third image shows the plate, still later. The cancer cells are still gone while the normal cells have completely filled the plate:

Click Image for larger view

3c

The fourth image is the same plate with a stain used to make it more visible:

Click Image for larger view

3d

The fifth image shows a control in which no treatment was performed. The plate is complely overrun with cancer cells:

Click Image for larger view

3e

The sixth image shows a partial treatment. The cancer cells appear as colonies on a base of the normal cells:

Click Image for larger view

3f

The next three images show a breast cancer treated in the same manner. The first is the control, with no treatment:

Click Image for larger view

4a

The second is a partial treatment:

Click Image for larger view

4b
The third is a full treatment. Again. the plate is filled with normal cells and cancer cells are completely absent.

Click Image for larger view

4c

The entire treatment takes ten days, after which the cancer is completely gone.

A HTML Prime Number Generator


Prime numbers are integers that are indivisible and their discovery has often been of interest to mathematicians.

The brute force method would be to take a number and see if can be evenly divided by a smaller number. Since there can be many prime numbers this would be a slow process for large primes. The coding is relatively simple, so this post will focus on the logic needed to speed the process.

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>Prime</title>
<style>
body {margin-left:0;margin-right:0;font:normal normal normal 15pt Arial;}
a{ text-decoration: }:link { color: rgb(0, 0, 255) }
:visited {color :rgb(100, 0,100) }
:hover { }
:active { }
textarea{position: absolute; left: 0; top: 0; width: 100%; height: 100%; padding 5px}
</style>
</head>
<body>
<textarea id=”ta1″ name=”ta1 ” rows=” ” cols=” “></textarea>

prime = new Array(); var str = “2 “; var up; var typ; var k;
var ipt = prompt(“Type & Val, a for all primes, b for highest + Upper Val”, “”);
typ = ipt.substr(0,1);
up = ipt.substr(1);

for (var i=3; i
</body></html>

First, I ignored the trivial value of 1.

2 is the only even prime, since all other even numbers are divisible by 2. I therefore ignored even numbers and created a string variable with the value “2 “:
var str = “2 “;

The calculation of odd primes was done by nested loops.

The outer loop was initiated at 3 and limited at a value chosen from a prompt. A boolean Array prime[] had been initiated and its value for the current index set to true:
for (var i=3; i <= up;i += 2) {
prime[i] = true;

The inner loop was also initiated at 3. Since no odd number is evenly divisible by an even number, only add numbers had to be considered,

Since no integer is divisible by an integer more than half its value, the inner loop was limited at i/2 – 1.
for (var j=3; j <= i /2 – 1; j += 2 ) {

Modular division was used as a test. If i % j = 0, i is divisible by j.

Using 13 as an example: Since there is no way that 13 could be divided by 7 or higher, only 3 and 5 need to be considered, thus shortening the number of calculations needed to find any prime.

Finally I shall use 15 as an example: 15 is divisible by both 3 and 5, but once it can be divided by 3, it is not a prime and it is not necessary to test its division by 5, again shortening the number of calculations. prime[3] is therefore set to false:
if (i % j == 0 ) {
prime[i] = false;
break;
}

There are two ways to display the results, a choice of a list of all primes or only the highest prime up to the set limit. The prompt is entered as either a or b followed by the limit, eg:
a1000 b2500, etc.

The prompt value is parsed into two variables:
var ipt = prompt(“Type & Val, a for all primes, b for highest + Upper Val”, “”);
typ = ipt.substr(0,1);
up = ipt.substr(1);

The string variable str is then altered, depending on whether a or b was chosen: Only integers in which prime[i] is true are included:
for (var i = 3; i <= up; i ++) {
if (prime[i]) {
if (typ == “a”) {
str += i.toString() + ” “;
} else {
str = i.toString();
}
}
}

Finally, the value of a textarea is set to str:
document.getElementById(“ta1”).value = str;

Even with the shortcuts described, there are many calculations that need to be made. For relatively small integers, the result can be displayed almost instantly, for higher integers it takes a little longer. On a not very fast laptop, I was able to display all primes up to 1000000 in about 1 1/2 minutes: it would undoubtably be faster for a faster computer.

Here is a list of some prime numbers:

Click Image for larger view