Get a single class name as a string from an element - javascript

This is probably simple but I am having some difficulty. I am trying to return a specific class name from an element as a string. There will be many interactive_items with different class name that follow the element__content__item pattern so I need the element__content__item class name.
Right now I am just trying the first element found.
I need to get the string slider__content__item
const elements = [...document.querySelectorAll('.interactive__item')]
const regex = new RegExp(/^.*(content__item).*$/g)
const result = elements[0].className.match(regex).toString()
This returns slider__content__item interactive__item entry which is correct but then how do I pull out the slider__content__item class as a string.
If there is a better way to do this I am all ears.
<aside class="slider__content__item interactive__item entry">
</aside>

/\w+__content__item/g
const elements = [...document.querySelectorAll('.interactive__item')]
const regex = new RegExp(/\w+__content__item/g)
const result = elements[0].className.match(regex).toString()
console.log(result)
<aside class="slider__content__item interactive__item entry">
</aside>

const elements = Array.from(document.querySelectorAll('.interactive__item'));
const regex = new RegExp(/^.*(content__item).*$/g)
const result = Array.from(elements[0].classList); // you have all item classes after that write your mathing statements

maybe try with document.getElementById(id of the element).className
or document.getElementByTagName(name of the tag).className ?

Related

Cypress get content of several DIVs, and compose one long string

