I am trying to wrap each individual word on a webpage in a tag so I can style them individually based on their starting letter.
I have found this method of wrapping each word in a span tag individually, but I can't figure out how to vary the class based on the first letter of the word.
let e = document.getElementById('words');
e.innerHTML = e.innerHTML.replace(/(^|<\/?[^>] >|\s )([^\s<] )/g, '$1<span >$2</span>');
CodePudding user response:
What you're trying to achieve can't be done with regex if you want to reference the individual words.
I've wrote a little snippet that uses document.querySelector()
instead
outerText property on the query selector object returns a plain text string which is later converted to an array with split()
function
Then it simply loops over the array and appends the style tag and to get the first letter I've used substring()
function
const words = document.querySelector("#words").outerText.split(" ");
const wordsDiv = document.querySelector("#words")
wordsDiv.innerHTML = ""
words.map((el) => {
wordsDiv.innerHTML = `<span >${el}</span> `
})
<div id="words">red green blue orange</div>
CodePudding user response:
Try this:
let e = document.getElementById('words');
// Create array with words
let words = e.innerHTML.split(' ');
// Object with CSS classes and corresponding letter
const classes = {
a: 'class-one',
b: 'class-two',
// and so on
}
// Return array with the new strings
words = words.map(word => {
const firstLetter = word.substring(0,1);
return `<span >${word}</span>`;
});
// Join the array and update the DOM
e.innerHTML = words.join(' ');
Here the following is happening:
- Words are being separated by a space, creating an array;
- The
classes
constant must receive, as in the example, the correspondence of each letter with its class; - In the function of the
map
method, the first letter of the word is being returned and the classes object is accessed with that letter; - Finally we do a
join
to join all the texts separating them with a space.
Remembering that if there is more than one space between words, inconsistencies will occur, as the first letter will be a space.
CodePudding user response:
From the string.prototype.replace reference, you can also add a replace function to the method, instead of an string. The replace function has this form.
So, if I didn't misinterpret your problem, you can do something similar to this:
let e = document.getElementById('words');
e.innerHTML = e.innerHTML.replace(/(^|<\/?[^>] >|\s )([^\s<] )/g, function(match, p1, p2) {
const myClasses = {
a: "aword",
b: "bword",
...
}
return `${p1}<span >${p2}</span>'
});
CodePudding user response:
You could do something like this:
- Select all the children
- map them with their text content
- Split the text into single words
- map again with some styled html
- Join, render and enjoy.
words.innerHTML = [...words.children].flatMap(el => el.innerText.replace(/\n/ig, " ").split(" ")).map(el => `<div >${el}</div>`).join("")
.someClass {
color: red;
background: orange;
margin: 10px;
}
<div id="words">
<div>
Some dummy content
<span>Some other nested dummy content</span>
</div>
<p>Some sibling content</p>
</div>