How to replace new line character with comma in angular - javascript

I have one textarea field in which the user can enter input in a new line as well as comma-separated values. so when I m sending values in API /n is appended in case of the new line and same /n is visible on detail page which I don't want. below is the example of user input.
Ex-1
ABC
red
test,blue
Ex-2
abc,blue,
green,red
test
I want each time to check for new line break and comma, my mean is to say
if user enter values in new line then replace newline character with a comma and if a comma is already appended
then keep it as it is.
Expected output
Ex-1
ABC,red,test,blue
Ex-2
abc,blue,green,red,test
Below is my code
createData(data) {
const Obj = {};
if (data.enum && data.value_type === 'Enum') {
Obj['values'] = data.enum.split(',');
}
console.log(Obj,"constraint");
return Obj;
}

You need first split the string with a newline character, Remove any empty string from the array once it's done joined it with ,. Also, we need to take care of some double comma as string contain a comma.
var str = `ABC
red
test,blue`;
var str2 = `abc,blue,
green,red
test`;
formateString(str);
formateString(str2);
function formateString(str) {
var strArray = str.split("\n");
strArray = strArray.filter((item) => {
return item !== '';
});
console.log(strArray.join(",").split(",,").join(","));
}

Using regex split()
Regex Demo
const str1 = `ABC
red
test,blue`;
const str2 = `abc,blue,
green,red
test`;
console.log(str1.split(/[,\n]+\s+/g).join(','))
console.log(str2.split(/[,\n]+\s+/g).join(','))

Another approach is to intercept input every time user enters character. With this method you avoid parsing whole text over and over again with every keystroke (including redundant ones).
Following is a simple piece of code that substitutes newlines and spaces with commas on the fly. Assuming you have a textarea with id textArea somewhere in your HTML.
const textArea = document.getElementById('textArea');
const parseText = function parseText(e) {
if (e.keyCode === 13 || e.keyCode === 32) {
e && e.preventDefault();
let text = textArea.value;
let curStart = textArea.selectionStart;
let curEnd = textArea.selectionEnd;
if (curStart == text.length && curEnd == text.length && !text.endsWith(',')) {
text += ',';
textArea.value = text;
}
}
}
textArea.addEventListener('keydown', parseText);
Regards

Related

Split and replace text by two rules (regex)

