Snitz Forums 2000
Snitz Forums 2000
Home | Profile | Register | Active Topics | Members | Search | FAQ
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 Help Groups for Snitz Forums 2000 Users
 Help: MOD Implementation
 Javascript Issues
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic  

Carefree
Advanced Member

Philippines
4207 Posts

Posted - 18 November 2017 :  00:40:39  Show Profile  Reply with Quote
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.


<%
'#################################################################################
'## 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.


$(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);
}

Edited by - Carefree on 12 December 2017 00:22:04

HuwR
Forum Admin

United Kingdom
20579 Posts

Posted - 18 November 2017 :  12:00:06  Show Profile  Visit HuwR's Homepage  Reply with Quote
are you getting errors?
Have you tried debugging the javascript in your browser?

MVC .net dev/test site | MVC .net running on Raspberry Pi
Go to Top of Page

Carefree
Advanced Member

Philippines
4207 Posts

Posted - 21 November 2017 :  05:22:41  Show Profile  Reply with Quote
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.
Go to Top of Page

HuwR
Forum Admin

United Kingdom
20579 Posts

Posted - 21 November 2017 :  09:50:31  Show Profile  Visit HuwR's Homepage  Reply with Quote
quote:
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?

MVC .net dev/test site | MVC .net running on Raspberry Pi
Go to Top of Page

Carefree
Advanced Member

Philippines
4207 Posts

Posted - 29 November 2017 :  23:25:10  Show Profile  Reply with Quote
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:


/*
 * 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);
});
Go to Top of Page

Carefree
Advanced Member

Philippines
4207 Posts

Posted - 12 December 2017 :  00:20:38  Show Profile  Reply with Quote
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?
Go to Top of Page

HuwR
Forum Admin

United Kingdom
20579 Posts

Posted - 13 December 2017 :  13:27:26  Show Profile  Visit HuwR's Homepage  Reply with Quote
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


MVC .net dev/test site | MVC .net running on Raspberry Pi
Go to Top of Page

Carefree
Advanced Member

Philippines
4207 Posts

Posted - 18 December 2017 :  03:47:00  Show Profile  Reply with Quote
Will give it a go, thanks
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
Snitz Forums 2000 © 2000-2021 Snitz™ Communications Go To Top Of Page
This page was generated in 0.23 seconds. Powered By: Snitz Forums 2000 Version 3.4.07