Javascript RegEx Help - javascript

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.

Related

Dynamic from fields using reactive forms in Angular?

I have a scenario like Need to edit the single quotes values (only single quotes values),
So I extracted the single quotes values using regex and prepare the reactive dynamic form.
onclick of performing edit button will show old step name above, new step name below, submit step will replace the step name in the original array.
WOrking fine as expected in few scenarios according to my approach, but in scenarios, I realized whatever algorithm I am following does not fulfill my requirement.
Below are the test cases
Test case 1:
Step Name: "Then I should hire an employee using profile '1' for 'USA'",
// Here --> '1', 'USA' values are editable
Test case 2: "And Employee should be hired on '01' day of pay period '01' of 'Current' Fiscal"
// '01', '01', 'Current'
Issues: in test case 2 if I tried to edit second 01 it is editing the first 01
I try to solve the perform edit function with help of indexof, substring functions
this.replaceString = this.selectedStep.name;
this.metaArray.forEach((element: any) => {
var metaIndex = this.replaceString.indexOf(element.paramValue);
if (metaIndex !== -1) {
const replaceValue = this.stepEditForm.controls[element['paramIndex']].value;
this.replaceString = this.replaceString.substring(0, metaIndex) + replaceValue + this.replaceString.substring(metaIndex + (element.paramValue.length));
}
});
but in indexof always find the first occurrence of a value in a string. So I realized my approach is wrong on performed it function
please find the attachment for the code
https://stackblitz.com/edit/angular-reactive-forms-cqb9hy?file=app%2Fapp.component.ts
So Can anyone please suggest to me how to solve this issue,
Thanks in advance
I added a function called matchStartingPositions that returns the starting position indexes of each match. Using this method you can then perform your edit by replacing the string just as you do, but we'll find the proper match to be replaced at the given position.
So in your line
var metaIndex = this.replaceString.indexOf(element.paramValue);
we can then add a second parameter to indexOf, that is the starting point:
var metaIndex = this.replaceString.indexOf(element.paramValue, startingPositions[element.paramIndex]);
The function for getting the index positions just looks for those single quotes in a given string:
matchStartingPositions(str) {
let count = 0;
let indices = [];
[...str].forEach((val, i) => {
if (val === "'") {
if (count % 2 == 0) {
indices.push(i);
}
count++;
}
});
return indices;
}
Here it is in action:
https://angular-reactive-forms-xhkhmx.stackblitz.io
https://stackblitz.com/edit/angular-reactive-forms-xhkhmx?file=app/app.component.ts

why does this javascript take the "h" out of "he"?

I have this javascript code and it's supposed to display 4.0026 in the alert box after the user inputs "1 he" into the prompt, but for some reason it instead decides to take only the "h" out of "he" and use that while thinking you inputted "h" only.
var first=prompt("Enter first term");
if(first==""){
periodictable();
}else{
var split=first.split(" ");
var firsttrans=split[1].replace("h", 1.008).replace("he", 4.0026);
alert(firsttrans);
}
btw ignore the function invocation periodictable() because it's not related to this problem.
After replacing h you have no more h inside. You could change the replacement and look first for he, then for h.
var firsttrans = split[1].replace("he", 4.0026).replace("h", 1.008);
You have to change your replace logic. First you have check for he and if not not found then h. With your current logic, since you are replacing h first there will be no more "he" found.
split[1].replace("he", 4.0026).replace("h", 1.008)
Here is another clean solution. This way you can add as many pairs as you want without touching your replace code. All you need to do is just updat the changes and done.
var str = "Mr.h, here is he ";
var reps = {
"h" : 1.008,
"he" : 4.0026
};
str = str.replace(/he|h/gi, function(found){
return reps[found];
});
console.log(str)
As Nina Scholz said, the replacements happen sequentially.
In case you add more elements later on, you might want to extract your data to a separate place, like so:
var replacements = {
"h": 1.008,
"he": 4.0026
};
var first=prompt("Enter first term");
if(first==""){
periodictable();
}else{
var split=first.split(" ");
var firsttrans=replacements[split[1]];
alert(firsttrans);
}

