not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

319 lines
10 KiB

//This is the CalculateApp object, providing a full context for the app
var CalculateApp = {
/* UI Elements */
elements: {
resultsZoneDiv: undefined,
calcInputDiv: undefined,
calcInput: undefined,
labelInput: undefined,
modalDiv: undefined
},
/* libraries loaded by require */
libs: {
mustache: undefined,
functionPlot: undefined
},
/* Application data */
data: {
buddyColor: {
stroke: "#1500A7",
fill: "#ff0000"
},
calculations: [],
windowWidth: undefined,
windowHeight: undefined,
isMobile: /iphone|ipod|ipad|android|blackberry|opera mini|opera mobi|skyfire|maemo|windows phone|palm|iemobile|symbian|symbianos|fennec/i.test(navigator.userAgent.toLowerCase()),
isIos: (navigator.userAgent.match(/iPad|iPhone|iPod/g) ? true : false ),
outputBase: 10,
outputDigits: 6,
isRadian: false,
pi: 3.141592653589793
},
/* Return if Chrome WebApp env. Chrome WebApp does not allow eval. */
isFullMode: function fullModeEval() {
if (typeof chrome != "undefined" && chrome.app && chrome.app.runtime) {
return false;
}
return true;
}(),
/* Evaluate a calculation without using eval() */
evalParser: function(input) {
var result = Parser.parse(input).evaluate();
return result;
},
/* Evaluate a calculation using eval() - provides advanced features */
evalMathJS: function(input) {
var result = mathjs.eval(input);
return result;
},
/* Auto eval using light or full mode */
eval: function(input) {
var result;
var resultBase10;
if (CalculateApp.isFullMode) {
result = CalculateApp.evalMathJS(input);
resultBase10 = CalculateApp.baseConv(CalculateApp.evalMathJS(input), CalculateApp.data.outputBase, 10);
} else {
result = CalculateApp.evalParser(input);
resultBase10 = CalculateApp.baseConv(CalculateApp.evalParser(input), CalculateApp.data.outputBase, 10);
}
return {
resultBase10: CalculateApp.toFixed(result, CalculateApp.data.outputDigits),
result: CalculateApp.toFixed(resultBase10, CalculateApp.data.outputDigits)
};
},
/* Calcul f(x) with x = 0 using light or full mode*/
evalFunctionAtZero: function(input) {
var result;
if (CalculateApp.isFullMode) {
try {
result = mathjs.eval(input)(0);
if (isNaN(result) || !isFinite(result)) {
return 0;
}
return result;
} catch (error) {
return 0;
}
} else {
try {
result = Parser.parse(input).evaluate({
x: 0
});
if (isNaN(result) || !isFinite(result)) {
return 0;
}
return result;
} catch (error) {
return 0;
}
}
},
/* Check if simple calculation or function */
isGraph: function(input) {
if (input.indexOf("f(x)") == -1) {
return false;
}
return true;
},
/* Display a graph */
_graph: function(equation, valueForZero, graphFn) {
nanoModal(CalculateApp.elements.modalDiv, {
buttons: [],
}).onShow(function(m) {
CalculateApp.elements.modalDiv.style.display = "block";
CalculateApp.elements.modalDiv.style.marginLeft = "auto";
CalculateApp.elements.modalDiv.style.marginRight = "auto";
CalculateApp.elements.modalDiv.style.height = parseInt(CalculateApp.data.windowHeight * 80 / 100) + "px";
CalculateApp.elements.modalDiv.style.width = parseInt(CalculateApp.data.windowWidth * 80 / 100) + "px";
try {
var openedModal = CalculateApp.libs.functionPlot({
target: '#plot',
yDomain: [valueForZero - 10, valueForZero + 10],
xDomain: [-10, 10],
width: parseInt(CalculateApp.data.windowWidth * 80 / 100),
height: parseInt(CalculateApp.data.windowHeight * 80 / 100),
data: [{
fn: graphFn
}]
});
for (var i = 0; i < 10; i++) {
window.scroll(0, 0);
}
} catch (err) {
m.hide();
}
}).onHide(function(m) {
m.remove();
setTimeout(function() {
CalculateApp.focus();
}, 300);
}).show();
},
/* Display a graph using light mode */
graphParser: function(equation) {
var valueForZero = CalculateApp.evalFunctionAtZero(equation);
var graphFn = function(x) {
return Parser.parse(equation).evaluate({
"x": x
});
};
CalculateApp._graph(equation, valueForZero, graphFn);
},
/* Display a graph using full mode */
graphMathJS: function(equation) {
var valueForZero = CalculateApp.evalFunctionAtZero(equation);
var graphFn = mathjs.eval(equation);
CalculateApp._graph(equation, valueForZero, graphFn);
},
/* Display a graph using light or full mode */
graph: function(input) {
input = CalculateApp.tryPatchGraphEquation(input);
if (CalculateApp.isFullMode) {
return CalculateApp.graphMathJS(input);
} else {
return CalculateApp.graphParser(input);
}
},
/* Display a calculation */
displayCalculation: function(calculation) {
var node = document.createElement("div");
if (calculation.error) {
node.innerHTML = CalculateApp.libs.mustache.render(getErrorTemplate(), calculation);
} else {
if (calculation.graph) {
node.innerHTML = CalculateApp.libs.mustache.render(getGraphTemplate(), calculation);
var childrens = node.childNodes[0].childNodes;
var functionGraph = function(input) {
CalculateApp.graph(input.target.value);
};
for (var i = 0; i < childrens.length; i++) {
if (childrens[i].tagName === "BUTTON") {
childrens[i].addEventListener('click', functionGraph);
}
}
} else {
node.innerHTML = CalculateApp.libs.mustache.render(getResultTemplate(), calculation);
}
}
CalculateApp.elements.resultsZoneDiv.insertBefore(node, CalculateApp.elements.resultsZoneDiv.childNodes[0]);
},
/* Add calculation to list */
storeCalculation: function(calculation) {
if(CalculateApp.data.calculations === null){
CalculateApp.data.calculations = [];
}
CalculateApp.data.calculations.push(calculation);
},
/* Persist calculation lists */
persistCalculations: function() {
var calculationsToSave = [];
for (var i = CalculateApp.data.calculations.length - 1; i >= 0; i--) {
if (calculationsToSave.length >= 20) {
break;
}
calculationsToSave.unshift(CalculateApp.data.calculations[i]);
}
var json = JSON.stringify(calculationsToSave);
CalculateApp.libs.activity.getDatastoreObject().setDataAsText(json);
CalculateApp.libs.activity.getDatastoreObject().save(function() {});
},
/* Base convert */
baseConv: function(number, to, from) {
if (to == from) {
return number;
}
return parseInt(number, from || 10).toString(to);
},
/* Handle window resize */
onResize: function() {
CalculateApp.data.windowHeight = getWindowHeight();
CalculateApp.data.windowWidth = getWindowWidth();
setTimeout(function() {
CalculateApp.elements.resultsZoneDiv.style.height = CalculateApp.elements.calcInputDiv.clientHeight + "px";
CalculateApp.elements.resultsZoneDiv.style.display = "block";
}, 300);
},
/* Focus only if computer */
focus: function() {
if (!CalculateApp.data.isMobile) {
CalculateApp.elements.calcInput.focus();
}
},
/* Translation of the Gui */
transateGui: function() {
if (CalculateApp.libs.webL10n.get("calcul") !== undefined && CalculateApp.libs.webL10n.get("calcul").length > 0) {
CalculateApp.elements.calcInput.placeholder = CalculateApp.libs.webL10n.get("calcul");
}
if (CalculateApp.libs.webL10n.get("label") !== undefined && CalculateApp.libs.webL10n.get("label").length > 0) {
CalculateApp.elements.labelInput.placeholder = CalculateApp.libs.webL10n.get("label");
}
if (CalculateApp.libs.webL10n.get("clear") !== undefined && CalculateApp.libs.webL10n.get("clear").length > 0) {
CalculateApp.elements.calcButtonClear.innerHTML = CalculateApp.libs.webL10n.get("clear");
}
},
/* We clear the result box and display all previous calculations */
displayAllCalculations: function() {
while (CalculateApp.elements.resultsZoneDiv.firstChild) {
CalculateApp.elements.resultsZoneDiv.removeChild(CalculateApp.elements.resultsZoneDiv.firstChild);
}
if(CalculateApp.data.calculations !== null){
for (var i = 0; i < CalculateApp.data.calculations.length; i++) {
CalculateApp.displayCalculation(CalculateApp.data.calculations[i]);
}
}
},
/* We try to patch the equation to handle things like degree to radians conversion */
tryPatchEquation: function(equation) {
if (CalculateApp.data.isRadian) {
return equation;
}
var matchingFunctions = [
"cos",
"sin",
"tan",
"acos",
"asin",
"atan",
"cosh",
"sinh",
"tanh"
];
for (var i = 0; i < matchingFunctions.length; i++) {
var regex = new RegExp(matchingFunctions[i] + "\\((.+?)\\)", "gi");
var results = equation.match(regex);
if (results) {
for (var j = 0; j < results.length; j++) {
var parenthesisRegex = new RegExp("\\(([^\\)]+)\\)", "gi");
var arrayToReplace = parenthesisRegex.exec(results[j]);
if (arrayToReplace && arrayToReplace.length >= 2) {
equation = equation.replace(arrayToReplace[1], arrayToReplace[1] + " * " + CalculateApp.data.pi + " / 180");
}
}
}
}
return equation;
},
/* We try to patch the equation to make the graph working on both full mode and light mode */
tryPatchGraphEquation: function(question) {
if (!CalculateApp.isFullMode) {
question = question.replace("f(x)=", "");
}
return question;
},
/* Simple toFixed method to format the output with max digits */
toFixed: function(value, precision) {
if (isNaN(value) || (Number(value) === value && value % 1 === 0)) {
return value;
}
var power = Math.pow(10, precision || 0);
return String(Math.round(value * power) / power);
}
};