I have some divs that render this way:
<div class="customer-data-column">
<h3>Title:</h3>
<div>Name Lastname</div>
<div>123 Address xxx yyy</div>
<div>Chicago XY 33056</div>
<div>Country name</div>
</div>
This content is generated by:
{customerData.replaceAll("/r", "").split("\n").map(item => <div key={item}>{item}</div>)}
This data is coming from redux.
In console log (from redux data) the address appears this way:
Name Lastname\n123 Address xxx yyy\nChicago XY 33056\nCountry name
I want to check in Cypress if this address is correct, the same that is in redux.
I need some way that merges the content of the divs into one string, and adds the \n between each div.
I thought I could start this way:
cy.get('.customer-data-column').should($title => {
const store = Cypress.store.getState();
const reduxPath = store.customerData;
expect("not sure what to put here... how to merge").to.equals(reduxPath)
Can anyone please help?
===
EDIT
I made it almost work this way:
I added a class to the inner divs, so they render this way:
<div class="customer-data-column">
<h3>Title:</h3>
<div class="address-row">Name Lastname</div>
<div class="address-row">123 Address xxx yyy</div>
<div class="address-row">Chicago XY 33056</div>
<div class="address-row">Country name</div>
</div>
And the test:
cy.get('.address-row').then($divList => {
const textArray = Cypress.$.makeArray($divList).map(el => el.innerText)
const actual = textArray.join(textArray, '\n') // use join to array of strings into single string
expect(actual).to.eql(billToAddress)
})
However it still fails with such message:
assert expected Name LastnameName Lastname,23 Address xxx yyy,Chicago
XY 33056,Country name23 Address xxx yyyName Lastname,23 Address xxx
yyy,Chicago XY 33056,Country name7th FloorName Lastname,23 Address xxx
yyy,Chicago XY 33056,Country nameBrooklyn NY 11210Name Lastname,23
Address xxx yyy,Chicago XY 33056,Country nameCountry name to deeply
equal Name Lastname\n23 Address xxx yyy\n7th Floor\nBrooklyn NY
11210\nCountry name
Edit 2:
The solution that I found and works is this one:
.then(users => {
const billToAddress = users.response.body.filter(el => el.orderNumber === '3-331877')[0]
.billTo
cy.get('.address-row').each((item, index) => {
cy.log(cy.wrap(item).should('contain.text', billToAddress.split('\n')[index]))
})
})
Of course if somebody has a better way for achieving this test, I am open to learn more and code better.
If you make an array of the store data, an .each() loop can compare them.
const store = Cypress.store.getState()
const reduxData = store.customerData // expect 'Name Lastname\n123 Address xxx yyy\nChicago XY 33056\nCountry name'
const reduxDataArray = reduxData.split('\n')
cy.contains('.customer-data-column', 'Title:')
.find('div') // only divs inside '.customer-data-column'
.each(($div, index) => {
expect($div.text()).to.eq(reduxDataArray[index])
})
From other comment, it looks like cy.get('.custom-data-column') isn't strong enough to isolate this HTML you need to work on.
Perhaps cy.contains('.customer-data-column', 'Title:') is better.
All text at once
In this particular case you can test all text at once by globally removing \n
const store = Cypress.store.getState()
const reduxData = store.customerData // expect 'Name Lastname\n123 Address xxx yyy\nChicago XY 33056\nCountry name'
const reduxAllTexts = reduxData.replace(/\n/g, '')
cy.contains('.customer-data-column', 'Title:')
.find('div')
.invoke('text')
.should('eq', reduxAllTexts)
If the Cypress function yields multiple elements, we can join the text of those elements to create your string.
cy.get('.custom-data-column').find('div').then(($divList) => {
const store = Cypress.store.getState();
const reduxPath = store.customerData;
const textArray = $divList.map((x) => x.text()); // get the text values as an array
const actual = textArray.join(textArray, '\n'); // use join to array of strings into single string
expect(actual).to.eql(reduxPath);
});

JS React: replacing regex with component in a string

Given a string with the format:
'This is a string with some ::FaIconUpload:: icons in it as ::FaIconDownload:: these two.'
I'd like to split it using a RegEx and replace the coincidences with some React components. The string would have the type of component (FaIcon) and a props in it such as the name of the icon (Upload).
The objective with this is to be able to use React components within translated strings, and the expected return value would be something like:
[
'This is a string with some ',
<FaIcon iconName="Upload" />,
' in it as ',
<FaIcon iconName="Download" />,
' these two.'
]
The method
Currently, I've got a method which returns either a string or an array. This is compatible with React render methods, since if we return an array it will be capable of rendering any components on that array.
As I'll use it to translate some strings, I've created this custom hook:
const useCustomTranslation = () => {
const { t } = useTranslation();
const tlt = (...args) => {
// const str = t(...args);
const testStr =
'This is a string with some ::FaIconUpload:: icons in it as ::FaIconDownload:: these two.';
const reg = /(?<=::FaIcon)(.*?)(?=::)/g;
const preStrAr = testStr.split(reg);
console.log(preStrAr);
};
return { tlt };
};
The problem
Currently, this method is logging this:
[
"This is a string with some ::FaIcon",
"Upload",
":: icons in it as ::FaIcon",
"Download",
":: these two."
]
As you can see, it's not including the ::FaIcon and the final ::, as I haven't been able to find the right Regex to do so. But even if I got to that point, I feel like then I should have to re-iterate through the array to replace the strings with the right component, again using Regex to see if the array item matches the right format.
I find this somehow overcomplicated, and I think there has to be a much cleaner and easy way to get it (correct me if maybe I'm wrong and this is the only way).
Is there any way where I can split a string using a Regex, using part of the matched group to replace the string by another content using that matched string?
Perhaps you meant to do this?
/::FaIcon(.*?)::/ without the look
const str = `This is a string with some ::FaIconUpload:: icons in it as ::FaIconDownload:: these two.`
const newText = str.replace(/::FaIcon(.*?)::/g,function(_,match) {
return `<FaIcon iconName="${match}" />`
})
console.log(newText)
To make an array you can do
const str = `This is a string with some ::FaIconUpload:: icons in it as ::FaIconDownload:: these two.`
const newText = str.replace(/\s?::FaIcon(.*?)::\s?/g,function(_,match) {
return `::<FaIcon iconName="${match}" />::`
}).split("::")
console.log(newText)
Finally, I've made it using (sadly) the re-iteration method, as it's the only way I can see it would work. Thanks to #mplungjan for his first answer, which gave me the hints to get it working:
export const replaceIconInStr = (str) => {
// Matches the whole icon component pattern
const regComponent = /(::FaIcon.*?::)/g;
// Matches just the component prop we need
const regIconName = /::FaIcon(.*?)::/g;
// Split the string by the component pattern
const splittedStr = str.split(regComponent);
// If there are any matches
if (splittedStr.length) {
// Match the elements in the array and get the prop to replace it by the real component
return splittedStr.map((el) => {
const matched = regIconName.exec(el)?.[1];
if (matched) {
return <FaIcon iconName={matched} />;
}
return el;
});
}
// If there is no pattern matching, return the original string
return str;
};

Regex using array.filter in javascript

I'm trying to use a regular expression to filter the name column in a csv file that has be put into an object array. Everything works fine if I type the exact value.
values I want "king" to match are below:
kingkong, king kong, king-kong, king_kong, king11, kongking, kong-king, kong_king, kong king, 11king
I've tried using filter and find methods but I want to use filter to return multiple values if they exist. I have tried the following regex but can't figure out the proper sytax if it is even correct.
const CSVToJSON = require('csvtojson');
const user = "king";
CSVToJSON().fromFile("./locations.csv").then(source => {
var found = source.filter(function(v, i){
return ((v["name"]== /\bking.*/g));
})
You can use the following approach.
const CSVToJSON = require('csvtojson');
CSVToJSON().fromFile("./locations.csv").then(source => {
var found = source.filter(function(v, i){
return ((v["name"].match(/king/g)));
});
return statement could be something like
return ((/king/g).test(v["name"]));
OR
return ((v["name"].match(/king/g)));
Both should work
However, your sample patterns show that king might stand either at the beginning or at the end of the target (bot can't have both prefix and suffix). If I am right, that means you don't need regex for that.
const CSVToJSON = require('csvtojson');
const user = "king";
CSVToJSON().fromFile("./locations.csv").then(source => {
var found = source.filter((v, i) => v.startsWith(user) || v.endsWith(user))
/*rest of the code */
});
If king can stand anywhere, you can simply use includes instead.
This is what worked, I'm totally new to JavaScript:
const user = args;
var regex = new RegExp(user, "g");
CSVToJSON().fromFile("./locations.csv").then(source => {
var found = source.filter(function(v, i){
return ((v["name"].match(regex)));
})

How to split Json response and get specific part using angular

I am developing angular blockchain application using hyperledger composer tool.When i query the historian i got a response like in the below.
{
transactionType:"org.hyperledger.composer.system.AddParticipant"
}
I display the transaction type using follwing code snippet.
<div class="col-md-6">
{{participant.transactionType}}
</div>
The displayed part like this.
org.hyperledger.composer.system.AddParticipant
but I only want to display the 'AddParticipant' part in the response without 'org.hyperledger.composer.system.' part. How can I fix it?
For that just do little string manipulation. Make use of JS .split() method which splits string by argument character/string.
let arr = this.participant.transactionType.split(".");
then arr[arr.length-1] is your required string part which you can bind to view. Like use below {{txTyepe}} in template binding
this.txType = arr[arr.length-1];
you can use "substr" to pick a word from string but you need position of your word in your string first so :
const str = 'org.hyperledger.composer.system.AddParticipant'
let getPosition = str.indexOf('AddParticipant'); // get the position of AddParticipant
let getWord = str.substr(getPosition,13);
the length of AddParticipant is 13 also you can change the code above for better and cleaner and multi use code
const splitWord = (index)=>{
const str = 'org.hyperledger.composer.system.AddParticipant'
let strArray = str.split('.')
let getPosition = str.indexOf('AddParticipant'); // get the position of AddParticipant
let getWord = str.substr(getPosition,strArray[index].lenght); //you just need to change the number
return getWord;
}
console.log(splitWord(4));
You can also get the last "word" with regular expression :
<div class="col-md-6">
{{participant.transactionType.match(/\w+$/i)}}
</div>
When you see your historian data it'll look something like this
'$namespace': 'org.hyperledger.composer.system',
'$type': 'HistorianRecord',
'$identifier': '6e43b959c39bdd0c15fe45587a8dc866f1fa854d9fea8498536e84b45e281b31',
'$validator': ResourceValidator { options: {} },
transactionId: '6e43b959c39bdd0c15fe45587a8dc866f1fa854d9fea8498536e84b45e281b31',
transactionType: 'org.hyperledger.composer.system.IssueIdentity',
transactionInvoked:
Relationship {
'$modelManager': [Object],
'$classDeclaration': [Object],
'$namespace': 'org.hyperledger.composer.system',
'$type': 'IssueIdentity',
'$identifier': '6e43b959c39bdd0c15fe45587a8dc866f1fa854d9fea8498536e84b45e281b31',
'$class': 'Relationship' },
So, instead of taking transactionType you can use the transactionInvoked object. And then you can get whatever information you want from that object.
Finally your code should be like this
<div class="col-md-6">
{{participant.transactionInvoked.$type}}
</div>
In my case it will give me transaction type as just 'IssueIdentity'.

using split and map in jsx

const arr = ['name', 'contact number']
const App = () => (
<div style={styles}>
Add {arr.split(',').map(o=>o)}
</div>
);
why this won't work? I want to print Add name & contact, but stuck at splitting it.
You're using 2 functions wrong:
split is supposed to be used to split a string into an array, around the provided character. You already have the resulting array.
.map(o=>o) is useless - it basically returns the same array provided.
You're probably looking to do this Add {arr.join(' & ')}.
You are looking to join the values
Add {arr.join(',')}
Below links should help you
MDN split
MDN join
There is nothing to split. I think you are trying to join them:
const arr = ['name', 'contact number']
const App = () => (
<div style={styles}>
Add {arr.join(',')}
</div>
);

Categories

Resources