科学计算器 ZENO-5000
科学计算器 ZENO-5000: HTML 5、CSS 3 和客户端 jQuery/JavaScript
引言
科学计算器 ZENO-5000 是一个轻量级的 Web 应用程序(<40kb),利用了最新的 HTML5/CSS3 功能以及客户端 jQuery/Java 脚本。该应用程序不包含任何图形文件。它具有便携性,能够以在线/离线模式在 PC/移动设备上运行。
背景
作为 Web “瘦客户端”应用程序实现的计算器软件需要“实时”的 Internet 连接。这种方法有利有弊:“瘦客户端”Web 应用程序是“零安装”且平台/操作系统独立的,因此具有便携性/能够在任何主流 Web 浏览器中运行(值得一提的是,Web 浏览器正在迅速成为 Web 应用程序和服务的“事实上的”虚拟操作系统,在某种程度上可以替代真实的操作系统)。但是,对 Internet 连接的需求带来了一定的限制;非常希望有一个能够离线运行的计算器应用程序。一个可能的解决方案是通过纯客户端脚本来实现该应用程序,主要是 JavaScript 代码,它兼容任何主流 Web 浏览器。这样的 Web 应用程序可以像往常一样在线运行,也可以下载并缓存到客户端的平台上。
一个可能的解决方案是仅通过客户端脚本来实现该应用程序,主要是 JavaScript 代码,它几乎兼容所有主流现有 Web 浏览器。这样的 Web 应用程序可以像往常一样在线运行,也可以下载并缓存到客户端的平台上,从而实现离线模式。这种“通用”解决方案有几个核心要求:
- 它必须是平台/操作系统独立的,能够在 4 个主流浏览器(Mozilla Firefox、Microsoft Internet Explorer、Google Chrome 和 Apple Safari)中运行。
- 安装过程必须简单明了,就像“复制粘贴”一样。
- 考虑到便携设备上潜在的内存空间限制,它应该有一个极小的“数字足迹”。
遵守上述设计原则将确保 OSC 的高便携性及其与大多数可用的移动/固定计算平台的兼容性。
科学计算器 ZENO-5000,示例截图
核心功能
- 数据输入操作:简单来说,就是点击任何数字键,或者直接输入常量值,如圆周率 pi、自然常数 e、2 的平方根等。
- 一元运算:这些运算直接在输入框的内容上执行,例如倒数函数 1/x,或三角函数 sin(x)。
- 对一对数值执行的二元运算:其中一个数值存储在内部内存寄存器“堆栈”中,第二个数值显示在输入框中。这类运算包括所有四种算术运算、指数计算(y^x,表示“y 的 x 次方”)和百分比计算。
几乎所有现代计算器都实现了内存操作。这个方便的功能允许将中间结果存储在内部内存寄存器中以供将来使用。简而言之,内存操作包括以下内容:
- 将输入框的内容移动/复制到内存(使用向下箭头键)。
- 将内存的内容移动/复制到输入框(使用向上箭头键)。
- 清除内存:点击内存框(位于输入框下方)以清除内容。
- 加到内存(使用标记为 M+ 的键)。
- 从内存减去(使用标记为 M- 的键)。
应用程序架构
在线科学计算器 ZENO-5000(下称 ZENO)被实现为一个富 Internet 应用程序,利用了新兴 Internet 标准(HTML5/CSS3)和客户端脚本(jQuery/JavaScript)中提供的最新功能。它可以在主要 Web 浏览器中以在线或离线模式运行:要使用后者,必须下载应用程序文件并存储在客户端计算机上。这些文件包括:
- 主文件:zeno.htm(文件包含对 jQuery 库的在线动态链接)。
- 样式表(CSS)文件:oscZeno.css。
- 用 JavaScript 编写的计算引擎:oscZeno.js。
- 参考文件:oscZenoRef.js。
二元运算涉及“堆栈”内存寄存器(变量 stackValue
),用于存储第一个操作数。另一个变量 opCode
存储操作码。
0-no operation
1-Addition
2-Subtraction
3-Multiplication
4-Division
5-power (y^x)
6-percent
这些操作是在堆栈内容和输入框中输入的数值上执行的。辅助寄存器(var boolClear
)提供了“在下次数据输入前清除输入框”的功能:它存储一个布尔值,强制代码在输入另一个数值之前清除输入寄存器。
关注点
科学计算器 ZENO-5000 完全兼容 Mozilla/Webkit 基于的 Web 浏览器,以及可能的 Internet Explorer 9。它已在各种桌面和移动平台(iPod Touch (Safari) 和 Windows Phone 7)上进行了测试。
ZENO-5000 项目不使用任何图像文件,因此具有极小的数字足迹。所有通过新颖功能实现的审美增强都通过 HTML 5/CSS 3 来实现,即:圆角、渐变、投影等。下面展示了最具创新的 HTML 5/CSS 3 编码技术。
列表 1:CSS 3 代码片段用于为屏幕对象添加阴影(注意:不需要图形图像)。
-moz-box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
-webkit-box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
列表 2:CSS 3 代码片段用于实现圆角(注意:不需要图形图像)。
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
列表 3:CSS 3 代码片段用于创建颜色渐变(在 IE<9 中无效)。
/* WebKit */
background: -webkit-gradient(linear, left top, right top from(#ffffcc), to(#ffffff));
/* Mozilla/Gecko */
background: -moz-linear-gradient(left top, #ffffcc, #ffffff);
列表 4:jQuery 代码片段在文档加载事件上执行一个简短的动画,演示了切换功能。最初,滑动面板显示为折叠模式(图 3)。
$(document).ready(function () {
// ON LOAD ********************************************
$("div.oscExtControl").fadeTo(1000, 0.25,
function () { $("div.oscExtControl").fadeTo(1000, 1.00); });
//
$("div.oscExtPanel").slideToggle("fast");
$("div.oscStackRegister").slideToggle("normal");
列表 5:jQuery 代码片段在控件按钮点击时启用面板滑动(切换)(参见图 1、2,显示扩展面板)。
// TOGGLE EXT PANEL ON CLICK
$("div.oscExtControl").click(function () {
var ctl = $(this);
$("div.oscExtPanel").slideToggle("fast", function () {
oscExtState = !oscExtState;
if (oscExtState) ctl.html(strLess); else ctl.html(strMore);
});
});
列表 6:可用的一元运算直接应用于输入框的内容。
// UNARY OPERATIONS *******************************************************
$("button.keyPad_btnUnaryOp").click(function () {
var inputBox = $(keyPad_UserInput);
var x = parseFloat(inputBox.val());
var retVal = oscError;
switch (this.id) {
// +/-
case 'keyPad_btnInverseSign': retVal = -x; break;
// 1/X
case 'keyPad_btnInverse': retVal = 1 / x; break;
// X^2
case 'keyPad_btnSquare': retVal = x * x; break;
// SQRT(X)
case 'keyPad_btnSquareRoot': retVal = Math.sqrt(x); break;
// X^3
case 'keyPad_btnCube': retVal = x * x * x; break;
// POW (X, 1/3)
case 'keyPad_btnCubeRoot': retVal = Math.pow(x, 1 / 3); break;
// NATURAL LOG
case 'keyPad_btnLn': retVal = Math.log(x); break;
// LOG BASE 10
case 'keyPad_btnLg': retVal = Math.log(x) / Math.LN10; break;
// E^(X)
case 'keyPad_btnExp': retVal = Math.exp(x); break;
// SIN
case 'keyPad_btnSin': retVal = Math.sin(x); break;
// COS
case 'keyPad_btnCosin': retVal = Math.cos(x); break;
// TAN
case 'keyPad_btnTg': retVal = Math.tan(x); break;
// CTG
case 'keyPad_btnCtg': retVal = 1 / Math.tan(x); break;
// Arcsin
case 'keyPad_btnAsin': retVal = Math.asin(x); break;
// Arccos
case 'keyPad_btnAcos': retVal = Math.acos(x); break;
// Arctag
case 'keyPad_btnAtan': retVal = Math.atan(x); break;
// Secant
case 'keyPad_btnSec': retVal = 1 / Math.cos(x); break;
// Cosecant
case 'keyPad_btnCosec': retVal = 1 / Math.sin(x); break;
// sinh
case 'keyPad_btnSinH':
retVal = (Math.pow(Math.E, x) - Math.pow(Math.E, -x)) / 2; break;
// cosh
case 'keyPad_btnCosinH':
retVal = (Math.pow(Math.E, x) + Math.pow(Math.E, -x)) / 2; break;
// coth
case 'keyPad_btnTgH':
retVal = (Math.pow(Math.E, x) - Math.pow(Math.E, -x));
retVal /= (Math.pow(Math.E, x) + Math.pow(Math.E, -x));
break;
// Secant hyperbolic
case 'keyPad_btnSecH':
retVal = 2 / (Math.pow(Math.E, x) + Math.pow(Math.E, -x)); break;
// Cosecant hyperbolic
case 'keyPad_btnCosecH':
retVal = 2 / (Math.pow(Math.E, x) - Math.pow(Math.E, -x)); ; break;
// 1+x
case 'keyPad_btnOnePlusX': retVal = 1 + x; break;
// 1-x
case 'keyPad_btnOneMinusX': retVal = 1 - x; break;
default: break;
}
boolClear = true;
inputBox.val(retVal);
inputBox.focus();
});
列表 7:jQuery 代码片段用于通过点击内存框来清除内存(也可以应用于输入框)——对于触摸屏移动设备(iPhone、WP7 等)来说,这是一个非常有价值的便利功能。
// CLEAR MEM BOX BY CLICKING ON IT
$("div#keyPad input.keyPad_TextBox").click(function () {
var inBox = $(keyPad_UserInput);
var mem = $(keyPad_Mem);
switch (this.id) {
//case 'keyPad_UserInput': $(keyPad_UserInput).val(strEmpty); break;
case 'keyPad_Mem': $(keyPad_Mem).val(strEmpty); memVal = 0; break;
default: break;
}
});
列表 8:在扩展模式(展开面板)下可直接输入的常量。
// CONST DATA ENTRY *******************************************************
$("button.keyPad_btnConst").click(function () {
var retVal = strEmpty;
switch (this.id) {
// PI
case 'keyPad_btnPi': retVal = Math.PI; break;
// PI/2
case 'keyPad_btnPiDiv2': retVal = Math.PI / 2; break;
// PI/3
case 'keyPad_btnPiDiv3': retVal = Math.PI / 3; break;
// PI/4
case 'keyPad_btnPiDiv4': retVal = Math.PI / 4; break;
// PI/6
case 'keyPad_btnPiDiv6': retVal = Math.PI / 6; break;
// e
case 'keyPad_btnE': retVal = Math.E; break;
// 1/e
case 'keyPad_btnInvE': retVal = 1 / Math.E; break;
// SQRT(2)
case 'keyPad_btnSqrt2': retVal = Math.SQRT2; break;
// SQRT(3)
case 'keyPad_btnSqrt3': retVal = Math.sqrt(3); break;
// CUBE ROOT OF(3)
case 'keyPad_btnCubeRoot2': retVal = Math.pow(2, 1 / 3); break;
// Ln(10)
case 'keyPad_btnLn10': retVal = Math.LN10; break;
// base10: Log(e)
case 'keyPad_btnLgE': retVal = Math.LOG10E; break;
// Sigmas: defects probability: on scale 0...1
// 1 Sigma
case 'keyPad_btnSigma': retVal = 0.69; break;
// 3 Sigma
case 'keyPad_btnSigma3': retVal = 0.007; break;
// 6 Sigma
case 'keyPad_btnSigma6': retVal = 3.4 * Math.pow(10, -6); break;
default: break;
}
boolClear = true;
$(keyPad_UserInput).val(retVal);
inputBox.focus();
});
列表 9:完整的 CSS 文件。
/******************************************************************************
Project : Scientific Calculator
Module : CSS 3
Description : Implements HTML 5 / CSS 3 advanced features
******************************************************************************
Author : Alexander Bell
Copyright : 2010 Infosoft International Inc
Date Created : 11/20/2010
Last Modified : 12/01/2010
******************************************************************************
DISCLAIMER: This Application is provide on AS IS basis without any warranty
You can use it at your sole risk.
******************************************************************************
TERMS OF USE : This module is copyrighted. You can use it provided that
: you keep the original copyright note.
******************************************************************************/
body {
margin: 0;
padding: 0;
font-family: Arial, Calibri, Verdana, Tahoma, Times New Roman ;
text-align: center;
vertical-align: middle;
background-color: #eaeaea;
}
/* CENTER COLUMN */
.oscCenterColumn {
width: 480px;
padding: 10px 0px 0px 0px;
margin: 10px auto;
text-align: left;
}
/* MAIN DIV W/ALL CONTENTS */
.oscMain {
padding:10px;
/* make rounded corners */
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
/* add shadows */
-moz-box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
-webkit-box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
/* add gradient */
/* WebKit */
background: -webkit-gradient(linear, left top, left bottom,
from(#404040), to(#707070));
/* Mozilla/Gecko */
background: -moz-linear-gradient(top, #404040, #707070);
}
/* NEW TAGS ADDED IN HTML 5 */
header, footer, nav { display:block }
.oscTitle {
float:right;
margin:0px 0px 0px 0px;
font-size: 24px;
font-weight:lighter;
color: #dadada;
vertical-align:middle;
}
.oscModel {
text-align:center;
height:30px;
line-height:30px;
background-color: #303030;
vertical-align:middle;
}
.oscModel {
width: 150px;
margin:0px 0px 0px 0px;
font-size: 24px;
font-weight:bold;
color: yellow;
/* make rounded corners */
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border-radius: 20px;
}
/* NAV */
button.oscNav
{
float:left;
height:30px;
line-height:30px;
vertical-align:middle;
font-size: 14px;
font-family: Arial, Tahoma, Verdana, Calibri;
color: #bababa;
margin: 0px 0px 0px 3px;
padding: 0px 5px 0px 5px;
border: 1px solid olive;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
background: #505050;
background: -moz-linear-gradient(top, #909090, #505050 15px, #303030 15px, #202020);
background: -webkit-gradient(linear, left top, left bottom, from(#909090),
color-stop(0.5, #505050), color-stop(0.5, #303030), to(#202020));
cursor: pointer;
cursor: hand;
}
a { text-decoration:none;}
button.oscNav:active { border: solid 2px #dadada; }
button.oscNav:hover {
background: #454545;
background: -moz-linear-gradient(top, #505050, #202020 20px, #303030 20px, #909090);
background: -webkit-gradient(linear, left top, left bottom, from(##505050),
color-stop(0.5, #202020), color-stop(0.5, #303030), to(##909090));
}
/* EXTENDER CONTROL */
.oscExtControl, .oscStackControl
{
float:right;
margin:0px 0px 0px 5px;
width:60px;
height:30px;
line-height:30px;
vertical-align:middle;
text-align:center;
background-color: olive;
color: #dadada;
font-size: 22px;
font-weight:bold;
cursor: pointer;
cursor: hand;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
/* stack register content */
.oscStackRegister
{
position:absolute;
width:310px;
height:30px;
line-height:30px;
vertical-align:middle;
margin:5px 0px 0px 10px;
font-size: 22px;
font-weight:normal;
text-align:center;
color:#eaeaea;
background-color:Olive;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
filter:alpha(opacity=90);
-moz-opacity:0.9;
opacity: 0.9;
z-index:20;
cursor: pointer;
cursor: hand;
}
/* extended functions area */
.oscExtPanel
{
margin:0px;
padding: 5px 5px 5px 5px;
display:block;
background-color:#404040;
border: solid 1px Olive;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
/* DIV CONTAINING KEYS AND INPUT/MEM BOXES */
div#keyPad { width: 100%; }
/* KEYS RIGHT ALIGN */
.keys_ToRight { float:right; }
/******** CONTROLS: KEYS, INPUT/MEM TEXT BOXES *********/
div#keyPad input, div#keyPad button
{
height: 40px;
vertical-align:middle;
line-height:40px;
margin: 0px;
padding: 0px;
border: 1px solid olive;
font-family: Arial, Tahoma, Verdana, Calibri;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
div#keyPad button {
width: 60px;
text-align: center;
font-size: 20px;
cursor: pointer;
cursor: hand;
color: #dadada;
font-weight:bold;
/* add gradient using stop-color property: not working in IE<9 */
background:#404040;
background: -moz-linear-gradient(top, #dadada, #505050 20px, #303030 20px, #202020);
background: -webkit-gradient(linear, left top, left bottom, from(#dadada),
color-stop(0.5, #505050), color-stop(0.5, #303030), to(#202020));
}
div#keyPad button:active { border: solid 2px #707070; }
div#keyPad button:hover {
background: #454545;
background: -moz-linear-gradient(top, #505050, #202020 20px, #303030 20px, #909090);
background: -webkit-gradient(linear, left top, left bottom, from(##505050),
color-stop(0.5, #202020), color-stop(0.5, #303030), to(##909090));
}
/* INPUT/MEM TEXT BOXES*/
div#keyPad input {
width: 330px;
text-align: left;
text-indent:10px;
font-size: 24px;
color: #202020;
/* add gradient */
/* WebKit */
background: -webkit-gradient(linear, left top, right top from(#ffffcc), to(#ffffff));
/* Mozilla/Gecko */
background: -moz-linear-gradient(left top, #ffffcc, #ffffff);
}
div#keyPad input#keyPad_Mem {color: #909090;}
/* ENTER BUTTON: QUAD WIDTH + 14 */
div#keyPad button#keyPad_btnEnter { width:188px; font-size: 20px; color:Yellow;}
/* INPUT/MEM KEYS*/
div#keyPad .keyPad_btnMemOp
{ font-size: 20px; color: Olive;}
/* ZERO BUTTON: DOUBLE WIDTH + 4 */
div#keyPad button#keyPad_btn0
{ width: 125px; }
/* BACKSPACE/CLEAR INPUT KEYS*/
div#keyPad button#keyPad_btnBack,
div#keyPad button#keyPad_btnClr,
div#keyPad button#keyPad_btnAllClr
{
border-color:red;
color:red;
}
div#keyPad button#keyPad_btnBack {font-size: 18px;}
/* SPECIAL FORMATTING FOR SUPER-SCRIPT KEYS */
div#keyPad button#keyPad_btnSquare,
div#keyPad button#keyPad_btnCube,
div#keyPad button#keyPad_btnExp,
div#keyPad keyPad_btnYpowX
{ font-size: 16px; }
/* CLEAR BOTH */
.clear {clear:both;}
.oscDisclaimer
{
margin: 5px 0px 5px 0px;
color: #adadad;
font-weight: normal;
font-size: 10pt;
text-align:center;
}
.oscNotice {
margin-top:5px;
text-align:center;
font-size: 12px;
color: #606060;
}
.oscSpacer2, .oscSpacer3, .oscSpacer5 {clear:both; width:100%;}
.oscSpacer2 {height:2px;}
.oscSpacer3 {height:3px;}
.oscSpacer5 {height:5px;}
/* COMPATIBILITY W/OLD IE<9 */
#ie { background-color: #303030; }
/*************************************************/
列表 10:JavaScript 计算引擎和 jQuery 动画增强。
/******************************************************************************
Project : ZENO-5000 | Online Scientific Calculator (OSC)
Module : oscZeno.js | jQuery/Javascript
Description : Implements Math functions through client-side scripting
******************************************************************************
Author : Alexander Bell
Copyright : 2010 Infosoft International Inc
Date Created : 11/20/2010
Last Modified : 12/01/2010
******************************************************************************
DISCLAIMER: This Application is provide on AS IS basis without any warranty
You can use it at your sole risk.
******************************************************************************
TERMS OF USE : This module is copyrighted. You can use it provided that
: you keep the original copyright note.
******************************************************************************/
// ******* MAIN **************************************************************
$(document).ready(function () {
// ON LOAD ********************************************
$("div.oscExtControl").fadeTo(1000, 0.25,
function () { $("div.oscExtControl").fadeTo(1000, 1.00); });
//
$("div.oscExtPanel").slideToggle("fast");
$("div.oscStackRegister").slideToggle("normal");
// SHOW STACK REGISTER CONTENT and OpCode *********************************
$("div.oscStackControl").mouseover(function () {
var ctl = $("div.oscStackRegister");
var op = "";
if (opCode == 1) op = " +";
else if (opCode == 2) op = " -";
else if (opCode == 3) op = " *";
else if (opCode == 4) op = " /";
ctl.html(stackVal + op);
ctl.show(300);
})
.mouseout(function () { $("div.oscStackRegister").hide(); })
.mouseleave(function () { $("div.oscStackRegister").hide(); });
// close stack register div
$("div.oscStackRegister").click(function ()
{ $("div.oscStackRegister").hide(); });
$(this).click(function () { $("div.oscStackRegister").hide(); });
// CLEAR MEM ON CLICK
$("div.oscMemLabel").click(function ()
{ $(keyPad_Mem).val(strEmpty); memVal = 0; });
// TOGGLE EXT PANEL ON CLICK
$("div.oscExtControl").click(function () {
var ctl = $(this);
$("div.oscExtPanel").slideToggle("fast", function () {
oscExtState = !oscExtState;
if (oscExtState) ctl.html(strLess); else ctl.html(strMore);
});
});
//************************************************************************
// DATA ENTRY: NUMERIC KEYS
$("div#keyPad button.keyPad_btnNumeric").click(function () {
var btnVal = $(this).html();
var inBox = $(keyPad_UserInput);
// clear input box if flag set
if (boolClear) { inBox.val(strEmpty); boolClear = false; }
var str = inBox.val();
// limit the input length
if (str.length > maxLength) return;
// prevent duplicate dot entry
if (this.id == "keyPad_btnDot" && str.indexOf('.') >= 0) return;
inBox.val(str + btnVal);
inBox.focus();
});
// CONST DATA ENTRY *******************************************************
$("button.keyPad_btnConst").click(function () {
var retVal = strEmpty;
switch (this.id) {
// PI
case 'keyPad_btnPi': retVal = Math.PI; break;
// PI/2
case 'keyPad_btnPiDiv2': retVal = Math.PI / 2; break;
// PI/3
case 'keyPad_btnPiDiv3': retVal = Math.PI / 3; break;
// PI/4
case 'keyPad_btnPiDiv4': retVal = Math.PI / 4; break;
// PI/6
case 'keyPad_btnPiDiv6': retVal = Math.PI / 6; break;
// e
case 'keyPad_btnE': retVal = Math.E; break;
// 1/e
case 'keyPad_btnInvE': retVal = 1 / Math.E; break;
// SQRT(2)
case 'keyPad_btnSqrt2': retVal = Math.SQRT2; break;
// SQRT(3)
case 'keyPad_btnSqrt3': retVal = Math.sqrt(3); break;
// CUBE ROOT OF(3)
case 'keyPad_btnCubeRoot2': retVal = Math.pow(2, 1 / 3); break;
// Ln(10)
case 'keyPad_btnLn10': retVal = Math.LN10; break;
// base10: Log(e)
case 'keyPad_btnLgE': retVal = Math.LOG10E; break;
// Sigmas: defects probability: on scale 0...1
// 1 Sigma
case 'keyPad_btnSigma': retVal = 0.69; break;
// 3 Sigma
case 'keyPad_btnSigma3': retVal = 0.007; break;
// 6 Sigma
case 'keyPad_btnSigma6': retVal = 3.4 * Math.pow(10, -6); break;
default: break;
}
boolClear = true;
$(keyPad_UserInput).val(retVal);
inputBox.focus();
});
// BINARY OPERATION KEY ***************************************************
$("div#keyPad button.keyPad_btnBinaryOp").click(function () {
var inBox = $(keyPad_UserInput);
var newOpCode = 0;
// validate: string cannot start w/operation symbol
if (inBox.val().indexOf('-') >= 0) return;
if (inBox.val().indexOf('+') >= 0) return;
if (inBox.val().indexOf('*') >= 0) return;
if (inBox.val().indexOf('÷') >= 0) return;
switch (this.id) {
case 'keyPad_btnPlus': newOpCode = 1; break;
case 'keyPad_btnMinus': newOpCode = 2; break;
case 'keyPad_btnMult': newOpCode = 3; break;
case 'keyPad_btnDiv': newOpCode = 4; break;
case 'keyPad_btnYpowX': newOpCode = 5; break;
case 'keyPad_btnPercent':
if (opCode == 1 || opCode == 2)
{ inBox.val(stackVal * parseFloat(inBox.val()) / 100); }
else if (opCode == 3 || opCode == 4)
{ inBox.val(parseFloat(inBox.val()) / 100); }
else return;
break;
default: break;
}
if (opCode) { oscBinaryOperation(); }
else { stackVal = parseFloat(inBox.val()); boolClear = true; }
opCode = newOpCode;
inBox.focus();
});
// BINARY COMPUTATION *****************************************************
function oscBinaryOperation() {
var inBox = $(keyPad_UserInput);
var x2 = parseFloat(inBox.val());
switch (opCode) {
case 1: stackVal += x2; break;
case 2: stackVal -= x2; break;
case 3: stackVal *= x2; break;
case 4: stackVal /= x2; break;
// stack power inputBox
case 5: stackVal = Math.pow(stackVal, x2); break;
default: break;
}
inBox.val(stackVal);
boolClear = true;
inBox.focus();
}
// UNARY OPERATIONS *******************************************************
$("button.keyPad_btnUnaryOp").click(function () {
var inputBox = $(keyPad_UserInput);
var x = parseFloat(inputBox.val());
var retVal = oscError;
switch (this.id) {
// +/-
case 'keyPad_btnInverseSign': retVal = -x; break;
// 1/X
case 'keyPad_btnInverse': retVal = 1 / x; break;
// X^2
case 'keyPad_btnSquare': retVal = x * x; break;
// SQRT(X)
case 'keyPad_btnSquareRoot': retVal = Math.sqrt(x); break;
// X^3
case 'keyPad_btnCube': retVal = x * x * x; break;
// POW (X, 1/3)
case 'keyPad_btnCubeRoot': retVal = Math.pow(x, 1 / 3); break;
// NATURAL LOG
case 'keyPad_btnLn': retVal = Math.log(x); break;
// LOG BASE 10
case 'keyPad_btnLg': retVal = Math.log(x) / Math.LN10; break;
// E^(X)
case 'keyPad_btnExp': retVal = Math.exp(x); break;
// SIN
case 'keyPad_btnSin': retVal = Math.sin(x); break;
// COS
case 'keyPad_btnCosin': retVal = Math.cos(x); break;
// TAN
case 'keyPad_btnTg': retVal = Math.tan(x); break;
// CTG
case 'keyPad_btnCtg': retVal = 1 / Math.tan(x); break;
// Arcsin
case 'keyPad_btnAsin': retVal = Math.asin(x); break;
// Arccos
case 'keyPad_btnAcos': retVal = Math.acos(x); break;
// Arctag
case 'keyPad_btnAtan': retVal = Math.atan(x); break;
// Secant
case 'keyPad_btnSec': retVal = 1 / Math.cos(x); break;
// Cosecant
case 'keyPad_btnCosec': retVal = 1 / Math.sin(x); break;
// sinh
case 'keyPad_btnSinH':
retVal = (Math.pow(Math.E, x) - Math.pow(Math.E, -x)) / 2; break;
// cosh
case 'keyPad_btnCosinH':
retVal = (Math.pow(Math.E, x) + Math.pow(Math.E, -x)) / 2; break;
// coth
case 'keyPad_btnTgH':
retVal = (Math.pow(Math.E, x) - Math.pow(Math.E, -x));
retVal /= (Math.pow(Math.E, x) + Math.pow(Math.E, -x));
break;
// Secant hyperbolic
case 'keyPad_btnSecH':
retVal = 2 / (Math.pow(Math.E, x) + Math.pow(Math.E, -x)); break;
// Cosecant hyperbolic
case 'keyPad_btnCosecH':
retVal = 2 / (Math.pow(Math.E, x) - Math.pow(Math.E, -x)); ; break;
// 1+x
case 'keyPad_btnOnePlusX': retVal = 1 + x; break;
// 1-x
case 'keyPad_btnOneMinusX': retVal = 1 - x; break;
default: break;
}
boolClear = true;
inputBox.val(retVal);
inputBox.focus();
});
// ************************************************************************
// COMMAND BUTTONS: BACKSPACE, CLEAR AND ALL CLEAR
$("div#keyPad button.keyPad_btnCommand").click(function () {
var inBox = $(keyPad_UserInput);
var mem = $(keyPad_Mem);
var strInput = inBox.val();
switch (this.id) {
// on enter calculate the result, clear opCode
case 'keyPad_btnEnter':
inBox.val(oscBinaryOperation()); opCode = 0; inBox.focus(); return;
// clear input box (if not empty) or opCode
case 'keyPad_btnClr':
if (strInput == strEmpty) { opCode = 0; boolClear = false; }
else { inBox.val(strEmpty); }
break;
// clear the last char if input box is not empty
case 'keyPad_btnBack': if (strInput.length > 0) {
inBox.val(strInput.substring(0, strInput.length - 1)); break;
}
// clear all
case 'keyPad_btnAllClr':
inBox.val(strEmpty);
stackVal = strEmpty;
mem.val(strEmpty);
opCode = 0;
break;
default: break;
}
});
// MEMORY OPERATIONS ****************************************************************
$("div#keyPad button.keyPad_btnMemOp").click(function () {
var inBox = $(keyPad_UserInput);
var mem = $(keyPad_Mem);
try {
memValNumeric = parseFloat(mem.val());
}
catch (ex)
{ memVal = strEmpty; mem.val(strEmpty); return; }
switch (this.id) {
// move to mem and clear input box
case 'keyPad_btnToMem': mem.val(inBox.val()); inBox.val(strEmpty); break;
// copy to input box, but do not clear ithe memory
case 'keyPad_btnFromMem': inBox.val(mem.val()); break;
// add to mem
case 'keyPad_btnMemPlus':
memVal += parseFloat(inBox.val()); mem.val(memVal);
boolClear = true; break;
// subtract from mem
case 'keyPad_btnMemMinus':
memVal -= parseFloat(inBox.val()); mem.val(memVal);
boolClear = true; break;
default: break;
}
});
// CLEAR MEM BOX BY CLICKING ON IT
$("div#keyPad input.keyPad_TextBox").click(function () {
var inBox = $(keyPad_UserInput);
var mem = $(keyPad_Mem);
switch (this.id) {
//case 'keyPad_UserInput': $(keyPad_UserInput).val(strEmpty); break;
case 'keyPad_Mem': $(keyPad_Mem).val(strEmpty); memVal = 0; break;
default: break;
}
});
})
// ***********************************************************************************
历史
在线科学计算器 ZENO-5000 最初是一个教育项目,旨在展示新兴 Internet 标准的强大功能,特别是:HTML 5 和 CSS 3,以及日益流行的 jQuery(JavaScript 的扩展)。ZENO 被实现为一个数字足迹极小的富 Internet 应用程序(RIA)。它不使用任何图形文件:所有审美增强,如颜色渐变、圆角、边框阴影等,都通过 HTML5/CSS 3 中提供的新功能实现,从而大大简化了页面布局设计并确保了应用程序的快速加载。ZENO 项目深入探讨了 Web 应用程序的客户端编码技术,主要用于教学目的。之后,它扩展了工程函数,并产生了非常受欢迎的在线工程计算器“VOLTA”。