Unable to Get Output From While Loop in Javascript

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.)

javascript custom humanize filter

I am stuck with creating custom humanize function for my project.
My API is returing labels that I want to turn into more readable such as:
probabilityOfDefault
and I want to change it into
Probability Of Default
or
historicalDate
and change it into
Historical Date
So far I have written a function but it only changes the letters to upper case, it doesnt add space before every each. Here it is:
var humanize = function(property) {
return property.replace(/_/g, ' ')
.replace(/(\w+)/g, function(match) {
return match.charAt(0).toUpperCase() + match.slice(1);
});
};
I am not an expert in regular expersions, also I am not unaware of any libaries that could do this for me. Any help ?
You can use:
s = 'probabilityOfDefault';
r = s[0].toUpperCase() + s.substring(1).replace(/([a-z])(?=[A-Z])/g, "$1 ");
//=> Probability Of Default

Node.innerHTML giving tag names in lower case

I am iterating NodeList to get Node data, but while using Node.innerHTML i am getting the tag names in lowercase.
Actual Tags
<Panel><Label>test</Label></Panel>
giving as
<panel><label>test</label></panel>
I need these tags as it is. Is it possible to get it with regular expression? I am using it with dojo (is there any way in dojo?).
var xhrArgs = {
url: "./user/"+Runtime.userName+"/ws/workspace/"+Workbench.getProject()+"/lib/custom/"+(first.type).replace(".","/")+".html",
content: {},
sync:true,
load: function(data){
var test = domConstruct.toDom(data);
dojo.forEach(dojo.query("[id]",test),function(node){
domAttr.remove(node,"id");
});
var childEle = "";
dojo.forEach(test.childNodes,function(node){
if(node.innerHTML){
childEle+=node.innerHTML;
}
});
command.add(new ModifyCommand(newWidget,{},childEle,context));
}
};
You cannot count on .innerHTML preserving the exact nature of your original HTML. In fact, in some browsers, it's significantly different (though generates the same results) with different quotation, case, order of attributes, etc...
It is much better to not rely on the preservation of case and adjust your javascript to deal with uncertain case.
It is certainly possible to use a regular expression to do a case insensitive search (the "i" flag designates its searches as case insensitive), though it is generally much, much better to use direct DOM access/searching rather than innerHTML searching. You'd have to tell us more about what exactly you're trying to do before we could offer some code.
It would take me a bit to figure that out with a regex, but you can use this:
var str = '<panel><label>test</label></panel>';
chars = str.split("");
for (var i = 0; i < chars.length; i++) {
if (chars[i] === '<' || chars[i] === '/') {
chars[i + 1] = chars[i + 1].toUpperCase();
}
}
str = chars.join("");
jsFiddle
I hope it helps.
If you are trying to just capitalise the first character of the tag name, you can use:
var s = 'panel';
s.replace(/(^.)(.*)/,function(m, a, b){return a.toUpperCase() + b.toLowerCase()}); // Panel
Alternatively you can use string manipulation (probably more efficient than a regular expression):
s.charAt(0).toUpperCase() + s.substring(1).toLowerCase(); // Panel
The above will output any input string with the first character in upper case and everything else lower case.
this is not thoroughly tested , and is highly inefficcient, but it worked quite quickly in the console:
(also, it's jquery, but it can be converted to pure javascript/DOM easily)
in jsFiddle
function tagString (element) {
return $(element).
clone().
contents().
remove().
end()[0].
outerHTML.
replace(/(^<\s*\w)|(<\/\s*\w(?=\w*\s*>$))/g,
function (a) {
return a.
toUpperCase();
}).
split(/(?=<\/\s*\w*\s*>$)/);
}
function capContents (element) {
return $(element).
contents().
map(function () {
return this.nodeType === 3 ? $(this).text() : capitalizeHTML(this);
})
}
function capitalizeHTML (selector) {
var e = $(selector).first();
var wrap = tagString(e);
return wrap[0] + capContents(e).toArray().join("") + wrap[1];
}
capitalizeHTML('body');
also, besides being a nice exercise (in my opinion), do you really need to do this?

Categories