Calculator: Mobile CSS, Corrected Trig Functionality (#4087)

* Enable history panel on mobile

* Namespace CSS rules, remove trailing spaces

* namespace all css rules

* cleanup indentation

* remove pete's css hacks

* Namespace additional css rules

* left align calculator with search box

* Implement full width mobile UI

* remove unused css

* remove unused ids

* Beter handling of history col for small screens

* Switch back to using on methd

* Fix trig regex and evaluation, remove precision

* Ensure subtitle overflows on left, prevent history item overflow

* Prevent subtitle text from being clipped

* Remove evalmath obj

* Updated conditional

* Add support for numpad period

* Fixed on start clear.

* Add postfix detection. Fixed infinity ledger.

* Removed Factorial BigNum hacks.

* Removed unnessesary code introduced.

* Fixed shift / clear issue.

* Remove undefined key strokes.

* Fix pi in exponents.

* Make return consistent.

* Fix broken history

* Apply user-select rules to desktop and mobile

* cleanup trailing spaces, commented out css

* Fix backspacing issue with operands.

* Remove console logs
master
Zaahir Moolla 2017-04-13 13:06:53 -04:00 committed by GitHub
parent 5f7defa0df
commit 3c784f2582
4 changed files with 354 additions and 320 deletions

View File

@ -1,49 +1,70 @@
/* Typography */
.zci--calculator,
.zci--calculator .tile__ctrl__btn,
.zci--calculator .tile__ctrl__toggle,
.zci--calculator .tile__skip-calc {
font-family: "DDG_ProximaNova","DDG_ProximaNova_UI_0","DDG_ProximaNova_UI_1","DDG_ProximaNova_UI_2","DDG_ProximaNova_UI_3","DDG_ProximaNova_UI_4","DDG_ProximaNova_UI_5","DDG_ProximaNova_UI_6","Proxima Nova","Helvetica Neue","Helvetica","Segoe UI","Nimbus Sans L","Liberation Sans","Open Sans",FreeSans,Arial,sans-serif;
font-family: "DDG_ProximaNova", "DDG_ProximaNova_UI_0", "DDG_ProximaNova_UI_1", "DDG_ProximaNova_UI_2", "DDG_ProximaNova_UI_3", "DDG_ProximaNova_UI_4", "DDG_ProximaNova_UI_5", "DDG_ProximaNova_UI_6", "Proxima Nova", "Helvetica Neue", "Helvetica", "Segoe UI", "Nimbus Sans L", "Liberation Sans", "Open Sans", FreeSans, Arial, sans-serif;
}
/* Show UI when CSS is loaded */
.tile--calculator {
.zci--calculator .tile--calculator {
display: block !important;
}
/* Layout */
.tile__calc {
.zci--calculator .zci__body {
padding-left: 0px;
}
.zci--calculator .tile__calc {
height: 352px;
}
.tile__calc__col {
.zci--calculator .tile__calc__col {
height: 251px;
width: 35%;
max-width: 295px; /* half width of search box */
float: left;
display: inline-block;
border-right: 1px solid #c8c8c8;
border-bottom: 1px solid #c8c8c8;
box-sizing: border-box;
}
/* Tabs */
.tile__calc .tile__tabs {
.zci--calculator .tile__calc .tile__tabs {
box-sizing: border-box;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* Controllers */
.tile__calc .tile__ctrl__btn,
.tile__calc .tile__ctrl__toggle {
.zci--calculator .tile__calc .tile__ctrl__btn,
.zci--calculator .tile__calc .tile__ctrl__toggle {
float: left;
position: relative;
box-sizing: border-box;
height: 50px;
}
/* Toggle */
.tile__calc .tile__ctrl__toggle {
.zci--calculator .tile__calc .tile__ctrl__toggle {
width: 50%;
padding: 15px 0;;
padding: 15px 0;
margin: 0;
background: #ebebeb;
border: 1px solid #c8c8c8;
@ -54,69 +75,68 @@
text-align: center;
}
/* The switch - the box around the slider */
.tile__ctrl__toggle-indicator {
position: relative;
display: inline-block;
width: 38px;
height: 14px;
.zci--calculator .tile__ctrl__toggle-indicator {
position: relative;
display: inline-block;
width: 38px;
height: 14px;
}
.tile__ctrl__toggle-indicator input {display:none;}
.tile__ctrl__toggle-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
.zci--calculator .tile__ctrl__toggle-indicator input {
display: none;
}
.tile__ctrl__toggle-slider:before {
position: absolute;
content: "";
height: 15px;
width: 15px;
left: 1px;
bottom: 0px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
.zci--calculator .tile__ctrl__toggle-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
/*
input:checked + .tile__ctrl__toggle-slider {
background-color: #2196F3;
}
*/
input:focus + .tile__ctrl__toggle-slider {
box-shadow: 0 0 1px #2196F3;
.zci--calculator .tile__ctrl__toggle-slider:before {
position: absolute;
content: "";
height: 15px;
width: 15px;
left: 1px;
bottom: 0px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .tile__ctrl__toggle-slider:before {
-webkit-transform: translateX(23px);
-ms-transform: translateX(23px);
transform: translateX(23px);
input:focus+.tile__ctrl__toggle-slider {
box-shadow: 0 0 1px #2196F3;
}
.tile__ctrl__toggle-slider.tile__ctrl__round-icon {
border-radius: 34px;
margin: 3px 0;
padding: 7px 0;
input:checked+.tile__ctrl__toggle-slider:before {
-webkit-transform: translateX(23px);
-ms-transform: translateX(23px);
transform: translateX(23px);
}
.tile__ctrl__toggle-slider.tile__ctrl__round-icon:before {
border-radius: 50%;
.zci--calculator .tile__ctrl__toggle-slider.tile__ctrl__round-icon {
border-radius: 34px;
margin: 3px 0;
padding: 7px 0;
}
.zci--calculator .tile__ctrl__toggle-slider.tile__ctrl__round-icon:before {
border-radius: 50%;
}
/* Buttons */
.tile__calc .tile__ctrl__btn {
.zci--calculator .tile__calc .tile__ctrl__btn {
width: 25%;
padding: 0;
margin: 0;
@ -129,49 +149,46 @@ input:checked + .tile__ctrl__toggle-slider:before {
font-size: 1.6em;
}
.tile__calc .tile__ctrl--double {
.zci--calculator .tile__calc .tile__ctrl--double {
width: 50%;
}
.tile__calc .tile__ctrl--ops,
.tile__calc .tile__tab__sci .tile__ctrl__btn {
.zci--calculator .tile__calc .tile__ctrl--ops,
.zci--calculator .tile__calc .tile__tab__sci .tile__ctrl__btn {
background: #ebebeb;
font-weight: lighter;
}
.tile__calc .tile__ctrl--important {
.zci--calculator .tile__calc .tile__ctrl--important {
background: #ffd90b;
font-family: "DDG_ProximaNova_UI_0","DDG_ProximaNova_UI_1","DDG_ProximaNova_UI_2","DDG_ProximaNova_UI_3","DDG_ProximaNova_UI_4","DDG_ProximaNova_UI_5","DDG_ProximaNova_UI_6","Proxima Nova","Helvetica Neue","Helvetica","Segoe UI","Nimbus Sans L","Liberation Sans","Open Sans",FreeSans,Arial,sans-serif;
font-family: "DDG_ProximaNova_UI_0", "DDG_ProximaNova_UI_1", "DDG_ProximaNova_UI_2", "DDG_ProximaNova_UI_3", "DDG_ProximaNova_UI_4", "DDG_ProximaNova_UI_5", "DDG_ProximaNova_UI_6", "Proxima Nova", "Helvetica Neue", "Helvetica", "Segoe UI", "Nimbus Sans L", "Liberation Sans", "Open Sans", FreeSans, Arial, sans-serif;
font-weight: lighter;
font-size: 2em;
padding-bottom: 0.1em;
}
/* Ctrl (Button, Toggle) */
.tile__calc .tile__ctrl__btn,
.tile__calc .tile__ctrl__toggle {
.zci--calculator .tile__calc .tile__ctrl__btn,
.zci--calculator .tile__calc .tile__ctrl__toggle {
cursor: pointer;
}
.tile__calc .tile__ctrl__btn:focus,
.tile__calc .tile__ctrl__toggle:focus,
.tile__calc .tile__ctrl__btn:active,
.tile__calc .tile__ctrl__toggle:active {
.zci--calculator .tile__calc .tile__ctrl__btn:focus,
.zci--calculator .tile__calc .tile__ctrl__toggle:focus,
.zci--calculator .tile__calc .tile__ctrl__btn:active,
.zci--calculator .tile__calc .tile__ctrl__toggle:active {
outline: 0;
}
.tile__calc .tile__ctrl__btn:focus,
.tile__calc .tile__ctrl__toggle:focus {
/*box-shadow: inset 0px 0px 5px #a5bdcb; /* TOREVISIT */*/
}
.no-touch .tile__calc .tile__ctrl__btn:hover,
.no-touch .tile__calc .tile__ctrl__toggle:hover {
background-color: #dadada;
}
.tile__calc .tile__ctrl__btn:active,
.tile__calc .tile__ctrl__toggle:active {
.zci--calculator .tile__calc .tile__ctrl__btn:active,
.zci--calculator .tile__calc .tile__ctrl__toggle:active {
background-color: #cacaca;
}
@ -179,12 +196,14 @@ input:checked + .tile__ctrl__toggle-slider:before {
background-color: #ddc750;
}
.tile__calc .tile__ctrl--important:active {
.zci--calculator .tile__calc .tile__ctrl--important:active {
background-color: #c8a900;
}
/* Accessibility skip handle */
.tile__calc .tile__skip-calc {
.zci--calculator .tile__calc .tile__skip-calc {
position: absolute;
opacity: 0;
pointer-events: none;
@ -195,14 +214,17 @@ input:checked + .tile__ctrl__toggle-slider:before {
font-size: 1em;
margin: 1px;
}
.tile__calc .tile__skip-calc:focus {
.zci--calculator .tile__calc .tile__skip-calc:focus {
pointer-events: all;
opacity: 1;
z-index: 1;
}
/* Input trap */
.tile__calc .tile__input-trap {
.zci--calculator .tile__calc .tile__input-trap {
position: absolute;
opacity: 0;
pointer-events: none;
@ -211,42 +233,54 @@ input:checked + .tile__ctrl__toggle-slider:before {
z-index: -9999;
}
/* Display */
.tile__calc .tile__display {
.zci--calculator .tile__calc .tile__display {
background: #fff;
border: 1px solid #c8c8c8;
border-bottom: 0;
padding: 0.8em;
box-sizing: border-box;
width: 70%;
max-width: 590px; /* Match width of search box */
border-right: 0;
height: 100px;
position: relative;
box-shadow: inset -1px -1px 0px #fff, inset 1px 1px 0px #fff;
transition: box-shadow 0.3s;
/* Text overflow */
text-align: right;
overflow: hidden;
white-space: nowrap;
}
.tile__calc .tile__input-trap:focus + .tile__display,
.tile__calc .tile__display:focus {
.zci--calculator .tile__calc .tile__input-trap:focus+.tile__display,
.zci--calculator .tile__calc .tile__display:focus {
box-shadow: inset -1px -1px 0px #61a0c7, inset 1px 1px 0px #61a0c7;
}
.tile__calc .tile__display__main,
.tile__calc .tile__display__aside {
text-align: right;
.zci--calculator .tile__calc .tile__display__aside--wrap {
position: relative;
overflow: hidden;
height: 1.3em;
}
.zci--calculator .tile__calc .tile__display__main,
.zci--calculator .tile__calc .tile__display__aside {
display: block;
}
.tile__calc .tile__display__aside {
.zci--calculator .tile__calc .tile__display__aside {
font-size: 1.1em;
letter-spacing: 0.025em;
color: #909090;
font-weight: lighter;
margin-top: -0.2em;
height: 1em;
position: absolute;
right: 0;
}
.tile__calc .tile__display__main {
.zci--calculator .tile__calc .tile__display__main {
color: #101010;
font-weight: lighter;
font-size: 2.5em;
@ -257,53 +291,36 @@ input:checked + .tile__ctrl__toggle-slider:before {
overflow: hidden;
white-space: nowrap;
outline: 0;
float: right;
}
/* Display EG */
.tile__calc .tile__display__main .tile__calc__eg {
box-sizing: border-box;
position: absolute;
left: 0;
top: 50%;
display: block;
height: 2px;
width: 2px;
overflow: hidden;
padding: 0;
background: #ffe1e1;
color: #fff;
font-weight: bold;
font-size: 0.3em;
letter-spacing: initial;
transition: 0.5s all 0.2s;
}
.tile__calc .tile__display__main:hover .tile__calc__eg {
transition-delay: 3.14s;
height: 1.6em;
width: 7em;
top: 0;
padding: 0.2em 0.3em;
background: #f07e7e;
text-align: center;
.zci--calculator .tile__calc .tile__display__main .pseudoBrace {
color: #d3d3d3;
}
/* Formula presentation: Big */
.tile__calc .tile__display__main sup {
.zci--calculator .tile__calc .tile__display__main sup {
top: -0.8em;
left: 0.1em;
padding-right: 0.2em;
}
.tile__calc .tile__display__main .formula__placeholder {
.zci--calculator .tile__calc .tile__display__main .formula__placeholder {
color: #909090;
}
/* Formula presentation: Small */
.tile__calc .tile__display__aside sup {
.zci--calculator .tile__calc .tile__display__aside sup {
top: -0.8em;
}
/* Calc display options */
.tile__calc .tile__options {
.zci--calculator .tile__calc .tile__options {
bottom: 0.4em;
padding: 0 0.8em;
width: 100%;
@ -312,8 +329,15 @@ input:checked + .tile__ctrl__toggle-slider:before {
position: absolute;
display: table;
box-sizing: border-box;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.tile__calc .tile__option {
.zci--calculator .tile__calc .tile__option {
transition: width 0.5s;
font-size: 0.8em;
width: auto;
@ -324,35 +348,43 @@ input:checked + .tile__ctrl__toggle-slider:before {
font-weight: 200;
letter-spacing: 0.03em;
}
.tile__calc .tile__option span {
cursor: pointer;
padding: 0.2em 0.5em;
margin: -0.5em;
}
.tile__calc .tile__option--active {
.tile__calc .tile__option span {
cursor: pointer;
padding: 0.2em 0.5em;
margin: -0.5em;
}
.zci--calculator .tile__calc .tile__option--active {
color: #54a3bb;
font-weight: 400;
}
.tile__calc .tile__option--active span {
cursor: default;
}
.tile__calc .tile__option__sci {
.tile__calc .tile__option--active span {
cursor: default;
}
.zci--calculator .tile__calc .tile__option__sci {
text-align: left;
}
.tile__calc .tile__option__basic {
.zci--calculator .tile__calc .tile__option__basic {
text-align: right;
}
.tile__calc .tile__option__history {
.zci--calculator .tile__calc .tile__option__history {
display: none;
text-align: right;
}
.tile__calc .tile__option:hover {
.zci--calculator .tile__calc .tile__option:hover {
text-decoration: none;
}
/* History tab */
.tile__calc .tile__history {
.zci--calculator .tile__calc .tile__history {
width: 30%;
background-color: #f9f9f9;
position: relative;
@ -366,12 +398,15 @@ input:checked + .tile__ctrl__toggle-slider:before {
overflow-y: auto;
transition: all 0.3s;
}
.tile__calc .tile__history--hidden {
.zci--calculator .tile__calc .tile__history--hidden {
width: 0px;
}
/* History item */
.tile__calc .tile__past-calc {
.zci--calculator .tile__calc .tile__past-calc {
box-sizing: border-box;
padding: 0.4em 0.6em 0.4em;
height: 50px;
@ -383,210 +418,213 @@ input:checked + .tile__ctrl__toggle-slider:before {
overflow: hidden;
transition: 0.5s all;
}
.tile__calc .tile__past-calc.tile__past-calc--hidden {
.zci--calculator .tile__calc .tile__past-calc.tile__past-calc--hidden {
height: 0px;
padding-top: 0;
padding-bottom: 0;
}
/******************/
/* TEXT SIZE ADJS */
/******************/
/* Largest */
.set-text--largest .tile__calc .tile__display__main {
font-size: 2em;
font-weight: 400;
}
.set-text--largest .tile__calc .tile__past-calc {
padding: 0.2em 0.4em;
}
.set-text--largest .tile__calc .zci--calculator .zci__main--detail {
max-width: 61.9em;
}
.set-text--largest .tile__calc .tile__past-result {
margin-top: -0.2em;
}
.tile__calc .tile__past-calc:hover {
.zci--calculator .tile__calc .tile__past-calc:hover {
background: #eee;
}
.tile__calc .tile__past-formula {
.zci--calculator .tile__calc .tile__past-formula {
display: block;
color: #aaa;
font-weight: 100;
font-size: 0.8em;
}
.tile__calc .tile__past-result {
.zci--calculator .tile__calc .tile__past-result {
font-weight: 700;
color: #191919;
font-size: 1.2em;
display: inline-block;
}
/* Big Widescreens >= 1200px (Default) */
.zci--calculator .zci__main {
max-width: 60em;
}
/*****************/
/* MEDIA QUERIES */
/*****************/
/* Monitors <= 1200 */
@media only screen and (min-width: 75em) {
.zci--calculator .zci__main {
padding-left: 90px;
}
}
/* Monitors with MQs >= 960 */
@media only screen and (min-width: 60em) {
.tile__calc .tile__options {
.zci--calculator .tile__calc .tile__options {
bottom: -1em;
}
}
/* Tablets <= 960 */
@media only screen and (max-width: 60em) {
/* show only one calc tab */
.tile__calc .tile__tabs {
.zci--calculator .tile__calc .tile__tabs {
overflow: hidden;
}
.tile__calc .tile__calc__col {
width: 310px;
.zci--calculator .tile__calc .tile__calc__col {
width: 295px;
}
/* default: basic tab */
.tile__calc .tile__tabs .tile__tab__sci /*:first-child*/ {
margin-left: -310px;
.zci--calculator .tile__calc .tile__tabs .tile__tab__sci {
margin-left: -295px;
}
.tile__calc .tile__display {
/*max-width: 21.6em;*/
max-width: 310px;
.zci--calculator .tile__calc .tile__display {
max-width: 295px;
}
.zci--calculator .zci__main--detail {
max-width: 43.8em;
}
.tile__calc .tile__history {
.zci--calculator .tile__calc .tile__history {
max-width: 295px;
transition: width 0.6s;
position: absolute;
}
/* show 3 tab options
.tile__calc .tile__display__main {
/* show 3 tab options */
.zci--calculator .tile__calc .tile__display__main {
margin-top: -0.2em;
} */
.tile__calc .tile__display .tile__options {
/*margin-top: 0em;*/
}
.tile__calc .tile__display .tile__option {
.zci--calculator .tile__calc .tile__display .tile__options {
margin-top: 0em;
}
.zci--calculator .tile__calc .tile__display .tile__option {
float: left;
}
.tile__calc .tile__display .tile__option__sci {
.zci--calculator .tile__calc .tile__display .tile__option__sci {
text-align: left;
}
.tile__calc .tile__display .tile__option__basic {
.zci--calculator .tile__calc .tile__display .tile__option__basic {
text-align: right;
}
}
/* Mobiles <= 740 */
@media only screen and (max-width: 46.25em) {
.tile__calc .tile__history {
width: 260px;
@media only screen and (max-width: 43.8em) {
.zci--calculator .tile__calc .tile__display {
width: 50%;
}
.zci--calculator .tile__calc .tile__calc__col {
width: 50%;
}
.zci--calculator .tile__calc .tile__history {
max-width: 260px;
}
}
/* Custom <= 660 */
/*@media only screen and (max-width: 42.8em) {*/
@media only screen and (max-width: 37.4em) {
.tile--calculator {
width: 100%;
box-sizing: border-box;
}
.tile__calc {
.zci--calculator .tile__calc {
overflow: hidden;
width: 310px;
width: 100%;
}
.tile__calc .tile__display {
.zci--calculator .tile__calc .tile__display {
width: 100%;
max-width: none;
border-right: 1px solid #d8d8d8;
}
.tile__calc .tile__tabs {
width: 930px;
.zci--calculator .tile__calc .tile__tabs {
width: 300%;
position: relative;
left: -310px; /* default: basic tab */
left: -100%;
/* default: basic tab */
transition: left 0.7s;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.tile__calc .tile__tabs.tile__tabs--single-basic {
left: -310px;
.zci--calculator .tile__calc .tile__tabs.tile__tabs--single-basic {
left: -100%;
}
.tile__calc .tile__tabs.tile__tabs--single-sci {
.zci--calculator .tile__calc .tile__tabs.tile__tabs--single-sci {
left: 0;
}
.tile__calc .tile__tabs.tile__tabs--single-history {
left: -620px;
.zci--calculator .tile__calc .tile__tabs.tile__tabs--single-history {
left: -200%;
}
.tile__calc .tile__calc__col {
.zci--calculator .tile__calc .tile__calc__col {
width: 33.33%;
max-width: 33.33%;
border-right: 1px solid #ccc;
}
.tile__calc .tile__tabs .tile__tab__sci:first-child {
.zci--calculator .tile__calc .tile__tabs .tile__tab__sci:first-child {
margin-left: 0;
}
.tile__calc .tile__history {
.zci--calculator .tile__calc .tile__history {
position: relative;
margin-left: 0;
margin-top: 0;
width: 310px;
width: 100%;
height: 251px;
}
/* 3 tab options */
/*
.tile__calc .tile__display .tile__option {
.zci--calculator .tile__calc .tile__display .tile__option {
width: 33%;
}
.tile__calc .tile__display .tile__option__basic {
.zci--calculator .tile__calc .tile__display .tile__option__basic {
text-align: center;
}
*/
.tile__calc .tile__display .tile__option__history {
.zci--calculator .tile__calc .tile__display .tile__option__history {
display: table-cell;
}
.is-mobile .zci--calculator .zci__body {
padding-right: 0px;
margin-left: -4px;
padding-left: 2px;
padding-right: 0;
}
}
/* Custom >= 660 & Tablets <= 960 */
@media only screen and (min-width: 37.4em) and (max-width: 60em) {
.tile__tabs.tile__tabs--single-sci .tile__tab__basic {
.zci--calculator .tile__tabs.tile__tabs--single-sci .tile__tab__basic {
width: 0;
}
.tile__tabs.tile__tabs--single-sci .tile__tab__sci {
.zci--calculator .tile__tabs.tile__tabs--single-sci .tile__tab__sci {
margin-left: 0;
}
.tile__tabs.tile__tabs--single-basic .tile__tab__basic {
}
.zci--calculator .tile__tabs.tile__tabs--single-basic .tile__tab__basic {}
}
@media only screen and (max-width: 21em) {
@ -597,27 +635,12 @@ input:checked + .tile__ctrl__toggle-slider:before {
}
}
/* Small mobiles <= 310 */
@media only screen and (max-width: 19.375em) {
.tile__calc .tile__history {
.zci--calculator .tile__calc .tile__history {
position: relative;
margin-top: 0;
}
}
/* pete's hacks */
/* allows the overflow */
#calculatorscreen {
text-align:right;
overflow:hidden;
white-space: nowrap;
}
#display {
float:right;
}
.pseudoBrace {
color: #d3d3d3;
}

View File

@ -8,7 +8,8 @@ DDH.calculator = DDH.calculator || {};
var FUNCTIONS = ["log(", "ln(", "tan(", "cos(", "sin("];
var MISC_FUNCTIONS = ["EE"];
var OPERANDS = ["+", "-", "×", "÷"];
var POSTFIX = ["+", "-", "×", "÷", "%", "EE", "!", "<sup>2</sup>", "<sup>3</sup>", "<sup>□</sup>"]
// global exponent constants
var OPEN_SUP = "<sup>";
var CLOSE_SUP = "</sup>";
@ -17,7 +18,6 @@ DDH.calculator = DDH.calculator || {};
// global variables
var buttons, cButton;
var evaluatedExpression;
var evalmath;
var usingState, evaluated;
var isExponential;
var yRootState = false;
@ -50,6 +50,7 @@ DDH.calculator = DDH.calculator || {};
106: "×",
107: "+",
109: "-",
110: ".",
111: "÷",
187: "=",
191: "÷",
@ -94,11 +95,11 @@ DDH.calculator = DDH.calculator || {};
* 7. tries to recover from user inputted faults (that make sense)
*/
function normalizeExpression( expression ) {
var expression = expression
return expression
// 1. handles +/- percentages
.replace(/(\+) (\d+(\.\d{1,2})?)%/g, PercentageNormalizer.addPercentage)
.replace(/(\d+(\.\d{1,2})?) \- (\d+(\.\d{1,2})?)%/g, PercentageNormalizer.subtractPercentage)
.replace(/(\d+(\.\d{1,2})?) - (\d+(\.\d{1,2})?)%/g, PercentageNormalizer.subtractPercentage)
.replace(/(\d+(\.\d{1,2})?)%/g, PercentageNormalizer.soloPercentage)
// 2. handles basic arithmetic
@ -117,16 +118,16 @@ DDH.calculator = DDH.calculator || {};
.replace(/(EE) (\d+(\.\d{1,})?)/g, RewriteExpression.ee)
// 5. handles scientific calculation functions
.replace(/\(?(\d+(\.\d{1,})?)\)?!/, RewriteExpression.factorial)
.replace(/log\((\d+(\.\d{1,})?)\)/, RewriteExpression.log10)
.replace(/ln\(/g, 'log(')
.replace(/(sin|cos|tan)\((\d+(\.\d+)?|πe)\)/g, RewriteExpression.trig)
.replace(/(sin|cos|tan)\((.+)\)/g, RewriteExpression.trig)
// 6. handles constants
.replace(/π/g, ' pi ')
.replace(/π/g, '(pi)')
// 7. last chance recovers
.replace(/<sup>□<\/sup>/g, '')
return expression;
}
/**
@ -191,6 +192,12 @@ DDH.calculator = DDH.calculator || {};
// isNan("23") --> false, isNan("NaN") --> true
isNan: function( total ) {
return total === NaN || total === "NaN";
},
// checks if an input element is in the POSTFIX constant array
// isPostfix("!") --> true, isPostfix("dax") --> false
isPostfix: function( element ) {
return $.inArray(element, POSTFIX) >= 0;
}
}
@ -210,13 +217,7 @@ DDH.calculator = DDH.calculator || {};
// exponent: rewrites the exponent(s) in given expression
exponent: function( _expression, number ) {
return "^" + number;
},
// factorial: rewrites a factorial expression to take a number (not BigNum)
// factorial("10.5!") --> `number("10.5")!`
factorial: function( _expression, number ) {
return "number(" + number + ")!";
return "^(" + number + ")";
},
// log10: rewrites log (base 10) function(s) in the expression
@ -231,11 +232,12 @@ DDH.calculator = DDH.calculator || {};
// trig: rewrites trig functions to handle the different outputs (RAD | DEG)
trig: function( _expression, func, number ) {
var unit = ''
if($('input#tile__ctrl__toggle-checkbox').is(':checked')) {
return "round(" + func + "(" + number + " deg), 11)";
} else {
return "round(" + func + "(" + number + "), 11)";
unit = ' deg';
}
var wrappedNum = "(" + number + ")";
return "round(" + func + "(" + wrappedNum + unit + "), 11)";
},
// yRoot: rewrites yth root of x expressions
@ -340,7 +342,7 @@ DDH.calculator = DDH.calculator || {};
* bracket is instanciated, a pseudo closing place is put into the display.
* There are cases where the user doesn't bother to close the bracket themselves.
* This object also provides expression parsing to recover from such instances.
*
*
* TODO: Support parens in an exponential state
*/
var ParenManager = {
@ -449,42 +451,36 @@ DDH.calculator = DDH.calculator || {};
ParenManager.reset();
}
// a hack for the BigNumber factorial issue
// If the expression contains a number bigger than 1,000,000! then bail
if(/([1-9]\d{6,}).?!/.test(display.value)) {
display.value = "Infinity";
}
isExponential = false;
try {
var total = evalmath.eval(
var total = math.eval(
normalizeExpression(display.value)
).toString()
} catch(err) {
// console.log(err);
display.value = "Error";
ExpressionParser.setExpression();
setCButtonState("C");
return false;
}
if(Utils.isInfinite(total)) {
display.innerHTML = "Infinity";
display.value = "";
setCButtonState("C");
return false;
} else if(Utils.isNan(total)) {
if(Utils.isNan(total)) {
display.value = "Error";
setCButtonState("C");
return false;
}
ExpressionParser.setExpression(display.value);
Ledger.addToHistory(display.value, DDG.commifyNumber(total));
if(Utils.isInfinite(total)) {
ExpressionParser.setExpression(display.value);
Ledger.addToHistory(display.value, DDG.commifyNumber(total));
display.value = "Infinity";
} else {
ExpressionParser.setExpression(display.value);
Ledger.addToHistory(display.value, DDG.commifyNumber(total));
display.value = total;
}
display.value = total;
evaluated = true;
setCButtonState("C");
yRootState = false;
@ -492,16 +488,16 @@ DDH.calculator = DDH.calculator || {};
/**
* Clear
*
*
* This fat function handles backspacing through the `display.value`. `display.value`
* is the *string* representation of the expression that is used throughout the calculator.
* It needs to take into consideration the key / button pressed and the state of the
* calculator.
*
*
* A calculator has a lot of edge cases, many of which are hard to account for in
* advance. Many of these hueristics were developed through trail and error and
* logical deduction.
*
* logical deduction.
*
* TODO: Refactor nested ifs. What is the best way to do this and handle edge cases?
*/
function clear( element ) {
@ -519,7 +515,7 @@ DDH.calculator = DDH.calculator || {};
ExpressionParser.setExpression();
setCButtonState("C");
ParenManager.reset();
// CE clears one step at a time base on the state and the length of expression
} else if(element === "CE" ) {
ExpressionParser.setExpression();
@ -528,32 +524,40 @@ DDH.calculator = DDH.calculator || {};
if (ExpressionParser.getExpressionLength() > 1 && ( Utils.isMathFunction(display.value.substr(-4, 4)) || Utils.isMathFunction(display.value.substr(-3, 3)))) {
ExpressionParser.backspace(4);
ParenManager.decrementTotal();
// if last element is an open paren, backspace 1
} else if(display.value.substr(-1, 1) === "(") {
ExpressionParser.backspace(1);
ParenManager.decrementTotal();
// if there is an operand in the second last character in expression, backspace 3
} else if (ExpressionParser.getExpressionLength() > 1 && Utils.isOperand(display.value.substr(-2, 2)) ) {
ExpressionParser.backspace(3);
// if there is an operand in the last character in expression, backspace 2
} else if (ExpressionParser.getExpressionLength() > 1 && Utils.isOperand(display.value.substr(-1, 1)) ) {
ExpressionParser.backspace(2);
// if last element is a closed paren, backspace 1
} else if(display.value.substr(-1, 1) === ")") {
ExpressionParser.backspace(1);
ParenManager.incrementTotal();
// Backspace 2 if the last 2 characters are a constant (pi, e)
} else if(ExpressionParser.getExpressionLength() > 1 && Utils.isConstant(display.value.substr(-2, 2).trim()) ) {
ExpressionParser.backspace(2);
// Backspace 3 if last characters are `EE `
} else if(ExpressionParser.getExpressionLength() > 1 && display.value.substr(-3, 3) === "EE ") {
ExpressionParser.backspace(3);
// If last 12 characters are `<sup>□</sup>`, backspace 12
} else if(ExpressionParser.getExpressionLength() > 1 && display.value.substr(-12, 12) === OPEN_CLOSE_SUP) {
ExpressionParser.backspace(12);
isExponential = false;
// ~~ nth square root ~~
// if nth square root with no digits, pop last element, replace with nothin and re-append popped element
// if nth square root with no digits, pop last element, replace with nothin and re-append popped element
} else if(/<sup>□<\/sup>√\d+$/.test(display.value)) {
var expression = display.value.split(" ");
var last_element = expression.pop();
@ -561,7 +565,7 @@ DDH.calculator = DDH.calculator || {};
expression.push(last_element);
display.value = expression.join(" ");
yRootState = false;
// if nth square root with 1 digit, pop last element, replace with `<sup>□</sup>`, reappend popped element
} else if(/<sup>\d{1}<\/sup>√\d+$/.test(display.value)) {
var expression = display.value.split(" ");
@ -569,33 +573,33 @@ DDH.calculator = DDH.calculator || {};
last_element = last_element.replace(/<sup>\d{1}<\/sup>/g, OPEN_CLOSE_SUP);
expression.push(last_element);
display.value = expression.join(" ");
// if ends with `<sup>□</sup>`, backspace 12
} else if(/<sup>\d{1}<\/sup>$/.test(display.value)) {
ExpressionParser.backspace(12);
display.value = display.value + OPEN_CLOSE_SUP;
// if `<sup></sup>` has numbers, backspace through the last number and reappend `</sup>`
} else if(/<sup>\d+<\/sup>$/.test(display.value)) {
ExpressionParser.backspace(7);
display.value = display.value + CLOSE_SUP;
// backspace 2 if last char is ` ` and 2nd last char is numeric
} else if(ExpressionParser.getExpressionLength() > 1 && (display.value[display.value.length-1] === " " && Utils.isNumber(display.value[display.value.length-2]))) {
ExpressionParser.backspace(2);
// backspace 1 if 2nd last char is not equal to ` `
} else if (ExpressionParser.getExpressionLength() > 1 && display.value[display.value.length-2] !== " ") {
ExpressionParser.backspace(1);
// backspace 2 if 2nd last char is ` ` and 3rd last is an operand (+, -, x, etc)
} else if(ExpressionParser.getExpressionLength() > 1 && (display.value[display.value.length-2] === " " && Utils.isOperand(display.value[display.value.length-3]))) {
ExpressionParser.backspace(2);
// if 2nd last char is ` `
} else if(ExpressionParser.getExpressionLength() > 1 && display.value[display.value.length-2] === " ") {
ExpressionParser.backspace(1);
// if expression length is 1, then reset the display value and expression, and set cButton to state `C`
} else if (ExpressionParser.getExpressionLength() === 1) {
display.value = "";
@ -611,7 +615,8 @@ DDH.calculator = DDH.calculator || {};
// if all else fails, back space 1
ExpressionParser.backspace(1);
}
}
}
/**
* ~~ THE MAIN ENTRY POINT ~~
@ -630,12 +635,14 @@ DDH.calculator = DDH.calculator || {};
}
// handles the display like a normal calculator
if(evaluated === true && Utils.isNumber(element) ) {
// If a new number / function / clear, bail and start new calculation
if(evaluated === true && (Utils.isNumber(element) || Utils.isMathFunction(element) || Utils.isConstant(element) || Utils.isClear(element)) ) {
ExpressionParser.setExpression("Ans: " + display.value);
display.value = "";
usingState = false;
evaluated = false;
} else if(evaluated === true && (!Utils.isOperand(element) && !Utils.isClear(element) && !Utils.isMiscMathFunction(element) && element !== "<sup>□</sup>" && element !== "!")) {
// if evaluated and new input is a postfix operand, continue on.
} else if(evaluated === true && !Utils.isPostfix(element)) {
return false;
} else {
evaluated = false;
@ -806,20 +813,6 @@ DDH.calculator = DDH.calculator || {};
usingState = false;
display.value = displayValue;
/**
* The math.js object
*
* evalmath is the global math.js object that is used throughout this codebase
* to evaluate the infix expression that the user provides via the calculators
* interface.
*/
evalmath = math.create({
// helps with rounding issues. The exception is trig functions
// where it is rewritten as a number. See: `RewriteExpression.trig`
number: 'BigNumber',
precision: 11
});
/**
* Bind the buttons
*
@ -860,12 +853,23 @@ DDH.calculator = DDH.calculator || {};
* The calculator has a collapsed view when the user is viewing the device
* on a mobile device. The following two functions handle the touch events.
*/
$("#sci-tab").bind('touchstart', function() {
$(".tile__calc .tile__tabs").css("left", "0");
});
$('.tile__options .tile__option span').click(function(e) {
var $tabHandle = $(this).parent();
if ($tabHandle.hasClass('tile__option--active')) {
return;
}
$("#basic-tab").bind('touchstart',function() {
$(".tile__calc .tile__tabs").css("left", "-310px");
$('.tile__options .tile__option').removeClass('tile__option--active');
$tabHandle.toggleClass('tile__option--active');
var activeTab = $('.tile__options .tile__option.tile__option--active').data('tab');
$('.tile__tabs')
.removeClass(function (index, css) {
return (css.match(/(^|\s)tile__tabs--single-[a-z]+/g) || []).join(' ');
})
.addClass('tile__tabs--single-'+activeTab);
});
/**
@ -886,6 +890,10 @@ DDH.calculator = DDH.calculator || {};
evt = SHIFT_KEYCODES[key];
}
if(evt === undefined) {
return false;
}
calculator(evt);
setFocus();
e.stopImmediatePropagation();
@ -893,7 +901,7 @@ DDH.calculator = DDH.calculator || {};
/**
* Handles clicking on history items
*
*
* If an item is clicked in the ledger section, the expression and result are loaded
* and passed to the Ledger object where it resets the calculators state and result
*/

View File

@ -3,18 +3,21 @@
<div class="tile__calc clearfix">
<button class="tile__skip-calc">Skip calculator</button>
<button class="tile__input-trap"></button>
<div class="tile__display" id="calculatorscreen">
<span class="tile__display__aside" id="expression">{{{subtitle}}}</span>
<div class="tile__display">
<div class="tile__display__aside--wrap">
<span class="tile__display__aside" id="expression">{{{subtitle}}}</span>
</div>
<span class="tile__display__main" id="display" tabindex="0">{{{title_html}}}</span>
<ul class="tile__options">
<li class="tile__option tile__option__sci" id="sci-tab" data-tab="sci"><span>Scientific</span></li>
<li class="tile__option tile__option__basic tile__option--active" id="basic-tab" data-tab="basic"><span>Basic</span></li>
<!-- <li class="tile__option tile__option__history" data-tab="history"><span>History</span></li> // introducing in phase 3 // -->
<li class="tile__option tile__option__sci" data-tab="sci"><span>Scientific</span></li>
<li class="tile__option tile__option__basic tile__option--active" data-tab="basic"><span>Basic</span></li>
<li class="tile__option tile__option__history" data-tab="history" ><span>History</span></li>
</ul>
</div>
<div class="tile__tabs">
<div class="tile__calc__col tile__tab__sci">
<span class="tile__ctrl__toggle">
<span>RAD</span>
@ -47,7 +50,7 @@
<button class="tile__ctrl__btn" data-cmd="FN_POW_E" value="e<sup>□</sup>">e<sup>x</sup></button>
<button class="tile__ctrl__btn" data-cmd="CONST_E" value="e">e</button>
</div>
<!-- basic calculations -->
<div class="tile__calc__col tile__tab__basic">
<button class="tile__ctrl__btn tile__ctrl--double" id="clear_button" data-cmd="META_CLEAR" value="C">C</button>
@ -73,10 +76,10 @@
<button class="tile__ctrl__btn" value=".">.</button>
<button class="tile__ctrl__btn tile__ctrl--important" data-cmd="META_PROCEED" value="=">=</button>
</div>
<!-- the ledger (history) section of the calculators UI -->
<ul class="tile__calc__col tile__history"></ul>
</div>
</div>
</div>
</div>

View File

@ -1,4 +1,4 @@
<li class="tile__past-calc tile__past-calc__tpl">
<span class="tile__past-formula">{{{ expression }}}</span>
<span class="tile__past-result">{{ result }}</span>
</li>
<span class="tile__past-formula one-line">{{{ expression }}}</span>
<span class="tile__past-result one-line">{{ result }}</span>
</li>