I trying to split text by two rules:
Split by whitespace
Split words greater than 5 symbols into two separate words like (aaaaawww into aaaaa- and www)
I create regex that can detect this rules (https://regex101.com/r/fyskB3/2) but can't understand how to make both rules work in (text.split(/REGEX/)
Currently regex - (([\s]+)|(\w{5})(?=\w))
For example initial text is hello i am markopollo and result should look like ['hello', 'i', 'am', 'marko-', 'pollo']
It would probably be easier to use .match: match up to 5 characters that aren't whitespace:
const str = 'wqerweirj ioqwejr qiwejrio jqoiwejr qwer qwer';
console.log(
str.match(/[^ ]{1,5}/g)
)
My approach would be to process the string before splitting (I'm a big fan of RegEx):
1- Search and replace all the 5 consecutive non-last characters with \1-.
The pattern (\w{5}\B) will do the trick, \w{5} will match 5 exact characters and \B will match only if the last character is not the ending character of the word.
2- Split the string by spaces.
var text = "hello123467891234 i am markopollo";
var regex = /(\w{5}\B)/g;
var processedText = text.replace(regex, "$1- ");
var result = processedText.split(" ");
console.log(result)
Hope it helps!
Something like this should work:
const str = "hello i am markopollo";
const words = str.split(/\s+/);
const CHUNK_SIZE=5;
const out = [];
for(const word of words) {
if(word.length > CHUNK_SIZE) {
let chunks = chunkSubstr(word,CHUNK_SIZE);
let last = chunks.pop();
out.push(...chunks.map(c => c + '-'),last);
} else {
out.push(word);
}
}
console.log(out);
// credit: https://stackoverflow.com/a/29202760/65387
function chunkSubstr(str, size) {
const numChunks = Math.ceil(str.length / size)
const chunks = new Array(numChunks)
for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
chunks[i] = str.substr(o, size)
}
return chunks
}
i.e., first split the string into words on spaces, and then find words longer than 5 chars and 'chunk' them. I popped off the last chunk to avoid adding a - to it, but there might be a more efficient way if you patch chunkSubstr instead.
regex.split doesn't work so well because it will basically remove those items from the output. In your case, it appears you want to strip the whitespace but keep the words, so splitting on both won't work.
Uses the regex expression of #CertainPerformance = [^\s]{1,5}, then apply regex.exec, finally loop all matches to reach the goal.
Like below demo:
const str = 'wqerweirj ioqwejr qiwejrio jqoiwejr qwer qwer'
let regex1 = RegExp('[^ ]{1,5}', 'g')
function customSplit(targetString, regexExpress) {
let result = []
let matchItem = null
while ((matchItem = regexExpress.exec(targetString)) !== null) {
result.push(
matchItem[0] + (
matchItem[0].length === 5 && targetString[regexExpress.lastIndex] && targetString[regexExpress.lastIndex] !== ' '
? '-' : '')
)
}
return result
}
console.log(customSplit(str, regex1))
console.log(customSplit('hello i am markopollo', regex1))

Converting user input strings with Special characters to regular expression

Note: there was a similar question but since it didn't have 'Special characters' and the problem here is only with 'Special characters', I posted a new question.
I have a list (from user input textarea) of Regular Expression representations:
Example: (simplified)
// starting point is a string like this one
let str = `/ab+c/
/Chapter (\d+)\.\d*/
/\d+/
/d(b+)d/`;
I need to convert them into an array to check (for validity) and prepare each line e.g. (simplified)
let arr = str.split(/[\r\n]+/);
for (let i = 0, len = arr.length; i < len; i++) {
arr[i] = arr[i].slice(1, -1); // removing the start/end slashes
// problem with double slashing the Special characters
// it doesn't give the required result
arr[i] = arr[i].replace(/\\/g, '\\$&');
// same result with replace(/\\/g, '\\\\')
}
Finally, convert them into one RegEx object
let regex = new RegExp(arr.join('|'), 'i');
console.log(regex.test('dbbbd')); // true
console.log(regex.test('256')); // false
I must be missing something here.
Update
I missed the point that the data that comes from a textarea (or similar) doesn't need to be escaped at all. When I was testing the code, I was testing it like above which didn't work.
Lets use the "change" event on <textarea> so that once the user changes the content and clicks outside, we just access the value property of it we can then construct the composite RegExp object. I haven't had the need to escape the \ characters at all.
Just copy paste the following to the text area and click outside.
/ab+c/
/Chapter (\d+)\./
/\d+/
/d(b+)d/
var myTextarea = document.getElementById("ta");
myTextarea.addEventListener("change", function(e) {
var str = e.currentTarget.value.split(/[\r\n]+/)
.map(s => s.slice(1, -1))
.join("|");
rgx = new RegExp(str, "i")
console.log(`Derived RegExp object: ${rgx}`);
console.log(`Testing for 'dbbbd': ${rgx.test('dbbbd')}`); // true
console.log(`Testing for '256': ${rgx.test('256')}`); // true
});
#ta {
width: 33vw;
height: 50vh;
margin-left: 33vw;
}
<textarea id="ta"></textarea>

Replace content present in the nested brackets

Input = ABCDEF ((3) abcdef),GHIJKLMN ((4)(5) Value),OPQRSTUVW((4(5)) Value (3))
Expected Output = ABCDEF,GHIJKLMN,OPQRSTUVW
Tried so far
Output = Input.replace(/ *\([^)]*\)*/g, "");
Using a regex here probably won't work, or scale, because you expect nested parentheses in your input string. Regex works well when there is a known and fixed structure to the input. Instead, I would recommend that you approach this using a parser. In the code below, I iterate over the input string, one character at at time, and I use a counter to keep track of how many open parentheses there are. If we are inside a parenthesis term, then we don't record those characters. I also have one simple replacement at the end to remove whitespace, which is an additional step which your output implies, but you never explicitly mentioned.
var pCount = 0;
var Input = "ABCDEF ((3) abcdef),GHIJKLMN ((4)(5) Value),OPQRSTUVW((4(5)) Value (3))";
var Output = "";
for (var i=0; i < Input.length; i++) {
if (Input[i] === '(') {
pCount++;
}
else if (Input[i] === ')') {
pCount--;
}
else if (pCount == 0) {
Output += Input[i];
}
}
Output = Output.replace(/ /g,'');
console.log(Output);
If you need to remove nested parentheses, you may use a trick from Remove Nested Patterns with One Line of JavaScript.
var Input = "ABCDEF ((3) abcdef),GHIJKLMN ((4)(5) Value),OPQRSTUVW((4(5)) Value (3))";
var Output = Input;
while (Output != (Output = Output.replace(/\s*\([^()]*\)/g, "")));
console.log(Output);
Or, you could use a recursive function:
function remove_nested_parens(s) {
let new_s = s.replace(/\s*\([^()]*\)/g, "");
return new_s == s ? s : remove_nested_parens(new_s);
}
console.log(remove_nested_parens("ABCDEF ((3) abcdef),GHIJKLMN ((4)(5) Value),OPQRSTUVW((4(5)) Value (3))"));
Here, \s*\([^()]*\) matches 0+ whitespaces, (, 0+ chars other than ( and ) and then a ), and the replace operation is repeated until the string does not change.

