The title of this question is probably wrong, but i can't think of how to name it.
I'm trying to build a simple calculator using AngularJS. Right now its functioning, but i'm trying to add some other buttons. I want a "delete" key and a decimal key. The delete key is what i'm focused on now.
If someone clicks, 3, then 3 again. we have 33. (this calculator currently, can only accept a left and right operand, and an operator separating them (ex, 3+3, or 56*486, etc). not multiple operators or operands). Now say the user were to enter 334, but they want the 4 taken off because they meant to click 5. How do I use javascript to delete the most recent number if an operator or equals hasn't been pressed?
If i had to guess, it's going to be something like this:
$scope.deleteNumb = function(d){
if(!$scope.operator){
// if no operator, delete most recent left operand
}
else{ //delete most recent right operand}
}
};
The "C" button doesn't work. I had that set up as "Clear" which refreshed the page to start a new calculation. I need a way to figure out how to delete the existing answer without using location.reload();
So the main thing here, is trying to delete the recent most operand, whether it be left or right, depending if an operator has been clicked or not.
My code is here:
https://codepen.io/tevon/pen/Moewba
For clear (C) did you try to clear all values in setClear
$scope.setClear = function (a) {
$scope.leftOperand = "";
$scope.operator = "";
$scope.rightOperand = "";
$scope.answer = "";
};
to delete a part of your number; have a look to substr as your input is a string :
For exemple :
$scope.removeBtn = function(){
var tmp = $scope.leftOperand;
console.warn("test",tmp)
$scope.leftOperand = tmp.substr(0,tmp.length-1);
}
This function removes the last number of your leftOperand.
Adapt it to your need for left/right
$scope.setClear = function (a) {
// $scope.clear = location.reload();
var result = $scope.leftOperand + $scope.operator + $scope.rightOperand;
result = result.substring(0, result.length - 1);
if ($scope.operator){
$scope.rightOperand = result;
}
else {
$scope.leftOperand = result;
}
};
Not tested.. Would have to tweak a little when operators come i guess
Related
World!
I'm trying to create a program in Javascript that takes the log of a number typed into an HTML input. Unfortunately i've encountered a problem where it wont accept the string with the .replace().
Its Function:
I.E: When log(10) is calculated, the function should first remove the first 4 char's "log(" next remove the last parenthesis ")" and then take the log of the no. between.
HTML includes style elements, button and input form and an output < DIV >.
//Function
function calculate()
{
var inputString = document.getElementById("inpstr");
var output = document.getElementById("output");
//TESTING CODE
/*
if (inputString.value.startsWith("log(").endsWith(")"))
{
console.log(output.innerHTML = inputString.value.substring(4, 20).replace(")", ""));
}
else
{
output.innerHTML = "false";
}
*/
//Math.log() calc *****DOESNT WORK*****
if (inputString.value.startsWith("log(").endsWith(")"))
{
output.innerHTML = Math.log(inputString.value.replace(")", "").substring(4, 20));
}
else
{
output.innerHTML = inputString.value;
}
event.preventDefault();
}
If someone can give me an effective solution that would be much appreciated.
Thanks,
Syntax
Since Math.log() accepts only number values and you're trying to pass a string to it, you should first parse this value into a float number and then pass it to the log function:
let val = parseFloat(inputString.value.replace(")", "").substring(4, 20));
output.innerHTML = Math.log(val);
I'm guessing I got downvoted for being lazy, so here is the quick info. Gonras got it right relating to what you want to extract, but he forgot to check that what's being input is actually a log.
That's where the regex below comes in handy! I'm matching the field to:
^ start of word, since we want to match the entire field.
log(
([-.\d])) any consecutive sequence () of numbers (\d), -, and '.', represented by the []. The \(...\) makes sure to save this inner part for later.
$ is end of word, see 1.
res will be null if there is no match. Otherwise, res[0] is the entire match (so the entire input field) and res[1] is the first 'capture group', at point 3 - which is presumably the number.
This of course fails for multiple "-" inside, or "." etc... so think it over.
//Function
function calculate()
{
var inputString = document.getElementById("inpstr");
var output = document.getElementById("output");
var res = /^log\(([-.\d]*)\)$/.exec(inputString.value);
if (res)
output.innerHTML = Math.log(res[1]);
else
output.innerHTML = res;
}
document.getElementById("output").innerHTML='start';
calculate()
<div id='output'></div>
<input id='inpstr' value='log(2.71828)'></input>
If I wanted to fix your if to supplement Gonras's solution:
if (inputString.value.startsWith("log(") && inputString.value.endsWith(")"))
Yours fails since startsWith() returns a boolean, which obviously doesn't have a endsWith function.
I'm working on my final project of the Winter 2017 quarter to demonstrate how to use Regular Expressions in both C# and JavaScript code behind pages. I've got the C# version of my demonstration program done, but the JavaScript version is making me pull what little hair I have left on my head out (no small achievement since I got a fresh buzz cut this morning!). The problem involves not getting any output after applying a Regular Expression in a While loop to get each instance of the expression and printing it out.
On my HTML page I have an input textarea, seven radio buttons, an output textarea, and two buttons underneath (one button is to move the output text to the input area to perform multiple iterations of applying expressions, and the other button to clear all textareas for starting from scratch). Each radio button links to a function that applies a regular expression to the text in the input area. Five of my seven functions work; the sixth is the one I can't figure out, and the seventh is essentially the same but with a slightly different RegEx pattern, so if I fix the sixth function, the seventh function will be a snap.
(I tried to insert/upload a JPG of the front end, but the photo upload doesn't seem to be working. Hopefully you get the drift of what I've set up.)
Here are my problem children from my JS code behind:
// RegEx_Demo_JS.js - code behind for RegEx_Demo_JS
var inputString; // Global variable for the input from the input text box.
var pattern; // Global variable for the regular expression.
var result; // Global variable for the result of applying the regular expression to the user input.
// Initializes a new instance of the StringBuilder class
// and appends the given value if supplied
function StringBuilder()
{
var strings = [];
this.append = function (string)
{
string = verify(string);
if (string.length > 0) strings[strings.length] = string;
}
this.appendLine = function (string)
{
string = verify(string);
if (this.isEmpty())
{
if (string.length > 0) strings[strings.length] = string;
else return;
}
else strings[strings.length] = string.length > 0 ? "\r\n" + string : "\r\n";
}
this.clear = function () { strings = []; };
this.isEmpty = function () { return strings.length == 0; };
this.toString = function () { return strings.join(""); };
var verify = function (string)
{
if (!defined(string)) return "";
if (getType(string) != getType(new String())) return String(string);
return string;
}
var defined = function (el)
{
// Changed per Ryan O'Hara's comment:
return el != null && typeof(el) != "undefined";
}
var getType = function (instance)
{
if (!defined(instance.constructor)) throw Error("Unexpected object type");
var type = String(instance.constructor).match(/function\s+(\w+)/);
return defined(type) ? type[1] : "undefined";
}
}
Within the code of the second radio button (which will be the seventh and last function to complete), I tested the ScriptBuilder with data in a local variable, and it ran successfully and produced output into the output textarea. But I get no output from this next function that invokes a While loop:
function RegEx_Match_TheOnly_AllInstances()
{
inputString = document.getElementById("txtUserInput").value;
pattern = /(\s+the\s+)/ig; // Using an Flag (/i) to select either lowercase or uppercase version. Finds first occurrence either as a standalone word or inside a word.
//result = pattern.exec(inputString); // Finds the first index location
var arrResult; // Array for the results of the search.
var sb = getStringBuilder(); // Variable to hold iterations of the result and the text
while ((arrResult = pattern.exec(inputString)) !==null)
{
sb.appendLine = "Match: " + arrResult[0] ;
}
document.getElementById("txtRegExOutput").value = sb.toString();
/* Original code from C# version:
// string pattern = #"\s+(?i)the\s+"; // Same as above, but using Option construct for case insensitive search.
string pattern = #"(^|\s+)(?i)the(\W|\s+)";
MatchCollection matches = Regex.Matches(userTextInput, pattern);
StringBuilder outputString = new StringBuilder();
foreach (Match match in matches)
{
string outputRegExs = "Match: " + "\"" + match.Value + "\"" + " at index [" + match.Index + ","
+ (match.Index + match.Length) + "]" + "\n";
outputString.Append(outputRegExs);
}
txtRegExOutput.Text = outputString.ToString();
*/
} // End RegEx_Match_The_AllInstances
I left the commented code in to show what I had used in the C# code behind version to illustrate what I'm trying to accomplish.
The test input/string I used for this function is:
Don’t go there. If you want to be the Man, you have to beat The Man.
That should return two hits. Ideally, I want it to show the word that it found and the index where it found the word, but at this point I'd be happy to just get some output showing every instance it found, and then build on that with the index and possibly the lastIndex.
So, is my problem in my While loop, the way I'm applying the StringBuilder, or a combination of the two? I know the StringBuilder code works, at least when not being used in a loop and using some test data from the site I found that code. And the code for simply finding the first instance of "the" as a standalone or inside another word does work and returns output, but that doesn't use a loop.
I've looked through Stack Overflow and several other JavaScript websites for inspiration, but nothing I've tried so far has worked. I appreciate any help anyone can provide! (If you need me to post any other code, please advise and I'll be happy to oblige.)
So the problem I am having is that whenever I try to make the to.Fixed(2); at the end of my g_fTotal I get a lint error and it also doesn't show up in the txtTotal field. IT shows up in the filed when I take the toFixed off but I need to have the total show only two decimal points. What am I doing wrong here?
// DO IT: Assign the total to the txtTotal textbox. Include a dollar sign and use .toFixed() to display 2 decimal places
document.getElementById("txtTotal").value = "$" + g_fTotal.toFixed(2);
This is the whole code below.
// DO NOT DELETE ANYTHING IN THIS FILE
/*jsl:option explicit*/
/*jsl:declare $*//*jsl:declare addEventListener*//*jsl:declare isDigits*//*jsl:declare alert*//*jsl:declare blur*//*jsl:declare clearInterval*//*jsl:declare clearTimeout*//*jsl:declare close*//*jsl:declare closed*//*jsl:declare confirm*//*jsl:declare console*//*jsl:declare Debug*//*jsl:declare defaultStatus*//*jsl:declare document*//*jsl:declare event*//*jsl:declare focus*//*jsl:declare frames*//*jsl:declare getComputedStyle*//*jsl:declare history*//*jsl:declare Image*//*jsl:declare length*//*jsl:declare location*//*jsl:declare moveBy*//*jsl:declare moveTo*//*jsl:declare navigator*//*jsl:declare open*//*jsl:declare opener*//*jsl:declare opera*//*jsl:declare Option*//*jsl:declare parent*//*jsl:declare Number*//*jsl:declare parseInt*//*jsl:declare print*//*jsl:declare prompt*//*jsl:declare resizeBy*//*jsl:declare resizeTo*//*jsl:declare screen*//*jsl:declare scroll*//*jsl:declare scrollBy*//*jsl:declare scrollTo*//*jsl:declare setInterval*//*jsl:declare setTimeout*//*jsl:declare status*//*jsl:declare top*//*jsl:declare window*//*jsl:declare XMLHttpRequest*/
// Constants (Constants are variables that never change throughout the running of your program. They are almost always declared globally.)
var gc_fSandwichPrice = 5.99; // Price for each sandwich (Version 1 and 2 only)
var gc_fExtrasPrice = 1.50; // Price for each extra item
// GLOBAL VARS
// Global object vars
var g_divErrors;
var g_radSandwich;
var g_radSize;
var g_chkExtras;
// Other global vars
var g_fTotal;
var g_sSandwich;
var g_sSize;
var g_sExtras;
// DO IT: Hook up an event handler for window.onload to the Init function.
window.onload = Init;
function Init() {
// DO IT: Change the version number in the line below, if necessary, so it accurately reflects this particular version of Dirty Deli.
document.getElementById("h1Title").innerHTML = "Dirty Deli 1.0";
// DO IT: grab and assign any html objects you need to work with
g_divErrors = document.getElementById("divErrors");
g_radSandwich = document.getElementsByName("radSandwich");
g_radSize = document.getElementsByName("radSize");
g_chkExtras = document.getElementsByName("chkExtras");
// DO IT: Set the innerHTML of spanExtrasPrice to gc_fExtrasPrice. Tip: Use the .toFixed() method to display it with 2 decimal places
document.getElementById("spanExtrasPrice").innerHTML = gc_fExtrasPrice.toFixed(2);
// DO IT: Hook up any event handlers you need
document.getElementById("btnCalculateTotal").onclick = CalculateTotal;
document.getElementById("btnProcessOrder").onclick = ProcessOrder;
// Version 2
// DO IT: You need to hook up an event handler that runs whenever the user selects a different Payment option.
//This is the "onchange" event. I suggest you use an anonymous function, and make use of the *selectedIndex* property to see if they chose the credit card.
//This function will check to see if the user selected the Credit card option. If they did, set the CSS visibility property to "visible", otherwise set it to "hidden".
document.getElementById("selPayment").onchange =
function() {
var divCreditCardInfo = document.getElementById ("divCreditCardInfo");
if (document.getElementById("selPayment").selectedIndex === 2) {
divCreditCardInfo.style.visibility = "visible";
}
else {
divCreditCardInfo.style.visibility = "hidden";
}
};
} // function Init()
// function Init
function CalculateTotal() {
// this function should be called when the user clicks the Calculate Total button. Its purpose is mainly to, well, calculate the total. Remember to hook up an appropriate event handler so this function will be called when they click.
// DO IT: clear out divErrors (set the innerHTML to an empty string)
g_divErrors.innerHTML = "";
// DO IT: Tip: you're going to be adding to g_fTotal. Remember: adding anything to garbage will always give you garbage. So how do you prevent this error?
// Same deal for g_sExtras.
g_fTotal = 0;
g_sExtras = " ";
/* DO IT:
Sandwich code - Version 1
Using an IF statement, see which radio button they checked, and assign the value of the selected sandwich to a global var name g_sSandwich.
If nothing is selected, set divErrors to "Select a sandwich", and exit the function.
Sandwich code - Version 2
Within each IF statement remove the line of code you wrote for Version 1.
Replace it with a call to a function (that you will write) named GetSandwichName().
When you call this function, pass it one parameter - the index of the radSandwich radio button that the user checked.
More info on the function itself is given below.
*/
/* if (g_radSandwich[0].checked === true) {
GetSandwichName(0);
}
else if (g_radSandwich[1].checked === true) {
GetSandwichName(1);
}
else if (g_radSandwich[2].checked === true) {
GetSandwichName(2);
}
else if (g_radSandwich[3].checked === true) {
GetSandwichName(3);
}
else {
g_divErrors.innerHTML = "Select a sandwich";
return;
}
*/
// Version 3
/* CONVERT: Sandwich code
Using a FOR loop and a single IF statement within the loop, see which radio button they checked.
When you find it, set g_sSandwich to the sandwich name
and break out of the loop using the break command.
If nothing is selected, set divErrors to "Select a sandwich", and exit the function.
But how do you know if nothing was selected? Use a boolean variable in the If statement,
then check its value after you get out of the loop.
Remember: Your code should be flexible enough so that if the number
of sandwiches change, your code can still work.
Afterall, that's one of the reasons we're using a loop.
Do NOT call the GetSandwichName() function. Incorporate its code here, and remove it.
*/
var iChecked = false;
var i;
for (i = 0; i < g_radSandwich.length; i++) {
if (g_radSandwich[i].checked) {
iChecked = true;
g_sSandwich = g_radSandwich[i].value;
break;
}
}
if (iChecked === false) {
g_divErrors.innerHTML = "Select a sandwich";
return;
}
// Version 1
/* DO IT:
This is the Size code.
Make sure they selected a size.
Update the total by adding the price of a sandwich (which is already declared as a constant) to the total
If nothing is selected, set divErrors to "Please choose a size", and exit the function.
Tip: An If Statement is the key here.
*/
// Version 2
/*
In this version, the sandwiches are not all the same price.
The price of each sandwich is contained within the title attribute of the radSandwich radio button for that sandwich
(take a look at the html to verify this).
So, modify the IF statement from Version 1. You need to call a function (that you will write) named GetSizeUpdateTotal(). More on that below.
*/
/*
if (g_radSize[0].checked === true) {
GetSizeUpdateTotal(0);
}
else if (g_radSize[1].checked === true) {
GetSizeUpdateTotal(1);
}
else if (g_radSize[2].checked === true) {
GetSizeUpdateTotal(2);
}
else {
g_divErrors.innerHTML = "Please choose a size";
return;
}
*/
// Version 3
/* CONVERT: Size code
Once again, using a FOR loop and a single IF statement within the loop,
see which radio button they checked, get the price and update the total just like you did previously.
Then break out of the loop using the break command.
If nothing is selected, set divErrors to "Please choose a size", and exit the function.
Do NOT call the GetSizeUpdateTotal() function. Incorporate its code here, and remove it.
*/
iChecked = false;
var price;
for (i = 0; i < g_radSize.length; i++) {
if (g_radSize[i].checked) {
iChecked = true;
price = g_radSize[i].title;
price = price.substr(1);
price += Number(price);
g_sSize = g_radSize[i].value;
g_fTotal += price;
break;
}
}
if (iChecked === false) {
g_divErrors.innerHTML = "Please choose a size";
return;
}
/* DO IT:
"Extras" code - Version 1
Using an IF statement, see which extra(s) they checked. For each extra selected, do the following:
Concatenate the value of the selected extra to a global var name g_sExtras.
Update the Total with the price of the Extra.
"Extras" code - Version 2
Remove each IF statement you wrote for Version 1. Replace it with a call to a function (that you will write) named GetExtraUpdateTotal().
When you call this function, pass it one parameter - the index of the chkExtras checkbox that the user checked.
More info on the function itself is given below.
*/
GetExtraUpdateTotal(0);
GetExtraUpdateTotal(1);
GetExtraUpdateTotal(2)
// Version 3
/* CONVERT: "Extras" code
Again, using a FOR loop and a single IF statement within the loop, do what needs to be done. Remember NOT to break out of the loop when you find a checked checkbox (there may be more).
Do NOT call the GetExtraUpdateTotal() function. Incorporate its code here, and remove it.
*/
/* ****** That's it -- you're done with the loops. ******* */
// END Version 3
/* DO IT:
Optional fun: Remove the trailing comma on the last extra.
HINT: use the length property and the substr() method.
*/
// Version 1
// DO IT: Assign the total to the txtTotal textbox. Include a dollar sign and use .toFixed() to display 2 decimal places
document.getElementById("txtTotal").value = "$" + g_fTotal.toFixed(2);
} // function CalculateTotal
// Version 2
/* DO IT:
Declare function GetSandwichName().
This function takes one parameter, named p_iSandwichIndex,
which is a radSandwich radio button index, i.e. the index of the Sandwich they selected.
It assigns the value of the selected sandwich to a global var name g_sSandwich.
*/
// END Version 2
// Version 2
/* DO IT:
Declare function GetSizeUpdateTotal().
This function takes one parameter, named p_iSizeIndex, which is a radSize radio button index,
i.e. the index of the radSize radio button that they selected.
The function should assign the *value* of the selected size to a global var name g_sSize.
Also, it must update the Total with the price for the size they selected.
The price is located in the title attribute of the radio button (take a look).
Remember that (using dot notation) you can access any object attribute you want, once you grab the object.
But the price in the title attribute contains a dollar sign,
and you want everything AFTER the dollar sign.
Use the substr() method to get the entire string, starting with the SECOND character in the string.
Look back on our class notes to see how we did this.
Use an alert to see that you got what you intended.
Then, convert that string to a number and add it to the Total.
TIP: Declare local vars as necessary.
*/
// Version 2
/* DO IT:
Declare function GetExtraUpdateTotal().
This function takes one parameter, named p_iExtraIndex, which is a chkExtras checkbox index, i.e. the index of an extra they selected.
Use an if statement to see if this particular checkbox is checked. If it is, then do the following:
Concatenate the value of the selected extra to a global var name g_sExtras.
Update the Total with the price of the Extra.
*/
function GetExtraUpdateTotal(p_iExtraIndex) {
if (g_chkExtras[p_iExtraIndex].checked === true) {
g_sExtras += g_chkExtras[p_iExtraIndex].value + ", ";
g_fTotal += gc_fExtrasPrice;
}
}
function ProcessOrder() {
// This function should run when the ProcessOrder button is clicked.
// Version 2
// DO IT: declare any local vars you may need
var txtName = document.getElementById("txtName");
var txtMonth = document.getElementById("txtMonth");
var selPayment = document.getElementById("selPayment");
var selYear = document.getElementById("selYear");
var txtCreditCardNbr = document.getElementById("txtCreditCardNbr");
var month;
// Version 2
// DO IT: Before you do your error checking, does anything need to be initialized to an empty string? Now's the time to do it.
document.getElementById("divOrder").innerHTML = "";
g_divErrors.innerHTML = "";
// Version 2
// DO IT: If the name field is blank, display "Enter customer's name", set the focus and get out.
if (txtName.value === "") {
g_divErrors.innerHTML = "Enter customer's name";
txtName.focus();
return;
}
// Version 2
/* DO IT: Credit Card Code
Use an IF statement to determine if the user selected the credit card option in the selPayment dropdown
If they did, you need to do the following:
if the credit card number field was left blank or the contents of the field is not a number, display (in divErrors) the message shown in the working version, put focus on the card number field and get out.
if the month field was left blank or the contents of the field is not a number, display the message shown in the working version, put focus on the month field and get out.
if the month they entered is less than 1 or > 12, display the message shown in the working version, put focus on the month field and get out.
TIP: Remember to convert the txtMonth value to a number before you do your comparison.
if they neglected to select a year, display the message shown in the working version, put focus on the year field and get out.
*/
// END Version 2
// The following section I got assistance from another classmate.
if (selPayment.selectedIndex === 2) {
if ((txtCreditCardNbr.value === "") || (isDigits(txtCreditCardNbr.value) === false)) {
g_divErrors.innerHTML = "Enter your card number using only digits";
txtCreditCardNbr.focus();
return;
} else if ((txtMonth.value === "") || (isDigits(txtMonth.value) === false)) {
g_divErrors.innerHTML = "Enter month using only digits";
txtMonth.focus();
return;
} else {
month = Number(txtMonth.value);
if ((month < 1) || (month > 12)) {
g_divErrors.innerHTML = "Enter month between 1 and 12";
txtMonth.focus();
return;
}
}
if (selYear.selectedIndex === 0) {
g_divErrors.innerHTML = "Please select a year";
selYear.focus();
return;
}
}
// DO IT: Concatenate the appropriate msg into divOrder. The Welcome msg is within an h3 tag. Every other line is within a p tag. The last line is in bold.
/* Version 1:
Do not include the user's name in the welcome message.
Do not include the "Paid by" statement.
*/
/* Version 2:
Include the user's name in the welcome message.
Include the "Paid by" statement.
*/
document.getElementById("divOrder").innerHTML =
"<h3>Welcome to Dirty Deli!</h3>" + txtName.value + "<br>" +
"You have ordered a " + g_sSize + " " + g_sSandwich + " with " + g_sExtras + "<br>" +
"Your total is " + document.getElementById("txtTotal").value + "<br>" +
"Paid with " + selPayment.value + "<br>" + "<br>" +
"<strong>Have a nice day!</strong>";
} // function ProcessOrder
I'm struggling with a ExtJS 4.1.1 grid that has editable cells (CellEditing plugin).
A person should be able to type a mathematic formula into the cell and it should generate the result into the field's value. For example: If a user types (320*10)/4 the return should be 800. Or similar if the user types (320m*10cm)/4 the function should strip the non-mathematical characters from the formula and then calculate it.
I was looking to replace (or match) with a RegExp, but I cannot seem to get it to work. It keeps returning NaN and when I do console.log(e.value); it returns only the originalValue and not the value that I need.
I don't have much code to attach:
onGridValidateEdit : function(editor,e,opts) {
var str = e.value.toString();
console.log(str);
var strCalc = str.match(/0-9+-*\/()/g);
console.log(strCalc);
var numCalc = Number(eval(strCalc));
console.log(numCalc);
return numCalc;
},
Which returns: str=321 strCalc=null numCalc=0 when I type 321*2.
Any help appreciated,
GR.
Update:
Based on input by Paul Schroeder, I created this:
onGridValidateEdit : function(editor,e,opts) {
var str = e.record.get(e.field).toString();
var strCalc = str.replace(/[^0-9+*-/()]/g, "");
var numCalc = Number(eval(strCalc));
console.log(typeof numCalc);
console.log(numCalc);
return numCalc;
},
Which calculates the number, but I am unable to print it back to the grid itself. It shows up as "NaN" even though in console it shows typeof=number and value=800.
Final code:
Here's the final code that worked:
onGridValidateEdit : function(editor,e,opts) {
var fldName = e.field;
var str = e.record.get(fldName).toString();
var strCalc = str.replace(/[^0-9+*-/()]/g, "");
var numCalc = Number(eval(strCalc));
e.record.set(fldName,numCalc);
},
Lets break this code down.
onGridValidateEdit : function(editor,e,opts) {
var str = e.value.toString();
What listener is this code being used in? This is very important for us to know, here's how I set up my listeners in the plugin:
listeners: {
edit: function(editor, e){
var record = e.record;
var str = record.get("your data_index of the value");
}
}
Setting it up this way works for me, So lets move on to:
var strCalc = str.match(/0-9+-*\/()/g);
console.log(strCalc);
at which point strCalc=null, this is also correct. str.match returns null because your regex does not match anything in the string. What I think you want to do instead is this:
var strCalc = str.replace(/[^0-9+*-]/g, "");
console.log(strCalc);
This changes it to replace all characters in the string that aren't your equation operators and numbers. After that I think it should work for whole numbers. I think that you may actually want decimal numbers too, but I can't think of the regex for that off the top of my head (the . needs to be escaped somehow), but it should be simple enough to find in a google search.
I want to take strings like:
Submit Changes
Create New
Update Record
Save Item
and convert them to:
Submitting Changes
Creating New
Updating Record
Saving Item
with a function like:
var ConvertToProgressivePresent = (function(){
// cache this regex
var rProgressivePresent = /\b(?:(Submi(t))|(Creat|Sav|Updat)e)\b/i;
return function(phrase){
return phrase.replace(rProgressivePresent, "$1$2$3ing");
};
}());
This above regex works but doesn't seem like the best way to do it. I don't like the grouping here where 1-2 groups are always empty when there is a match.
Got any suggestions or improvements?
If you have specific words to replace with then you could make a word bank. Have the words and their replacement stored in an object and then loop through it.
var ConvertToProgressivePresent = (function() {
var replaceValues = {
"Submit": "Submitting",
"Create": "Creating",
"Update": "Updating",
"Save": "Saving"
}
return function(phrase) {
for (var item in replaceValues) {
phrase = phrase.replace(item, replaceValues[item]);
}
return phrase;
};
}());
Here is a JSFiddle Example
I think you should probablly use CASE statments instead. Regex isn't the most efficient way of doing things...and that is probably best that it doesn't cuz you know the old saying.
Wow, I have this problem...I know, I'll use regex...ok, now you have two problems 90)
First off, it doesn't appear to me that your regex does quite what you want anyway in that I don't see a second "t" added when changing submit to submitting.
However, I don't think I would use regex for this task at all anyway. If you are just trying to replace one word with another, and the word always comes at the beginning of the string, I might do something like:
function ReplaceIfBeginsWith(wholeString, checkFor, replaceWith)
{
if (wholeString.indexOf(checkFor + ' ') == 0)
{
return replaceWith + ' ' + wholeString.substr(checkFor.length + 1);
}
if (wholeString == checkFor)
{
return replaceWith;
}
return wholeString;
}
Then, you can call the function with each of the words you would want to replace. If you want case-insensitivity, just check against lowercase versions of all the strings.