mr.jsnerd
01-09-2010, 03:34 PM
i made a javascript graphing calculator.
here is the code:
/*
graphing calculator made by Mr.JSNerd. Graphs equations in javascript syntax
Copyright ( C ) 2010 bryce paputa
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
( at your option ) any later version.
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
along with this program. If not, see < http : // www.gnu.org / licenses / > .
contact me at Mr.JSNerd@googlemail.com
*/
/*TODO---------------------------------------------
[X]be able to graph a function
[X]be able to graph a piece-wise function
[ ]^easily
[1/2]use non javascript syntax (might take a while...)
[X]clear the graph with out F5
[X]show/unshow axes,orgin,tick marks and others
[ ]be able to sacale graph
[X]be able to graph ALL recursive sequences
[ ]^ALL eaisaly
[X]^arithmetic
[ ]^easily
[X]^geometric
[ ]^easily
[X]^user made
[ ]^easily
[X]gui basics done
[X]CSS styling done
[ ]relaese to public
[ ] FINISH THIS MAKING THIS CHECKLIST!!!
*/
var initgraph = function( canvasid )
{
var graph =
{
}
;
graph.logmsg = [];
var dlog;
graph.curlog = ( document.getElementById( "dlog" ) ) ? document.getElementById( "dlog" ) : null;
if ( graph.curlog === null ){
graph.dlog = function()
{
}
;
}
else{
graph.dlog = dlog = function( str )
{
graph.logmsg.push( str );
var temp = graph.logmsg.join( "\n" );
graph.curlog.value = temp;
return str;
}
;
}
//alert( 'debbuging log initalized' );
graph.canvas = document.getElementById( canvasid );
graph.dlog( "canvas found" );
graph.dlog( "width: " + ( graph.w = parseInt( document.defaultView.getComputedStyle( graph.canvas, null ).width, 10 ) ) );
graph.dlog( "height: " + ( graph.h = parseInt( document.defaultView.getComputedStyle( graph.canvas, null ).height, 10 ) ) );
graph.h2 = Math.round( graph.h / 2 );
graph.w2 = Math.round( graph.w / 2 );
graph.dlog( "computed styles calculated" );
graph.ctx = graph.canvas.getContext( "2d" );
graph.dlog( 'canvas context gained' );
graph.fillStyle = (document.getElementById('site').value=='win')?'#ffffff':"#E0FFFF";
graph.ctx.fillStyle=graph.fillStyle;
graph.dlog( 'styles set' );
graph.ctx.translate( graph.w2, graph.h2 );
graph.ctx.stroke();
graph.ctx.save();
graph.dlog( 'canvas context saved' );
graph.ctx.beginPath();
graph.dlog( 'axis postitions have been calculated' );
graph.lg = [];
graph.gs = [];
graph.dlog( 'arrays initialized' );
graph.goodsize = 1;
if( graph.h < 200 || graph.w < 200 ){
alert( "Canvas for graph is too small.\n Minimum recomended size is 200 X 200, recomended size is 500 X 500.\nSize is " + graph.h + " X " + graph.w + ".\n Graphs may be hard to see or they may be pointless." );
graph.goodsize = 0;
}
else{
graph.dlog( "graph is big enuf" );
}
if( graph.h != graph.w ){
alert( "The canvas is not square. Graph may not look right." );
graph.goodsize = 0;
}
else{
graph.dlog( 'graph is square' );
}
graph.lineTo = function( x, y ){
graph.ctx.lineTo( x, - y );
return graph;
}
;
graph.moveTo = function( x, y ){
graph.ctx.moveTo( x, - y );
return graph;
}
;
graph.dot = function( xx, yy )
{
if( ( typeof xx !== "number" || typeof yy !== "number" ) || Math.abs( xx ) > graph.w2 || Math.abs( yy ) > graph.h2 )
{
graph.dlog( "Dot (" + xx + ", " + yy + ") will not fit on the graph. Will not attempt to graph." );
return graph;
}
graph.ctx.fillStyle=(document.getElementById('site').value=='win')?'#000000':'#2B167B';
yy = 0 - Math.round( yy );
xx = Math.round( xx );
graph.ctx.fillRect( xx - 1, yy + 1, 3, 3 );
return graph;
}
;
graph.dlog( 'basic graphing methods created' );
graph.da = function( axes,ticks,orgin )/////////////////////////////////////////////////////////////////////////////////////////
{
// if ( clr === true )
// {
// graph.ctx.clearRect( - graph.w2, - graph.h2, graph.h, graph.w );
// } // old stuf.
graph.ctx.strokeStyle = (document.getElementById('site').value=='win')?'#000000':'#2B167B';
if( axes ){
graph.moveTo( - graph.w2, 0 );
graph.lineTo( graph.w2, 0 );
graph.moveTo( 0, - graph.h2 );
graph.lineTo( 0, graph.h2 );
//alert('axes')
}
if( ticks ){
var j = - 3;
var i = - graph.w2;
for( i; i <= graph.w2; i += 10 )
{
graph.ctx.moveTo( i, j+0.5 );
graph.ctx.lineTo( i, j +5.5 );
}
j = - 3;
i = - graph.h2;
for( i; i <= graph.h2; i += 10 )
{
graph.ctx.moveTo( j+0.5, i );
graph.ctx.lineTo( j + 5.5, i );
}
// alert('ticks')
}
if( orgin ){
graph.dot( 0, 0)
// alert('orgin')
}
graph.ctx.stroke();
graph.ctx.beginPath();
return graph;
}
;
graph.dlog( 'axis drawing method initialized' );
graph.clrAll = function(){
graph.gs = [];
graph.ctx.fillStyle=graph.fillStyle;
graph.ctx.fillRect( -graph.w2, -graph.h2, graph.w, graph.h );
graph.ctx.beginPath();
graph.dlog('graph cleared');
return graph;
}
graph.clrAll();
graph.dlog( 'axes drawn' );
graph.ec = function( /*y=*/equ ){
if( typeof equ !== "string" )
{
alert( "Equation must be a string." );
return false;
}
graph.ts = equ.replace(/[x0-9\*\^\/\.\)\(\-\+\%\s]/g,'');
graph.ts= graph.ts.replace(/(Math|abs|acos|asin|atan|atan2|ceil|cos|exp|floor|log|max|min|pow|random|round|sin|sqrt|tan)/g,'');
graph.ts= graph.ts.replace(/(E|LN10|LN2|LOG10E|LOG2E|PI|SQRT1_2|SQRT2)/g,'')
if(graph.ts!=''){
alert('Illegal keyword found: '+graph.ts);
return 'perspicaciousness';
}
equ = equ.replace( /\|([^\|]+)\|/g, "Math.abs($1)" );
equ = equ.replace( /([a-z0-9\[\]\.\-]+)\s*\^\s*([a-z0-9\[\]\.\-]+)/, "Math.pow($1,$2)" );
equ = equ.replace(/([0-9])x/, '$1 * x');
equ = equ.replace(/([0-9]|x|E|I)\w*\(/g,'$1 * (');
// eventually this will allow for normal human syntax equations and not only javascript syntax ones
return equ;
}
;
graph.dlog( 'equation interpreter initialized' );
graph.graph = function( /*y=*/equ ){
equ = graph.ec( equ );
graph.ctx.strokeStyle='#000000';
if( equ === false ){
alert( 'Pass equation as a string without the "y=", "f(x)=", "g(x)=" or similar.' );
return graph;
}
if( equ == 'perspicaciousness' ){
return graph;
}
var a=graph.lg;
var i = 0;
for( var x = 0 - graph.w2; x <= graph.w2; x ++ )
{
try
{ var a=graph.lg;
graph.lg[x] = eval(equ);
}
catch( e )
{
alert(graph.dlog("Bad syntax!"));
return graph
}
if(!( isNaN( graph.lg[x] ) || Math.abs( graph.lg[x] ) > graph.h2) ){
if( i === 0 ){
graph.moveTo( x, graph.lg[x] )
i = 1;
}
else{
graph.lineTo( x, graph.lg[x])
graph.ctx.stroke();
}
}
}
dlog('graphed '+equ);
return graph;
}
;
graph.dlog( 'main graphing object initialized. \ngraph library finished. exiting grafit.js' );
return graph;
}
// ---------------------------------------
;
sorry for the length. an implemtation of it is attached (as a .txt file, cant upload html), with the pictures.
here is the code:
/*
graphing calculator made by Mr.JSNerd. Graphs equations in javascript syntax
Copyright ( C ) 2010 bryce paputa
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
( at your option ) any later version.
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
along with this program. If not, see < http : // www.gnu.org / licenses / > .
contact me at Mr.JSNerd@googlemail.com
*/
/*TODO---------------------------------------------
[X]be able to graph a function
[X]be able to graph a piece-wise function
[ ]^easily
[1/2]use non javascript syntax (might take a while...)
[X]clear the graph with out F5
[X]show/unshow axes,orgin,tick marks and others
[ ]be able to sacale graph
[X]be able to graph ALL recursive sequences
[ ]^ALL eaisaly
[X]^arithmetic
[ ]^easily
[X]^geometric
[ ]^easily
[X]^user made
[ ]^easily
[X]gui basics done
[X]CSS styling done
[ ]relaese to public
[ ] FINISH THIS MAKING THIS CHECKLIST!!!
*/
var initgraph = function( canvasid )
{
var graph =
{
}
;
graph.logmsg = [];
var dlog;
graph.curlog = ( document.getElementById( "dlog" ) ) ? document.getElementById( "dlog" ) : null;
if ( graph.curlog === null ){
graph.dlog = function()
{
}
;
}
else{
graph.dlog = dlog = function( str )
{
graph.logmsg.push( str );
var temp = graph.logmsg.join( "\n" );
graph.curlog.value = temp;
return str;
}
;
}
//alert( 'debbuging log initalized' );
graph.canvas = document.getElementById( canvasid );
graph.dlog( "canvas found" );
graph.dlog( "width: " + ( graph.w = parseInt( document.defaultView.getComputedStyle( graph.canvas, null ).width, 10 ) ) );
graph.dlog( "height: " + ( graph.h = parseInt( document.defaultView.getComputedStyle( graph.canvas, null ).height, 10 ) ) );
graph.h2 = Math.round( graph.h / 2 );
graph.w2 = Math.round( graph.w / 2 );
graph.dlog( "computed styles calculated" );
graph.ctx = graph.canvas.getContext( "2d" );
graph.dlog( 'canvas context gained' );
graph.fillStyle = (document.getElementById('site').value=='win')?'#ffffff':"#E0FFFF";
graph.ctx.fillStyle=graph.fillStyle;
graph.dlog( 'styles set' );
graph.ctx.translate( graph.w2, graph.h2 );
graph.ctx.stroke();
graph.ctx.save();
graph.dlog( 'canvas context saved' );
graph.ctx.beginPath();
graph.dlog( 'axis postitions have been calculated' );
graph.lg = [];
graph.gs = [];
graph.dlog( 'arrays initialized' );
graph.goodsize = 1;
if( graph.h < 200 || graph.w < 200 ){
alert( "Canvas for graph is too small.\n Minimum recomended size is 200 X 200, recomended size is 500 X 500.\nSize is " + graph.h + " X " + graph.w + ".\n Graphs may be hard to see or they may be pointless." );
graph.goodsize = 0;
}
else{
graph.dlog( "graph is big enuf" );
}
if( graph.h != graph.w ){
alert( "The canvas is not square. Graph may not look right." );
graph.goodsize = 0;
}
else{
graph.dlog( 'graph is square' );
}
graph.lineTo = function( x, y ){
graph.ctx.lineTo( x, - y );
return graph;
}
;
graph.moveTo = function( x, y ){
graph.ctx.moveTo( x, - y );
return graph;
}
;
graph.dot = function( xx, yy )
{
if( ( typeof xx !== "number" || typeof yy !== "number" ) || Math.abs( xx ) > graph.w2 || Math.abs( yy ) > graph.h2 )
{
graph.dlog( "Dot (" + xx + ", " + yy + ") will not fit on the graph. Will not attempt to graph." );
return graph;
}
graph.ctx.fillStyle=(document.getElementById('site').value=='win')?'#000000':'#2B167B';
yy = 0 - Math.round( yy );
xx = Math.round( xx );
graph.ctx.fillRect( xx - 1, yy + 1, 3, 3 );
return graph;
}
;
graph.dlog( 'basic graphing methods created' );
graph.da = function( axes,ticks,orgin )/////////////////////////////////////////////////////////////////////////////////////////
{
// if ( clr === true )
// {
// graph.ctx.clearRect( - graph.w2, - graph.h2, graph.h, graph.w );
// } // old stuf.
graph.ctx.strokeStyle = (document.getElementById('site').value=='win')?'#000000':'#2B167B';
if( axes ){
graph.moveTo( - graph.w2, 0 );
graph.lineTo( graph.w2, 0 );
graph.moveTo( 0, - graph.h2 );
graph.lineTo( 0, graph.h2 );
//alert('axes')
}
if( ticks ){
var j = - 3;
var i = - graph.w2;
for( i; i <= graph.w2; i += 10 )
{
graph.ctx.moveTo( i, j+0.5 );
graph.ctx.lineTo( i, j +5.5 );
}
j = - 3;
i = - graph.h2;
for( i; i <= graph.h2; i += 10 )
{
graph.ctx.moveTo( j+0.5, i );
graph.ctx.lineTo( j + 5.5, i );
}
// alert('ticks')
}
if( orgin ){
graph.dot( 0, 0)
// alert('orgin')
}
graph.ctx.stroke();
graph.ctx.beginPath();
return graph;
}
;
graph.dlog( 'axis drawing method initialized' );
graph.clrAll = function(){
graph.gs = [];
graph.ctx.fillStyle=graph.fillStyle;
graph.ctx.fillRect( -graph.w2, -graph.h2, graph.w, graph.h );
graph.ctx.beginPath();
graph.dlog('graph cleared');
return graph;
}
graph.clrAll();
graph.dlog( 'axes drawn' );
graph.ec = function( /*y=*/equ ){
if( typeof equ !== "string" )
{
alert( "Equation must be a string." );
return false;
}
graph.ts = equ.replace(/[x0-9\*\^\/\.\)\(\-\+\%\s]/g,'');
graph.ts= graph.ts.replace(/(Math|abs|acos|asin|atan|atan2|ceil|cos|exp|floor|log|max|min|pow|random|round|sin|sqrt|tan)/g,'');
graph.ts= graph.ts.replace(/(E|LN10|LN2|LOG10E|LOG2E|PI|SQRT1_2|SQRT2)/g,'')
if(graph.ts!=''){
alert('Illegal keyword found: '+graph.ts);
return 'perspicaciousness';
}
equ = equ.replace( /\|([^\|]+)\|/g, "Math.abs($1)" );
equ = equ.replace( /([a-z0-9\[\]\.\-]+)\s*\^\s*([a-z0-9\[\]\.\-]+)/, "Math.pow($1,$2)" );
equ = equ.replace(/([0-9])x/, '$1 * x');
equ = equ.replace(/([0-9]|x|E|I)\w*\(/g,'$1 * (');
// eventually this will allow for normal human syntax equations and not only javascript syntax ones
return equ;
}
;
graph.dlog( 'equation interpreter initialized' );
graph.graph = function( /*y=*/equ ){
equ = graph.ec( equ );
graph.ctx.strokeStyle='#000000';
if( equ === false ){
alert( 'Pass equation as a string without the "y=", "f(x)=", "g(x)=" or similar.' );
return graph;
}
if( equ == 'perspicaciousness' ){
return graph;
}
var a=graph.lg;
var i = 0;
for( var x = 0 - graph.w2; x <= graph.w2; x ++ )
{
try
{ var a=graph.lg;
graph.lg[x] = eval(equ);
}
catch( e )
{
alert(graph.dlog("Bad syntax!"));
return graph
}
if(!( isNaN( graph.lg[x] ) || Math.abs( graph.lg[x] ) > graph.h2) ){
if( i === 0 ){
graph.moveTo( x, graph.lg[x] )
i = 1;
}
else{
graph.lineTo( x, graph.lg[x])
graph.ctx.stroke();
}
}
}
dlog('graphed '+equ);
return graph;
}
;
graph.dlog( 'main graphing object initialized. \ngraph library finished. exiting grafit.js' );
return graph;
}
// ---------------------------------------
;
sorry for the length. an implemtation of it is attached (as a .txt file, cant upload html), with the pictures.