Block user from input with regex

I have a function which checks an input box with an regex string for max. 3 words and two spaces.
$('input.words_input__input_field').on("keyup", function(e) {
if (e.keyCode == 13) {
send_message();
}
var re = /^((([\'\-\+\s]\s*[a-zA-Z])?[a-zA-Z]*)){3}$/g;
var str = $('input.words_input__input_field').val();
var m;
while ((m = re.exec(str)) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
send_text = str;
// View your result using the m-variable.
// eg m[0] etc.
}
console.log(m);
});
When the Regex applies on the input value the send_text will not be edited anymore. But I want to prevent the user from typing anymore into the input box.
Is there any way to create a block for the input so that the user cannot type in more than as "allowed" by the regex?
EDIT: I have some problems with this regex, so it works too perfect it should only prevent the user from typing in after three words and two spaces are in the input field. I have a code like this:
var test = /^((([\'\-\+\s]\s*[a-zA-Z])?[a-zA-Z]*)){3}$/g;
if (test.test($(this).val())) {
$(".input").val($(".input").val().replace(/\s/g, ""));
}
But it "kills" all whitespaces. And I only want to delete the whitespaces at the end. Any ideas?
Set the input to disabled with
$('input.words_input__input_field').prop('disabled', true);
Or store the .val() in a variable or a data object as long as it's valid and regenerate it from there if the regex is not met anymore.
EDIT:
The code below will let the user type 3 words, separated by commas. If anything is added that violates the regex, the input will be reset to the last value.
var p;
var f;
$(".inp").on('keyup',function(e){
var k = e.which;
var i = $(".inp").val();
if(k != 8 && k != 46){ // allow backspace and delete
if(i.search(/^[A-Za-z]+ [A-Za-z]+ [A-Za-z]+$/) >= 0){
f = true;
p = i;
}
else{
if(f){
$(".inp").val(p);
}
}
}
});
<input type="text" class="inp">
Fiddle

Display only whole word using javascript

I have a text say "A sample text for testing". I need to display only ten characters in a div.
so i do substring on the text
txt.substring(0,10)
This gives me "A sample t". Since its ugly to display a unterminated word, i need only to display "A Sample" to be displayed. How do i do this?
You could do what you do, substringing the text to 10 chars.
Then you use txt.lastIndexOf(' ') to find the last space in the text.
Then you use that to substring the text again.
Example:
var txt = "A Sample Text";
txt = txt.subString(0,10); // "A Sample T"
txt = txt.subString(0, txt.lastIndexOf(' ')); // "A Sample"
Let me know if it helps!
Assuming that you'd rather have a cut off string than an empty string, if the word is longer than ten characters:
function shorten(txt)
{
// if it's short or a space appears after the first 10 characters, keep the substring (simple case)
if (txt.length <= 10 || txt[10] === ' ') return txt;
// get the index of the last space
var i = txt.substring(0, 11).lastIndexOf(' ');
// if a space is found, return the whole words at the start of the string;
// otherwise return just the first 10 characters
return txt.substring(0, i === -1 ? 11 : i);
}
use substring method to do this
i think you should add a filter to check whether the 11th character is space or not with the substring method. otherwise the last valid word too might removed. get "New sample text for testing" for example.
this is the code.
str = "A sample text for testing"
ch11_space = (str[10] == ' ') ? 0 : 1;
str = str.substring(0,10);
if (ch11_space) {
str = str.substring(0,str.lastIndexOf(' '));
}
function getShortenedString(str)
{
var maxLength = 10; // whatever the max string can be
var strLength = str.length;
var shortenedStr = str.substr(0, maxLength);
var shortenedStrLength = shortenedStr.length;
var lastSpace = str.lastIndexOf(" ");
if(shortenedStrLength != strLength)
{
// only need to do manipulation if we have a shortened name
var strDiff = strLength - shortenedStrLength;
var lastSpaceDiff = shortenedStrLength - lastSpace;
if(strDiff > lastSpaceDiff) // non-whole word after space
{
shortenedStr = str.substr(0, lastSpace);
}
}
return shortenedStr;
}

Categories

Resources