Javascript Issues

Snitz™ Forums 2000
https://forum.snitz.com/forumTopic/Posts/71245?pagenum=1
04 November 2025, 15:15

Topic


Carefree
Javascript Issues
18 November 2017, 00:40


From "source.asp" comes the following ... for some reason, the Select All no longer functions; I'm sure I have overlooked something that SHOULD be obvious.
Code:

<%
'#################################################################################
'## Snitz Forums 2000 v3.4.07
'#################################################################################
'## Copyright (C) 2000-17 Michael Anderson, Pierre Gorissen,
'## Huw Reddick and Richard Kinser
'##
'## This program is free software; you can redistribute and/or modify it under the
'## terms of the GNU General Public License as published by the Free Software
'## Foundation; version 2 or later of the License. '##
'## All copyright notices regarding Snitz Forums 2000 must remain intact in the
'## scripts and in the HTML output. The "powered by" text/logo with a link back
'## to http://forum.snitz.com in the footer of the pages MUST remain visible when
'## the pages are viewed on the internet or intranet. '##
'## This program is distributed in the hope that it will be useful, but WITHOUT ANY
'## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
'## PARTICULAR PURPOSE. See the GNU General Public License for more details. '##
'## You should have received a copy of the GNU General Public License with this
'## program; if not, write to:
'##
'## Free Software Foundation, Inc. '## 59 Temple Place - Suite 330
'## Boston, MA 02111-1307, USA
'##
'## Support can be obtained from our support forums at: http://forum.snitz.com
'##
'## Correspondence and marketing questions can be sent to: manderson@snitz.com
'##
'#################################################################################
%>
<!--#INCLUDE FILE="config.asp"-->
<%
Response.Buffer = True
Err.Clear
%>
<!--#INCLUDE FILE="includes/inc_sha256.asp" -->
<!--#INCLUDE FILE="includes/inc_header.asp" -->
<!--#INCLUDE FILE="includes/inc_func_secure.asp" -->
<%
Call ModCheck(intMod136)
If mLev < intSourceLev Then Response.Redirect "default.asp"
On Error Resume Next
Response.Write "<center><table border=""0"" width=""100%"">" & vbNewLine & _
" <tr>" & vbNewLine & _
" <td width=""33%"" align=""left"" nowrap><font face=""" & strDefaultFontface & """ size=""" & strDefaultFontSize & """>" & vbNewLine & _
" " & getCurrentIcon(strIconFolderOpen,"","align=""absmiddle""") & " <a href=""default.asp"">All Forums</a><br />" & vbNewLine & _
" " & getCurrentIcon(strIconBar,"","align=""absmiddle""") & getCurrentIcon(strIconFolderOpenTopic,"","align=""absmiddle""") & " Source Code Lister<br /></font></td>" & vbNewLine & _
" </tr>" & vbNewLine & _
"</table>" & vbNewLine & _
"<br />" & vbNewLine & _
"<table border=""0"" cellspacing=""0"" cellpadding=""5"" bgcolor=""transparent"" width=""1000"">" & vbNewLine & _
" <tr>" & vbNewLine & _
" <td class=""sidebar"">" & vbNewLine & _
" </td><td width="""" valign=""top"" align=""left"" rowspan=""2"" nowrap>" & _
" <table class=""tbl"" bgcolor=""" & strPopupTableColor & """ border=""1"" width=""100%"" cellspacing=""0"" cellpadding=""4"" align=""center"">" & vbNewLine & _
" <tr>" & vbNewLine & _
" <td>" & vbNewLine & _
" <table border=""0"" width=""100%"" cellspacing=""1"" cellpadding=""2"">" & vbNewLine & _
" <tr>" & vbNewLine & _
" <td colspan=""2"">" & vbNewLine
strDirPath = Server.MapPath("./")
strPageRequested = LCase(Request.QueryString("page"))
strShowLines = LCase(Request.QueryString("lines"))
If strShowLines <> "no" Then strShowLines = "yes"
strSql = "SELECT COUNT(*) AS CNT FROM " & strTablePrefix & "SOURCE"
Set rsSource = my_Conn.Execute(strSql)
If Not rsSource.EOF Then
intSCount = rsSource("CNT")
rsSource.Close
End If
Set rsSource = Nothing
strSql = "SELECT * FROM " & strTablePrefix & "SOURCE ORDER BY FILE_MATCHING ASC, FILE_NAME ASC"
Set rsSource = my_Conn.Execute(strSql)
If Not rsSource.EOF Then
rsSource.MoveFirst
intI = 0
Do While Not rsSource.EOF
intI = intI + 1
DoNotShare(intI,0) = rsSource("File_Name")
DoNotShare(intI,1) = rsSource("File_Matching")
If rsSource("File_Allowed") = 0 And rsSource("FILE_ENABLE") = 1 Then
DoNotShare(intI,2) = rsSource("FILE_ENABLE")
Else
DoNotShare(intI,2) = rsSource("File_Allowed")
End If
rsSource.MoveNext
Loop
rsSource.Close
End If
Set rsSource = Nothing
If Len(strPageRequested) > 0 Then
If barFile(strPageRequested) = True Then
noshare(1)
Else
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(Server.MapPath(strPageRequested)) = True Then
doshare()
Else
noshare(2)
End If
End If
Else
noshare(3)
End If
Response.Write " </td>" & vbNewLine & _
" </tr>" & vbNewLine & _
" </table>" & vbNewLine & _
" </td>" & vbNewLine & _
" </tr>" & vbNewLine & _
" </table>" & vbNewLine & _
" </td>" & vbNewLine & _
" </tr>" & vbNewLine & _
"</table>" & vbNewLine
WriteFooter
Response.End

Function barFile(ckFile)
barFile = False
If intSCount > 0 Then
For n = 1 To intSCount
If DoNotShare(n,1) = "Match" Then
If ckFile = DoNotShare(n,0) And (DoNotShare(n,2) = 0) Then
barFile = True
Exit Function
End If
Else
if InStr(LCase(ckFile), LCase(DoNotShare(n,0))) > 0 And (DoNotShare(n,2) = 0) Then
barFile = True
Exit Function
End If
End If
Next
End If
End Function

Sub noshare(n)
Select Case n
Case 1
Response.Write "<span class=""dft"">Sorry, but the file ""<b><i>" & strPageRequested & "</i></b>"" is not available for viewing.<br /></span>" & vbNewline
Case 2
Response.Write "<span class=""dft"">Sorry, but the file ""<b><i>" & strPageRequested & "</i></b>"" does not exist.</span><br />" & vbNewline
Case Else
Response.Write "<span class=""dft"">What?</span><br />" & vbNewline
End Select
SelectPageMenu()
End Sub

Sub doshare()
Dim read_all, read_lines, i, j, k, fso, act, numLines
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FileExists(Server.MapPath(strPageRequested)) Then
Set act = FSO.OpenTextFile(Server.MapPath(strPageRequested), 1)
read_asp = act.readall
numLines = act.Line
act.Close
Response.write "<span>" & vbNewLine & _
" <span>Viewing <b><i>" & strPageRequested & "</i></b></span>" & vbNewline & _
" <span><font size=""1"">(~" & numLines & " lines)</font></span><br />" & vbNewline
Call SelectPageMenu()
Response.Write " <div id=""center"">" & vbNewline & _
" <div id=""scrollcode"">" & vbNewline
If strShowLines = "yes" Then
Response.Write " <div style=""position:absolute; left: 0; top: 0; width: 50px; background: #F0F0F0;"">" & vbNewLine & _
" <pre style=""font-size:12px;"">" & vbNewline
For i = 1 To numLines
Response.Write Server.HTMLEncode(Right(" " & FormatNumber(i,0,,,0),5)) & vbNewLine
Next
Response.Write " </pre>" & vbNewLine & _
" </div>" & vbNewline
End If
Response.Write " <div id=""srcarea"" style=""position:absolute; left: 50px; top: 0; background: #FFFFE1; "">" & vbNewline & _
" <pre style=""font-size:12px; font-family:lucida console;"">" & Server.HTMLEncode(read_asp) & "</pre>" & vbNewline & _
" </div>" & vbNewline & _
" </div>" & vbNewline & _
" </div>" & vbNewline & _
" <form name=""selectall"">" & vbNewLine & _
" <textarea id=""holdtext"" wrap=""off"" style=""display:none;"">" & Server.HTMLEncode(read_asp) & "</textarea>" & vbNewLine & _
" <input class=""btn"" type=""button"" value=""Select / Copy Code"" onclick=""javascript:window.selectNode(document.getElementById('srcarea'));Copied = document.getElementById('holdtext').createTextRange();Copied.execCommand('Copy');"" />" & vbNewLine
strUAgent = Request.ServerVariables("HTTP_USER_AGENT") : strOKB = ""
For i = 1 To Len(strUAgent)
If UCase(Mid(strUAgent, i, 4)) = "MSIE" Or UCase(Mid(strUAgent, i, 5)) = "TOUCH" Then
strOKB = "IE"
Exit For
End If
Next
If strOKB <> "IE" Then
Response.Write "<br /><br /><span>(<B>NOTE</B>: IE will copy to clipboard but other browsers may only select the contents.<br />            To ensure copy, use CTRL-C after clicking.)</span>"
End If
Response.Write "</form>" & vbNewLine & _
"</span>" & vbNewLine
Else
noshare(2)
End If
End Sub


Sub SelectPageMenu()
Response.Write "<span class=""dft""><font size=""1"">Select "
If strPageRequested="" Then Response.Write "a "
If strPageRequested<>"" Then Response.Write "another "
Response.Write "page to view." & vbNewline & _
"<FORM name=""zFileForm"">" & vbNewline & _
"Line Numbers: " & vbNewline & _
"<input type=""radio"" name=""zShowLines"" value=""yes"""
If strShowLines <> "no" Then Response.Write " checked"
Response.Write " onClick=""change()"" />Yes " & vbNewline & _
"<input type=""radio"" name=""zShowLines"" value=""no"""
If strShowLines = "no" Then Response.Write " checked"
Response.Write " onClick=""change()"" />No</font> " & vbNewline
Response.Write "<SELECT name=""zFileName"">" & vbNewline
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(strDirPath)
Set colFiles = objFolder.Files
numFilesFound = objFolder.Files.Count
numMaxFiles = 0
numThisFile = 0
If numFilesFound > 0 Then
For Each objItem In colFiles
Set objFile = objFSO.GetFile(objItem)
filename = Trim(LCase(Right(objItem.Name,Len(objItem.Name) - InStrRev(objItem.Name, "\"))))
If barFile(objFile.Name) = False Then
numMaxFiles = numMaxFiles + 1
ReDim Preserve srcFileArray(numMaxFiles)
srcFileArray(numMaxFiles - 1) = objFile.Name
End If
Next
End If
strSql = "SELECT SUBFOLDER FROM " & strTablePrefix & "SOURCE_FOLDERS"
Set rsSource = my_Conn.Execute(strSql)
If Not rsSource.EOF Then
rsSource.MoveFirst
Do While Not rsSource.EOF
Set colFiles = Nothing
Set objFolder = Nothing
strSubF = strDirPath & "\" & rsSource("SUBFOLDER")
Set objFolder = objFSO.GetFolder(strDirPath & "\" & rsSource("SUBFOLDER"))
Set colFiles = objFolder.Files
numFilesFound = objFolder.Files.Count
If numFilesFound > 0 Then
For Each filename In colFiles
Response.Flush
filename = Trim(LCase(Right(filename,Len(filename) - InStrRev(filename, "\"))))
If barFile(filename) = False Then
numMaxFiles = numMaxFiles + 1
ReDim Preserve srcFileArray(numMaxFiles)
srcFileArray(numMaxFiles - 1) = rsSource("SUBFOLDER") & "/" & filename
End If
Next
End If
rsSource.MoveNext
Loop
rsSource.Close
End If
Set rsSource = Nothing
Set colFiles = Nothing
Set objFolder = Nothing
Set objFSO = Nothing
If numMaxFiles > 0 Then
Call QuickSort(srcFileArray,0,numMaxFiles)
For Each item In srcFileArray
If Len(item) > 0 Then
Response.Write "<option value=""" & item & """"
If strPageRequested = item Then Response.Write " SELECTED"
Response.Write ">" & item & "</option>" & vbNewline
End If
Next
End If
Response.Write "</SELECT>" & vbNewline & _
"<INPUT class=""btn"" TYPE=""button"" VALUE=""View source"" onClick=""change()"" />" & vbNewline & _
" <font size=""1"">(" & numMaxFiles & " Files Found)</font>" & vbNewline & _
"</FORM></font></span>" & vbNewline & _
"<script language=""Javascript"">" & vbNewline & _
"<!--" & vbNewline & _
"function change() {" & vbNewline & _
" if (document.zFileForm.zShowLines[0].checked) {" & vbNewline & _
" window.location = 'source.asp?page='+document.zFileForm.zFileName.options[document.zFileForm.zFileName.selectedIndex].value+'&lines=yes'" & vbNewline & _
" } else {" & vbNewline & _
" window.location = 'source.asp?page='+document.zFileForm.zFileName.options[document.zFileForm.zFileName.selectedIndex].value+'&lines=no'" & vbNewline & _
" }" & vbNewline & _
"}" & vbNewline & _
"//-->" & vbNewline & _
"</script>" & vbNewline
End Sub

Sub QuickSort(vec,loBound,hiBound)
Dim pivot,loSwap,hiSwap,temp
If hiBound - loBound = 1 Then
If vec(loBound) > vec(hiBound) Then
temp=vec(loBound)
vec(loBound) = vec(hiBound)
vec(hiBound) = temp
End If
End If
pivot = vec(Int((loBound + hiBound) / 2))
vec(Int((loBound + hiBound) / 2)) = vec(loBound)
vec(loBound) = pivot
loSwap = loBound + 1
hiSwap = hiBound
Do
While loSwap < hiSwap And vec(loSwap) <= pivot
loSwap = loSwap + 1
Wend
While vec(hiSwap) > pivot
hiSwap = hiSwap - 1
Wend
If loSwap < hiSwap Then
temp = vec(loSwap)
vec(loSwap) = vec(hiSwap)
vec(hiSwap) = temp
End If
Loop While loSwap < hiSwap
vec(loBound) = vec(hiSwap)
vec(hiSwap) = pivot
If loBound < (hiSwap - 1) Then Call QuickSort(vec,loBound,hiSwap-1)
If hiSwap + 1 < hibound Then Call QuickSort(vec,hiSwap+1,hiBound)
End Sub

Sub ShowSubFolders(objFolder)
Set colFolders = objFolder.SubFolders
For Each objSubFolder In colFolders
strTitle = ""
If Not ((objSubFolder.Attributes And 4) Or (objSubFolder.Attributes And 2)) Then
Set colFiles = objSubFolder.Files
If InStr(1, objSubFolder.Name, strQuery, vbTextCompare) <> 0 Then
strTitle = Mid(objSubFolder,4)
strTitle = Replace(strTitle,"\","/") & "/"
strLink = strPath & strTitle
%>
<tr bgcolor="#CCFFCC">
<td width="70%" align="left" ><a href="<%= strLink %>"><%= objSubFolder.Name %></a></td>
<td width="10%" align="right"> </td>
<td width="20%" align="right" > </td>
</tr>
<%
End If
strTitle = Mid(objSubFolder,4)
strTitle = Replace(strTitle,"\","/") & "/"
For Each objItem In colFiles
strDate = CStr(objItem.DateCreated)
If Len(strDate) < 22 Then
If Mid(strDate,2,1) = "/" Then strDate = "0" & strDate
If Mid(strDate,4,1) = "/" Then strDate = Left(strDate,2) & "0" & Mid(strDate,3)
If Mid(strDate,13,1) = ":" Then strDate = Left(strDate,11) & "0" & Mid(strDate,12)
End If
If InStr(1, objItem.Name, strQuery, vbTextCompare) <> 0 Then
strLink = strPath & strTitle & objItem.Name
%>
<tr bgcolor="#CCFFCC">
<td width="70%" align="left" ><a href="<% = strLink %>"><%= objItem.Name %></a></td>
<td width="10%" align="right"><%= objItem.Size %></td>
<td width="20%" align="right" ><%= strDate %></td>
</tr>
<%
End If
Next
ShowSubFolders(objSubFolder)
End If
Next
End Sub

%>
<script>
function selectNode (node) {
var selection, range, doc, win;
if ((doc = node.ownerDocument) && (win = doc.defaultView) && typeof
win.getSelection != 'undefined' && typeof doc.createRange != 'undefined'
&& (selection = window.getSelection()) && typeof
selection.removeAllRanges != 'undefined') {
range = doc.createRange();
range.selectNode(node);
selection.removeAllRanges();
selection.addRange(range);
}
else if (document.body && typeof document.body.createTextRange !=
'undefined' && (range = document.body.createTextRange())) {
range.moveToElementText(node);
range.select();
}
}
</script>

This one is from a HTML5 canvas application. Everything works EXCEPT for saving a file (which makes it about as useless as the old TI-994A computer). The original instructions on the web did nothing when you clicked the save button because the author merged two functions. Now I just get a "server error" message with no details.
Code:

$(document).ready(function(){
getBase64FromImageUrl('myCanvas');

function getBase64FromImageUrl(URL) {
var img = new Image();
img.src = URL;
img.onload = function () {
var canvas = document.createElement("myCanvas");
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
var dataURL = canvas.toDataURL("image/png");
//alert( dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
saveImageData(dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
}
}
});

function saveImageData (image_data) {
$.post("saveImage.asp",
{imageData:image_data,submit:true})
.done(function(data, textStatus, jqXHR)
{
alert(data);
}).fail(function(jqXHR, textStatus, errorThrown)
{
alert(errorThrown);
});
};

var mousePressed = false;
var lastX, lastY;
var ctx;
var dataURL = rendered.Canvas.toDataURL("images/png");
dataURL = dataURL.replace('data:image/png;base64,', '');
var areturn = $.ajax({
url: "saveImage.asp",
type: "POST",
data: '{ "imageData" : "' + dataURL + '" }',
dataType: "json",
beforeSend: function(x) {
x.overrideMimeType("application/j-son;charset=UTF-8");
}
}).done(function(result) {
console.log("Success Done!\n" + result);
}).always(function(data) {
console.log("Always:\n" + data.responseText);
});

function InitThis() {
ctx = document.getElementById('myCanvas').getContext("2d");
//ctx.src = 'cat_b.jpg';
//ctx.drawImage(ctx, 0, 0);
var image = new Image();
image.src = 'template/Tooth18.jpg';
$(image).load(function () {
ctx.drawImage(image, 0, 0);
});

$('#myCanvas').mousedown(function (e) {
mousePressed = true;
Draw(e.pageX - $(this).offset().left, e.pageY - $(this).offset().top, false);
});

$('#myCanvas').mousemove(function (e) {
if (mousePressed) {
Draw(e.pageX - $(this).offset().left, e.pageY - $(this).offset().top, true);
}
});

$('#myCanvas').mouseup(function (e) {
mousePressed = false;
});
$('#myCanvas').mouseleave(function (e) {
mousePressed = false;
});
}

function Draw(x, y, isDown) {
if (isDown) {
ctx.beginPath();
ctx.strokeStyle = $('#selColor').val();
ctx.lineWidth = $('#selWidth').val();
ctx.lineJoin = "round";
ctx.moveTo(lastX, lastY);
ctx.lineTo(x, y);
ctx.closePath();
ctx.stroke();
}
lastX = x; lastY = y;
}

function clearArea() {
// Use the identity matrix while clearing the canvas
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}

 

Replies ...


HuwR
18 November 2017, 12:00


are you getting errors? Have you tried debugging the javascript in your browser?
Carefree
21 November 2017, 05:22


I replaced the canvas js. The new version has more functions, but does not support saving like this one. I will attach a copy later. No errors on new code, just lost a function I wanted.
As for the source lister, no errors .. just no result when button clicked.
HuwR
21 November 2017, 09:50


As for the source lister, no errors .. just no result when button clicked.
Have you tried in different browsers? Does it call the javascript function?
Carefree
29 November 2017, 23:25


Yeah, same result in all browsers. Javascript is called, just does nothing. No error reported.
At any rate, can live without the select all if I have to. Would like the canvas to save, though. If someone could write a working JS routine to send it as image to an asp file (like the previous one was SUPPOSED to have done), that would be ideal. Here's current canvas.js code:

Code:

/*
* Copyright (C) 2012 David Geary. This code is from the book
* Core HTML5 Canvas, published by Prentice-Hall in 2012. *
* License:
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software. *
* The Software may not be used to create training material of any sort,
* including courses, books, instructional videos, presentations, etc. * without the express written consent of David Geary. *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE. */

var iconCanvas = document.getElementById('iconCanvas'),
drawingCanvas = document.getElementById('drawingCanvas'),
drawingContext = drawingCanvas.getContext('2d'),
backgroundContext = document.createElement('canvas').getContext('2d'),
iconContext = iconCanvas.getContext('2d'),
strokeStyleSelect = document.getElementById('strokeStyleSelect'),
fillStyleSelect = document.getElementById('fillStyleSelect'),
lineWidthSelect = document.getElementById('lineWidthSelect'),
eraseAllButton = document.getElementById('eraseAllButton'),
snapshotButton = document.getElementById('snapshotButton'),
controls = document.getElementById('controls'),
curveInstructions = document.getElementById('curveInstructions'),
curveInstructionsOkayButton = document.getElementById('curveInstructionsOkayButton'),
curveInstructionsNoMoreButton = document.getElementById('curveInstructionsNoMoreButton'),

showCurveInstructions = true,

drawingSurfaceImageData,
rubberbandW,
rubberbandH,
rubberbandUlhc = {},

dragging = false,
mousedown = {},
lastRect = {},
lastX, lastY,

controlPoint = {},
editingCurve = false,
draggingControlPoint = false,
curveStart = {},
curveEnd = {},

doFill = false,
selectedRect = null,
selectedFunction,

editingText = false,
currentText,

CONTROL_POINT_RADIUS = 20,
CONTROL_POINT_FILL_STYLE = 'rgba(255,255,0,0.5)',
CONTROL_POINT_STROKE_STYLE = 'rgba(0, 0, 255, 0.8)',

RUBBERBAND_LINE_WIDTH = 1,
RUBBERBAND_STROKE_STYLE = 'green',

GRID_HORIZONTAL_SPACING = 10,
GRID_VERTICAL_SPACING = 10,
GRID_LINE_COLOR = 'rgb(0, 0, 200)',

ERASER_ICON_GRID_COLOR = 'rgb(0, 0, 200)',
ERASER_ICON_CIRCLE_COLOR = 'rgba(100, 140, 200, 0.5)',
ERASER_ICON_RADIUS = 20,

SLINKY_LINE_WIDTH = 1,
SLINKY_SHADOW_STYLE = 'rgba(0,0,0,0.2)',
SLINKY_SHADOW_OFFSET = -5,
SLINKY_SHADOW_BLUR = 20,
SLINKY_RADIUS = 60,

ERASER_LINE_WIDTH = 1,
ERASER_SHADOW_STYLE = 'blue',
ERASER_STROKE_STYLE = 'rgba(0,0,255,0.6)',
ERASER_SHADOW_OFFSET = -5,
ERASER_SHADOW_BLUR = 20,
ERASER_RADIUS = 40,

SHADOW_COLOR = 'rgba(0,0,0,0.7)',

ICON_BACKGROUND_STYLE = '#eeeeee',
ICON_BORDER_STROKE_STYLE = 'rgba(100, 140, 230, 0.5)',
ICON_STROKE_STYLE = 'rgb(100, 140, 230)',
ICON_FILL_STYLE = '#dddddd',

TEXT_ICON_FILL_STYLE = 'rgba(100, 140, 230, 0.5)',
TEXT_ICON_TEXT = 'T',

CIRCLE_ICON_RADIUS = 20,

ICON_RECTANGLES = [
{ x: 13.5, y: 18.5, w: 48, h: 48 },
{ x: 13.5, y: 78.5, w: 48, h: 48 },
{ x: 13.5, y: 138.5, w: 48, h: 48 },
{ x: 13.5, y: 198.5, w: 48, h: 48 },
{ x: 13.5, y: 258.5, w: 48, h: 48 },
{ x: 13.5, y: 318.5, w: 48, h: 48 },
{ x: 13.5, y: 378.5, w: 48, h: 48 },
{ x: 13.5, y: 438.5, w: 48, h: 48 },
{ x: 13.5, y: 508.5, w: 48, h: 48 }
],

LINE_ICON = 0,
RECTANGLE_ICON = 1,
CIRCLE_ICON = 2,
OPEN_PATH_ICON = 3,
CLOSED_PATH_ICON = 4,
CURVE_ICON = 5,
TEXT_ICON = 6,
SLINKY_ICON = 7,
ERASER_ICON = 8,

keyboard = new COREHTML5.Keyboard();

// Grid..........................................................
function drawGrid(context, color, stepx, stepy) {
context.save()

context.strokeStyle = color;
context.fillStyle = '#ffffff';
context.lineWidth = 0.5;
context.fillRect(0, 0, context.canvas.width, context.canvas.height);
context.globalAlpha = 0.1;

context.beginPath();
for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) {
context.moveTo(i, 0);
context.lineTo(i, context.canvas.height);
}
context.stroke();

context.beginPath();
for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) {
context.moveTo(0, i);
context.lineTo(context.canvas.width, i);
}
context.stroke();

context.restore();
}

// Icons.........................................................
function drawLineIcon(rect) {
iconContext.beginPath();
iconContext.moveTo(rect.x + 5, rect.y + 5);
iconContext.lineTo(rect.x + rect.w - 5, rect.y + rect.h - 5);
iconContext.stroke();
}

function drawRectIcon(rect) {
fillIconLowerRight(rect);
iconContext.strokeRect(rect.x + 5, rect.y + 5,
rect.w - 10, rect.h - 10);
}

function drawCircleIcon(rect) {
var startAngle = 3*Math.PI/4,
endAngle = 7*Math.PI/4,
center = {x: rect.x + rect.w/2, y: rect.y + rect.h/2 };

fillIconLowerRight(rect);

iconContext.beginPath();
iconContext.arc(rect.x + rect.w/2, rect.y + rect.h/2,
CIRCLE_ICON_RADIUS, 0, Math.PI*2, false);
iconContext.stroke();
}

function drawOpenPathIcon(rect) {
iconContext.beginPath();
drawOpenPathIconLines(rect);
iconContext.stroke();
}

function drawClosedPathIcon(rect) {
fillIconLowerRight(rect);
iconContext.beginPath();
drawOpenPathIconLines(rect);
iconContext.closePath();
iconContext.stroke();
}

function drawCurveIcon(rect) {
fillIconLowerRight(rect);
iconContext.beginPath();
iconContext.beginPath();
iconContext.moveTo(rect.x + rect.w - 10, rect.y + 5);
iconContext.quadraticCurveTo(rect.x - 10, rect.y,
rect.x + rect.w - 10,
rect.y + rect.h - 5);
iconContext.stroke();
}

function drawTextIcon(rect) {
var text = TEXT_ICON_TEXT;

fillIconLowerRight(rect);
iconContext.fillStyle = TEXT_ICON_FILL_STYLE;
iconContext.fillText(text, rect.x + rect.w/2,
rect.y + rect.h/2 + 5);
iconContext.strokeText(text, rect.x + rect.w/2,
rect.y + rect.h/2 + 5);
}

function drawSlinkyIcon(rect) {
var x, y;

fillIconLowerRight(rect);

iconContext.save();
iconContext.strokeStyle = 'rgba(100, 140, 230, 0.6)';

for (var i=-2; i < rect.w/3 + 2; i+=1.5) {
if (i < rect.w/6) x = rect.x + rect.w/3 + i + rect.w/8;
else x = rect.x + rect.w/3 + (rect.w/3 - i) + rect.w/8;

y = rect.y + rect.w/3 + i;

iconContext.beginPath();
iconContext.arc(x, y, 12, 0, Math.PI*2, false);
iconContext.stroke();
}
iconContext.restore();
}

function drawEraserIcon(rect) {
var rect = ICON_RECTANGLES[ERASER_ICON];
iconContext.save();

iconContext.beginPath();
iconContext.arc(rect.x + rect.w/2,
rect.y + rect.h/2,
ERASER_ICON_RADIUS, 0, Math.PI*2, false);

iconContext.strokeStyle = ERASER_ICON_CIRCLE_COLOR;
iconContext.stroke();

iconContext.clip(); // restrict drawGrid() to the circle

drawGrid(iconContext, ERASER_ICON_GRID_COLOR, 5, 5);

iconContext.restore();
}

function drawIcon(rect) {
iconContext.save();

iconContext.strokeStyle = ICON_BORDER_STROKE_STYLE;
iconContext.strokeRect(rect.x, rect.y, rect.w, rect.h);
iconContext.strokeStyle = ICON_STROKE_STYLE;

if (rect.y === ICON_RECTANGLES[LINE_ICON].y) drawLineIcon(rect);
else if (rect.y === ICON_RECTANGLES[RECTANGLE_ICON].y) drawRectIcon(rect);
else if (rect.y === ICON_RECTANGLES[CIRCLE_ICON].y) drawCircleIcon(rect);
else if (rect.y === ICON_RECTANGLES[OPEN_PATH_ICON].y) drawOpenPathIcon(rect);
else if (rect.y === ICON_RECTANGLES[CLOSED_PATH_ICON].y) drawClosedPathIcon(rect, 20);
else if (rect.y === ICON_RECTANGLES[TEXT_ICON].y) drawTextIcon(rect);
else if (rect.y === ICON_RECTANGLES[CURVE_ICON].y) drawCurveIcon(rect);
else if (rect.y === ICON_RECTANGLES[ERASER_ICON].y) drawEraserIcon(rect);
else if (rect.y === ICON_RECTANGLES[SLINKY_ICON].y) drawSlinkyIcon(rect);

iconContext.restore();
}

function drawIcons() {
iconContext.clearRect(0,0, iconCanvas.width,
iconCanvas.height);

ICON_RECTANGLES.forEach(function(rect) {
iconContext.save();

if (selectedRect === rect) setSelectedIconShadow();
else setIconShadow();

iconContext.fillStyle = ICON_BACKGROUND_STYLE;
iconContext.fillRect(rect.x, rect.y, rect.w, rect.h);

iconContext.restore();

drawIcon(rect);
});
}

function drawOpenPathIconLines(rect) {
iconContext.lineTo(rect.x + 13, rect.y + 19);
iconContext.lineTo(rect.x + 15, rect.y + 17);
iconContext.lineTo(rect.x + 25, rect.y + 12);
iconContext.lineTo(rect.x + 35, rect.y + 13);
iconContext.lineTo(rect.x + 38, rect.y + 15);
iconContext.lineTo(rect.x + 40, rect.y + 17);
iconContext.lineTo(rect.x + 39, rect.y + 23);
iconContext.lineTo(rect.x + 36, rect.y + 25);
iconContext.lineTo(rect.x + 32, rect.y + 27);
iconContext.lineTo(rect.x + 28, rect.y + 29);
iconContext.lineTo(rect.x + 26, rect.y + 31);
iconContext.lineTo(rect.x + 24, rect.y + 33);
iconContext.lineTo(rect.x + 22, rect.y + 35);
iconContext.lineTo(rect.x + 20, rect.y + 37);
iconContext.lineTo(rect.x + 18, rect.y + 39);
iconContext.lineTo(rect.x + 16, rect.y + 39);
iconContext.lineTo(rect.x + 13, rect.y + 36);
iconContext.lineTo(rect.x + 11, rect.y + 34);
}

function fillIconLowerRight(rect) {
iconContext.beginPath();
iconContext.moveTo(rect.x + rect.w, rect.y);
iconContext.lineTo(rect.x + rect.w, rect.y + rect.h);
iconContext.lineTo(rect.x, rect.y + rect.h);
iconContext.closePath();
iconContext.fill();
}

function isPointInIconLowerRight(rect, x, y) {
iconContext.beginPath();
iconContext.moveTo(rect.x + rect.w, rect.y);
iconContext.lineTo(rect.x + rect.w, rect.y + rect.h);
iconContext.lineTo(rect.x, rect.y + rect.h);

return iconContext.isPointInPath(x, y);
}

function getIconFunction(rect, loc) {
var action;

if (rect.y === ICON_RECTANGLES[LINE_ICON].y) action = 'line';
else if (rect.y === ICON_RECTANGLES[RECTANGLE_ICON].y) action = 'rectangle';
else if (rect.y === ICON_RECTANGLES[CIRCLE_ICON].y) action = 'circle';
else if (rect.y === ICON_RECTANGLES[OPEN_PATH_ICON].y) action = 'path';
else if (rect.y === ICON_RECTANGLES[CLOSED_PATH_ICON].y) action = 'pathClosed';
else if (rect.y === ICON_RECTANGLES[CURVE_ICON].y) action = 'curve';
else if (rect.y === ICON_RECTANGLES[TEXT_ICON].y) action = 'text';
else if (rect.y === ICON_RECTANGLES[SLINKY_ICON].y) action = 'slinky';
else if (rect.y === ICON_RECTANGLES[ERASER_ICON].y) action = 'erase';

if (action === 'rectangle' || action === 'circle' ||
action === 'pathClosed' || action === 'text' ||
action === 'curve' || action === 'slinky') {
doFill = isPointInIconLowerRight(rect, loc.x, loc.y);
}

return action;
}

function setIconShadow() {
iconContext.shadowColor = SHADOW_COLOR;
iconContext.shadowOffsetX = 1;
iconContext.shadowOffsetY = 1;
iconContext.shadowBlur = 2;
}

function setSelectedIconShadow() {
iconContext.shadowColor = SHADOW_COLOR;
iconContext.shadowOffsetX = 4;
iconContext.shadowOffsetY = 4;
iconContext.shadowBlur = 5;
}

function selectIcon(rect) {
selectedRect = rect;
drawIcons();
}

// Saving/Restoring the drawing surface..........................
function saveDrawingSurface() {
drawingSurfaceImageData = drawingContext.getImageData(0, 0,
drawingCanvas.width,
drawingCanvas.height);
}

function restoreDrawingSurface() {
drawingContext.putImageData(drawingSurfaceImageData, 0, 0);
}

// Rubberbands...................................................
function updateRubberbandRectangle(loc) {
rubberbandW = Math.abs(loc.x - mousedown.x);
rubberbandH = Math.abs(loc.y - mousedown.y);

if (loc.x > mousedown.x) rubberbandUlhc.x = mousedown.x;
else rubberbandUlhc.x = loc.x;

if (loc.y > mousedown.y) rubberbandUlhc.y = mousedown.y;
else rubberbandUlhc.y = loc.y;
}

function drawRubberbandRectangle() {
drawingContext.strokeRect(rubberbandUlhc.x,
rubberbandUlhc.y,
rubberbandW, rubberbandH);
}

function drawRubberbandLine(loc) {
drawingContext.beginPath();
drawingContext.moveTo(mousedown.x, mousedown.y);
drawingContext.lineTo(loc.x, loc.y);
drawingContext.stroke();
}

function drawRubberbandCircle(loc) {
var angle = Math.atan(rubberbandH/rubberbandW);
var radius = rubberbandH / Math.sin(angle);

if (mousedown.y === loc.y) {
radius = Math.abs(loc.x - mousedown.x);
}

drawingContext.beginPath();
drawingContext.arc(mousedown.x, mousedown.y, radius, 0, Math.PI*2, false);
drawingContext.stroke();
}

function drawRubberband(loc) {
drawingContext.save();

drawingContext.strokeStyle = RUBBERBAND_STROKE_STYLE;
drawingContext.lineWidth = RUBBERBAND_LINE_WIDTH;

if (selectedFunction === 'rectangle') {
drawRubberbandRectangle();
}
else if (selectedFunction === 'line' ||
selectedFunction === 'curve') {
drawRubberbandLine(loc);
}
else if (selectedFunction === 'circle') {
drawRubberbandCircle(loc);
}

drawingContext.restore();
}

// Eraser........................................................
function setPathForEraser() {
drawingContext.beginPath();
drawingContext.moveTo(lastX, lastY);
drawingContext.arc(lastX, lastY,
ERASER_RADIUS + ERASER_LINE_WIDTH,
0, Math.PI*2, false);
}

function setSlinkyAttributes() {
drawingContext.lineWidth = lineWidthSelect.value;
drawingContext.shadowColor = strokeStyleSelect.value;
drawingContext.shadowOffsetX = SLINKY_SHADOW_OFFSET;
drawingContext.shadowOffsetY = SLINKY_SHADOW_OFFSET;
drawingContext.shadowBlur = SLINKY_SHADOW_BLUR;
drawingContext.strokeStyle = strokeStyleSelect.value;
}

function setEraserAttributes() {
drawingContext.lineWidth = ERASER_LINE_WIDTH;
drawingContext.shadowColor = ERASER_SHADOW_STYLE;
drawingContext.shadowOffsetX = ERASER_SHADOW_OFFSET;
drawingContext.shadowOffsetY = ERASER_SHADOW_OFFSET;
drawingContext.shadowBlur = ERASER_SHADOW_BLUR;
drawingContext.strokeStyle = ERASER_STROKE_STYLE;
}

function eraseLast() {
var x = lastX - ERASER_RADIUS-ERASER_LINE_WIDTH,
y = lastY - ERASER_RADIUS-ERASER_LINE_WIDTH,
w = ERASER_RADIUS*2+ERASER_LINE_WIDTH*2,
h = w,
cw = drawingContext.canvas.width,
ch = drawingContext.canvas.height;

drawingContext.save();

setPathForEraser();
drawingContext.clip();

if (x + w > cw) w = cw - x;
if (y + h > ch) h = ch - y;

if (x < 0) { x = 0; }
if (y < 0) { y = 0; }

drawingContext.drawImage(
backgroundContext.canvas, x, y, w, h, x, y, w, h);

drawingContext.restore();
}

function drawEraser(loc) {
drawingContext.save();
setEraserAttributes();

drawingContext.beginPath();
drawingContext.arc(loc.x, loc.y, ERASER_RADIUS,
0, Math.PI*2, false);
drawingContext.clip();
drawingContext.stroke();

drawingContext.restore();
}

function drawSlinky(loc) {
drawingContext.save();
setSlinkyAttributes();

drawingContext.beginPath();
drawingContext.arc(loc.x, loc.y, ERASER_RADIUS,
0, Math.PI*2, false);
drawingContext.clip();

drawingContext.strokeStyle = strokeStyleSelect.value;
drawingContext.stroke();

if (doFill) {
drawingContext.shadowColor = undefined;
drawingContext.shadowOffsetX = 0;
drawingContext.globalAlpha = 0.2;
drawingContext.fill();
}
drawingContext.restore();
}

// Finish drawing lines, circles, and rectangles.................
function finishDrawingLine(loc) {
drawingContext.beginPath();
drawingContext.moveTo(mousedown.x, mousedown.y);
drawingContext.lineTo(loc.x, loc.y);
drawingContext.stroke();
}

function finishDrawingCircle(loc) {
var angle = Math.atan(rubberbandH/rubberbandW),
radius = rubberbandH / Math.sin(angle);

if (mousedown.y === loc.y) {
radius = Math.abs(loc.x - mousedown.x);
}

drawingContext.beginPath();
drawingContext.arc(mousedown.x, mousedown.y,
radius, 0, Math.PI*2, false);

if (doFill) {
drawingContext.fill();
}

drawingContext.stroke();
}

function finishDrawingRectangle() {
if (rubberbandW > 0 && rubberbandH > 0) {
if (doFill) {
drawingContext.fillRect(rubberbandUlhc.x,
rubberbandUlhc.y,
rubberbandW, rubberbandH)
}
drawingContext.strokeRect(rubberbandUlhc.x,
rubberbandUlhc.y,
rubberbandW, rubberbandH);
}
}

// Drawing curves................................................
function drawControlPoint() {
drawingContext.save();

drawingContext.strokeStyle = CONTROL_POINT_STROKE_STYLE;
drawingContext.fillStyle = CONTROL_POINT_FILL_STYLE;
drawingContext.lineWidth = 1.0;

drawingContext.beginPath();
drawingContext.arc(controlPoint.x, controlPoint.y,
CONTROL_POINT_RADIUS, 0, Math.PI*2, false);
drawingContext.stroke();
drawingContext.fill();

drawingContext.restore();
}

function startEditingCurve(loc) {
if (loc.x != mousedown.x || loc.y != mousedown.y) {
drawingCanvas.style.cursor = 'pointer';

curveStart.x = mousedown.x;
curveStart.y = mousedown.y;

curveEnd.x = loc.x;
curveEnd.y = loc.y;

controlPoint.x = (curveStart.x + curveEnd.x)/2;
controlPoint.y = (curveStart.y + curveEnd.y)/2;

drawControlPoint();

editingCurve = true;

if (showCurveInstructions)
curveInstructions.style.display = 'inline';
}
}

function drawCurve() {
drawingContext.beginPath();
drawingContext.moveTo(curveStart.x, curveStart.y);
drawingContext.quadraticCurveTo(controlPoint.x, controlPoint.y,
curveEnd.x, curveEnd.y);
drawingContext.stroke();
}

function finishDrawingCurve() {
drawingCanvas.style.cursor = 'crosshair';
restoreDrawingSurface();
drawCurve();

if (doFill) {
drawingContext.fill();
}
}

// Guidewires....................................................
function drawHorizontalLine (y) {
drawingContext.beginPath();
drawingContext.moveTo(0, y+0.5);
drawingContext.lineTo(drawingCanvas.width, y+0.5);
drawingContext.stroke();
}

function drawVerticalLine (x) {
drawingContext.beginPath();
drawingContext.moveTo(x+0.5, 0);
drawingContext.lineTo(x+0.5, drawingCanvas.height);
drawingContext.stroke();
}

function drawGuidewires(x, y) {
drawingContext.save();
drawingContext.strokeStyle = 'rgba(0,0,230,0.4)';
drawingContext.lineWidth = 0.5;
drawVerticalLine(x);
drawHorizontalLine(y);
drawingContext.restore();
}

// Keyboard......................................................
function showKeyboard() {
var keyboardElement = document.getElementById('keyboard');

keyboardElement.style.height = '370px';
keyboardElement.style.top = '375px';
keyboardElement.style.border = 'thin inset rgba(0,0,0,0.5)';
keyboardElement.style.borderRadius = '20px';

keyboard.resize(1000, 368);
keyboard.translucent = mousedown.y > drawingCanvas.height/2;
keyboard.draw();
}

function hideKeyboard() {
var keyboardElement = document.getElementById('keyboard');

keyboardElement.style.height = '0px';
keyboardElement.style.top = '0px';
keyboardElement.style.border = '';
keyboardElement.style.borderRadius = '';

keyboard.resize(1000, 0);
}

// Event handling functions......................................
function windowToCanvas(canvas, x, y) {
var bbox = canvas.getBoundingClientRect();
return { x: x - bbox.left * (canvas.width / bbox.width),
y: y - bbox.top * (canvas.height / bbox.height)
};
}

function mouseDownOrTouchStartInControlCanvas(loc) {
if (editingText) {
editingText = false;
eraseTextCursor();
hideKeyboard();
}
else if (editingCurve) {
editingCurve = false;
restoreDrawingSurface();
}

ICON_RECTANGLES.forEach(function(rect) {
iconContext.beginPath();

iconContext.rect(rect.x, rect.y, rect.w, rect.h);
if (iconContext.isPointInPath(loc.x, loc.y)) {
selectIcon(rect, loc);
selectedFunction = getIconFunction(rect, loc);

if (selectedFunction === 'text') {
drawingCanvas.style.cursor = 'text';
}
else {
drawingCanvas.style.cursor = 'crosshair';
}
}
});
};

// Key event handlers............................................
function backspace() {
restoreDrawingSurface();
currentText = currentText.slice(0, -1);
eraseTextCursor();
};

function enter() {
finishDrawingText();
mousedown.y += drawingContext.measureText('W').width;
saveDrawingSurface();
startDrawingText();
};

function insert(key) {
currentText += key;
restoreDrawingSurface();
drawCurrentText();
drawTextCursor();
};

document.onkeydown = function (e) {
if (e.keyCode === 8) { // backspace
e.preventDefault();
backspace();
}
else if (e.keyCode === 13) { // enter
e.preventDefault();
enter();
}
}

document.onkeypress = function (e) {
var key = String.fromCharCode(e.which);

if (editingText && e.keyCode !== 8) {
e.preventDefault();
insert(key);
}
}

function eraseTextCursor() {
restoreDrawingSurface();
drawCurrentText();
}

function drawCurrentText() {
if (doFill)
drawingContext.fillText(currentText, mousedown.x, mousedown.y);

drawingContext.strokeText(currentText, mousedown.x, mousedown.y);
}

function drawTextCursor() {
var widthMetric = drawingContext.measureText(currentText),
heightMetric = drawingContext.measureText('W'),
cursorLoc = {
x: mousedown.x + widthMetric.width,
y: mousedown.y - heightMetric.width + 5
};

drawingContext.beginPath();
drawingContext.moveTo(cursorLoc.x, cursorLoc.y);
drawingContext.lineTo(cursorLoc.x, cursorLoc.y + heightMetric.width - 12);
drawingContext.stroke();
}

function startDrawingText() {
editingText = true;
currentText = '';
drawTextCursor();
showKeyboard();
}

function finishDrawingText() {
restoreDrawingSurface();
drawCurrentText();
}

function mouseDownOrTouchStartInDrawingCanvas(loc) {
dragging = true;

if (editingText) {
finishDrawingText();
}
else if (editingCurve) {
if (drawingContext.isPointInPath(loc.x, loc.y)) {
draggingControlPoint = true;
}
else {
restoreDrawingSurface();
}
editingCurve = false;
}

if (!draggingControlPoint) {
saveDrawingSurface();
mousedown.x = loc.x;
mousedown.y = loc.y;

if (selectedFunction === 'path' || selectedFunction === 'pathClosed') {
drawingContext.beginPath();
drawingContext.moveTo(loc.x, loc.y);
}
else if (selectedFunction === 'text') {
startDrawingText();
}
else {
editingText = false;
}

lastX = loc.x;
lastY = loc.y;
}
}

function moveControlPoint(loc) {
controlPoint.x = loc.x;
controlPoint.y = loc.y;
}

function mouseMoveOrTouchMoveInDrawingCanvas(loc) {
if (draggingControlPoint) {
restoreDrawingSurface();

moveControlPoint(loc);

drawingContext.save();

drawingContext.strokeStyle = RUBBERBAND_STROKE_STYLE;
drawingContext.lineWidth = RUBBERBAND_LINE_WIDTH;

drawCurve();
drawControlPoint();

drawingContext.restore();
}
else if (dragging) {
if (selectedFunction === 'erase') {
eraseLast();
drawEraser(loc);
}
else if (selectedFunction === 'slinky') {
drawSlinky(loc);
}
else if (selectedFunction === 'path' ||
selectedFunction === 'pathClosed') {
drawingContext.lineTo(loc.x, loc.y);
drawingContext.stroke();
}
else { // For lines, circles, rectangles, and curves, draw rubberbands
restoreDrawingSurface();
updateRubberbandRectangle(loc);
drawRubberband(loc);
}

lastX = loc.x;
lastY = loc.y;

lastRect.w = rubberbandW;
lastRect.h = rubberbandH;
}

if (dragging || draggingControlPoint) {
if (selectedFunction === 'line' ||
selectedFunction === 'rectangle' ||
selectedFunction === 'circle') {
drawGuidewires(loc.x, loc.y);
}
}
};

function endPath(loc) {
drawingContext.lineTo(loc.x, loc.y);
drawingContext.stroke();

if (selectedFunction === 'pathClosed') {
drawingContext.closePath();

if (doFill) {
drawingContext.fill();
}
drawingContext.stroke();
}
}

function mouseUpOrTouchEndInDrawingCanvas(loc) {
if (selectedFunction !== 'erase' && selectedFunction !== 'slinky') {
restoreDrawingSurface();
}

if (draggingControlPoint) {
moveControlPoint(loc);
finishDrawingCurve();
draggingControlPoint = false;
}
else if (dragging) {
if (selectedFunction === 'erase') {
eraseLast();
}
else if (selectedFunction === 'path' ||
selectedFunction === 'pathClosed') {
endPath(loc);
}
else {
if (selectedFunction === 'line') finishDrawingLine(loc);
else if (selectedFunction === 'rectangle') finishDrawingRectangle();
else if (selectedFunction === 'circle') finishDrawingCircle(loc);
else if (selectedFunction === 'curve') startEditingCurve(loc);
}
}
dragging = false;
};

// Control canvas event handlers.................................
iconCanvas.onmousedown = function (e) {
var x = e.x || e.clientX,
y = e.y || e.clientY,
loc = windowToCanvas(iconCanvas, x, y);

e.preventDefault();
mouseDownOrTouchStartInControlCanvas(loc);
}

iconCanvas.addEventListener('touchstart', function (e) {
if (e.touches.length === 1) {
e.preventDefault();
mouseDownOrTouchStartInControlCanvas(
windowToCanvas(iconCanvas,
e.touches[0].clientX, e.touches[0].clientY));
}
});

// Drawing canvas event handlers.................................
drawingCanvas.onmousedown = function (e) {
var x = e.x || e.clientX,
y = e.y || e.clientY;

e.preventDefault();
mouseDownOrTouchStartInDrawingCanvas(
windowToCanvas(drawingCanvas, x, y));
}

drawingCanvas.ontouchstart = function (e) {
if (e.touches.length === 1) {
e.preventDefault();
mouseDownOrTouchStartInDrawingCanvas(
windowToCanvas(drawingCanvas,
e.touches[0].clientX, e.touches[0].clientY));
}
}

drawingCanvas.ontouchmove = function (e) {
if (e.touches.length === 1) {
mouseMoveOrTouchMoveInDrawingCanvas(
windowToCanvas(drawingCanvas,
e.touches[0].clientX, e.touches[0].clientY));
}
}

drawingCanvas.ontouchend = function (e) {
var loc;

if (e.changedTouches.length === 1) {
loc = windowToCanvas(drawingCanvas, e.changedTouches[0].clientX, e.changedTouches[0].clientY);
mouseUpOrTouchEndInDrawingCanvas(loc);
}
}

drawingCanvas.onmousemove = function (e) {
var x = e.x || e.clientX,
y = e.y || e.clientY,
loc = windowToCanvas(drawingCanvas, x, y);

e.preventDefault();
mouseMoveOrTouchMoveInDrawingCanvas(loc);
}

drawingCanvas.onmouseup = function (e) {
var x = e.x || e.clientX,
y = e.y || e.clientY,
loc = windowToCanvas(drawingCanvas, x, y);

e.preventDefault();
mouseUpOrTouchEndInDrawingCanvas(loc);
}

// Control event handlers........................................
strokeStyleSelect.onchange = function (e) {
drawingContext.strokeStyle = strokeStyleSelect.value;
};

fillStyleSelect.onchange = function (e) {
drawingContext.fillStyle = fillStyleSelect.value;
};

lineWidthSelect.onchange = function (e) {
drawingContext.lineWidth = lineWidthSelect.value;
/*
var c = drawingContext.canvas,
sw = c.width,
sh = c.height,
dw = sw * lineWidthSelect.value,
dh = sh * lineWidthSelect.value;

drawingContext.scale(lineWidthSelect.value, lineWidthSelect.value);
drawingContext.drawImage(c, 0, 0);
*/
};

eraseAllButton.onclick = function (e) {
drawingContext.clearRect(0,0,
drawingCanvas.width,
drawingCanvas.height);
drawGrid(drawingContext, GRID_LINE_COLOR, 10, 10);
saveDrawingSurface();
rubberbandW = rubberbandH = 0;
};

curveInstructionsOkayButton.onclick = function (e) {
curveInstructions.style.display = 'none';
};

curveInstructionsNoMoreButton.onclick = function (e) {
curveInstructions.style.display = 'none';
showCurveInstructions = false;
};

snapshotButton.onclick = function (e) {
var dataUrl;

if (snapshotButton.value === 'Take snapshot') {
dataUrl = drawingCanvas.toDataURL();
snapshotImageElement.src = dataUrl;
snapshotImageElement.style.display = 'inline';
snapshotInstructions.style.display = 'inline';
drawingCanvas.style.display = 'none';
iconCanvas.style.display = 'none';
controls.style.display = 'none';
snapshotButton.value = 'Back to Paint';
}
else {
snapshotButton.value = 'Take snapshot';
drawingCanvas.style.display = 'inline';
iconCanvas.style.display = 'inline';
controls.style.display = 'inline';
snapshotImageElement.style.display = 'none';
snapshotInstructions.style.display = 'none';
}
};

function drawBackground() {
backgroundContext.canvas.width = drawingContext.canvas.width;
backgroundContext.canvas.height = drawingContext.canvas.height;

drawGrid(backgroundContext, GRID_LINE_COLOR, 10, 10);
}

// Initialization................................................
iconContext.strokeStyle = ICON_STROKE_STYLE;
iconContext.fillStyle = ICON_FILL_STYLE;

iconContext.font = '48px Palatino';
iconContext.textAlign = 'center';
iconContext.textBaseline = 'middle';

drawingContext.font = '48px Palatino';
drawingContext.textBaseline = 'bottom';

drawingContext.strokeStyle = strokeStyleSelect.value;
drawingContext.fillStyle = fillStyleSelect.value;
drawingContext.lineWidth = lineWidthSelect.value;

drawGrid(drawingContext, GRID_LINE_COLOR, 10, 10);
selectedRect = ICON_RECTANGLES[SLINKY_ICON];
selectedFunction = 'slinky';

// This event listener prevents touch devices from
// scrolling the visible viewport.
document.body.addEventListener('touchmove', function (e) {
e.preventDefault();
}, false);

drawIcons();
drawBackground();

/*
if (window.matchMedia) alert('found'); else alert('nope');
var mql = window.matchMedia("(orientation:landscape)");
if (mql.addListener) alert('found'); else alert('nope');

function listener(mql) { alert ('...'); }

mql.addListener( listener );
listener(mql);
*/

keyboard.appendTo('keyboard');
keyboard.addKeyListener( function (key) {
if (key === 'Enter') enter();
else if (key === '<') backspace();
else insert(key);
});
Carefree
12 December 2017, 00:20


I solved the "select all" issue. It was due to a javascript comment; oddly enough. Removing the comment made it work.
I'd still like to get code so the images created by the canvas app could be saved in a forum folder. Can anyone help with that one?
HuwR
13 December 2017, 13:27


Of the top of my head, I would do something like
//grab the canvas image and assign it to a form element,
document.getElementById('my_image').value = canvas.toDataURL('image/png');

you can then submit the form and process as you would any other form post
the my_image value is a base 64 image string so will need decoding before saving it

Carefree
18 December 2017, 03:47


Will give it a go, thanks
© 2000-2021 Snitz™ Communications