Loop through string and style individual letters - javascript

I have the title "INTRO TO GRID", and I want to individually style the letters in the string "GRID". I know I could do this with CSS, but I want to try with JS. I am having difficulty figuring out how to attach .css() to the individual letters. I have attached my code for reference. Thanks in advance!
var header = $("#header").text();
var grid = header.substring(9, header.length);
var chars = grid.split("");
for(var i = 0; i < chars.length; i++){
console.log(chars[i]);
}
console.log(chars);
With the help previous commenters, here is the solution to my problem.
var header = $("#header");
var chars = header.text().split("");
var headerSpans = chars.map(function(char){
return $('<span>' + char + '</span>');
});
$(header).html(headerSpans);
for(var i=9; i <= headerSpans.length; i++){
headerSpans[i].css({
"margin" : "20px",
"background-color" : "red"
});
}

#Jon Uleis is right, you cannot style individual characters. But you can style DOM elements, like <span>:
var header = $('#header'),
headerSpans = header.text()
.split("")
.map(function(char){
return $('<span>' + char + '</span>');
});
header.html(headerSpans);
headerSpans[9].css('color', 'red');
headerSpans[10].css('color', 'blue');
headerSpans[11].css('color', 'green');
headerSpans[12].css('color', 'orange');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="header">INTRO TO GRID</div>

You can change the style of elements with JavaScript using style object which can be accessed from specific HTML element or from the head section of the document. Find more about style document here.
There are plenty of solutions for your problem but I tried to provide you one which is simple to understand.
My solution:
You need to get HTML element where you will store your text. (In my example it is div element which id is root)
Store every character of your text in one array. (In my example, name of array is text).
Loop through array of characters with forEach method.( More about forEach here).
Create new span element for every letter inside forEach method.
Wrap every character in text node and append it to created span.
Style every span however you want to. (If statement is used to limit styling only to the word "GRID").
Append created and styled span to the div element where text will be displayed.
Solution code:
const div = document.getElementById(`root`); // div from HTML
const text = `INTRO TO GRID`.split(``); // every character of your text stored in array
text.forEach((char, index) => {
const node = document.createElement(`span`); // create new span element
const textnode = document.createTextNode(char); // create character as text node for span element
node.appendChild(textnode); // add text to span
// if you want only to style characters only in the word `GRID`
if(index >= text.length - `GRID`.length){
// style the characters however you want to
node.style.color = index % 2 === 0 ? `red` : `black`; // change color
node.style.fontWeight = index % 2 !== 0 ? 900 : 1; // change font weight
}
div.appendChild(node); // add span (character) to the div element in HTML
});
<div id="root">
</div>

Related

Dom manipulation with for loop

I am trying to do append() function. i have a table of data. i run a loop to first remove text in cell then i will append a new tag.this usecase is to create a progress bar. for an example
data sample inside cell is e.g 39% 39% 82% etc etc
let cf_percent;
let cf_regex;
for(let i = 0 ;i < tbl[0].length;i++){
cf_percent = tbl[0][i].innerHTML
cf_regex = cf_percent.replace(/[`~%]/gi, '');
console.log(cf_regex)
//Clear fields
tbl[0][i].innerHTML = ''
tbl[0][i].append('<p>Textfield</p>');
}
It should return texfield but instead, it is returning '<p> textfield </p>' in table cell.it should return textField. i have tried .html() but this does not work for this usecase.
in d3.js append function appends a new element with the specified name as the last child of each element in the current selection, returning a new selection containing the appended elements.
So to append p element use: tbl[0][i].append("p") and to set text use .text() further: e.g.
tbl[0][i].append("p").text("Textfield")
I will suggest to use:
let cf_percent;
let cf_regex;
for(let i = 0 ;i < tbl[0].length;i++){
cf_percent = tbl[0][i].innerHTML
cf_regex = cf_percent.replace(/[`~%]/gi, '');
console.log(cf_regex)
//Clear fields
tbl[0][i].innerHTML = ''
tbl[0][i].innerHTML += `<p>Textfield</p>`;
}
You have 2 options. The first is along what you are trying to do where you set the innerHTML to a string. The second is actually generating an element and then appending it. Your current scenario seems to be mixing the two.
const div1 = document.getElementById('sample1'),
div2 = document.getElementById('sample2'),
p = document.createElement('p');
div1.innerHTML = '<p>This set the innerHTML</p>';
p.innerText = 'This is a p appended to a div';
div2.appendChild(p);
#sample1 {
background-color: red;
}
#sample2 {
background-color: yellow;
}
<div id="sample1"></div>
<div id="sample2"></div>

How would i apply CSS to some text via DOM? (No Libraries, Just Javascript)

We are currently learning how to use the DOM and some javascript commands to make dynamic websites. My main and only problem so far is that my CSS won't apply to the HTML I have added to my <p> tag with the id="paragraph":
1.What am i doing wrong?
2.What can i do differently?
3.What can help clean up my code?
function Music() {
var string = document.getElementById('text').value.match( /[^\.!\?]+
[\.!\?]+/g ); // This searches through our text, puts results into an
array
for (var i = 0; i < string.length; i++) { // This goes through our "string array"
var space = string[i].match(/\s/g ); // Counts the amount of
spaces in each string.
var wrapEl = document.createElement("span"); // Create a span tag
wrapEl.innerHTML = string[i]; // place strings into span tag
// This clears the paragraph element and refills it with the new text output.
if (string.length > 0) {
document.getElementById("paragraph").innerHTML = "You didn't
write anything!";
} else {
console.log("You Didn't write anything!");
}
switch (space.length) {
case space <=2: //Tiny (0-2 words) - Yellow Highlight
span.addClass("style1");
break;
case space <=5: //Short (3-5 words) - Red Highlight
span.addClass("style2");
break;
case space <=14: //Medium (6-14 words) - Green Highlight
wrapEl.addClass("style3");
break;
case space >15: //Long (15+ words) - Blue Highlight
wrapEl.addClass("style4");
break;}
var paragraph = document.getElementById("paragraph");
paragraph.appendChild(wrapEl); // append span tag to paragraph tag via id
}
}
!!!For reference, Im using a tag in my HTML as the place to type your text. And i put all my CSS classes in the with the tag.!!!
You are currently trying to add a class to the DOM elements using .addClass(). This is actually a jQuery method, not vanilla JavaScript. I would rather suggest you add a class using classList.add().
Note: classList is not supported in Internet Explorer 9 and below. If you need to support older versions of IE, go with className += "style1" as described in this answer
You also have a few instances of span.addClass("style1"). From the code posted in your question, there is no span variable. Should this be wrapEl?
The following should do it:
var wrapEl = document.querySelector('span');
wrapEl.classList.add('style1')
.style1 {
color: red
}
<p>This is unaffected. Should be black.</p>
<span>This has .style1 applied. Should be red</span>

How can I change the color of one letter in JavaScript?

I have a string and I want to change just one color letter in JavaScript.
HTML:
<div id="lettersList">Hello</div>
In my JavaScript file, I retrieve like this (normal)
var lettres = document.getElementById("lettersList");
But I don't know how to change the color of just one word (the 'o' of "hello" for example).
If I change thanks to
for (var i=0; i<lettres.length; i++ { lettres[i].style.color = "yellow"; }
it changes all the text (of course). But I don't want that.
You can use the replace() method on the innerHTML property of the element:
const element = document.querySelector('#lettersList');
element.innerHTML = element.innerHTML.replace('o', '<span style="color: red;">o</span>');
<div id="lettersList">Hello</div>
In your code :
var letters = document.getElementById()
you actually retrieve the whole element, not the text in it. That might be the reason that it changed its color totally.
So I suggest you to use
document.getElementById().innerHtml()
.
This function will retrieve the content in your HTML tags (div). Then you do the color changing like
for(var i = 0; i<letters.length; i++){
//only change the one you want to
if(i == 4 // or whatever you like){
element.innerHTML = element.innerHTML.replace(letters[i], '<span style="color: yellow;">'+letters[i]+'</span>');
}
}
it works with
for(var i = 0; i<letters.length; i++){ if(i == 4 { element.innerHTML =element.innerHTML.replace(letters[i], '<span style="color:yellow;">'+letters[i]+'</span>');}}
But if a word contains two similar letters, I can't color the both... Why that ?
if a word contains two similar letters then with the for loop we can use position of letter as i inside
if i == n , replace(letter[n], styled span tag)

JAVASCRIPT - if last character is : (colon), change font weight

Is it possible to change font weight if last character is colon with JavaScript?
I have site, where people can add recipe. And i want to highlight parts of ingredients of recipe. For example:
topping:
-chocolate
-milk
filling:
-...
-...
I searched and i found that codes:
for last character
if (myString.charAt(myString.length - 1) == ':')
and for weight change
function changeWeight(600)
{
document.getElementById("id_1").style.fontWeight = fontWeight;
}
I do not know how to write the code to work. I am beginner.
Thank you very much.
Try this
if (myString.charAt(myString.length - 1) == ':') {
changeWeight("600");
}
function changeWeight(weight) {
document.getElementById("id_1").style.fontWeight = weight;
}
It seems that you want to make specific text bold, not all text within an element. You would need to get the text out of the element, change it, and put it back.
You can use code like this to but a bold tag around all words in the element that ends with a colon:
var element = document.getElementById("id_1");
var text = element.innerHTML;
text = text.replace(/([A-Za-z]+:)/g, '<strong>$1</strong>');
element.innerHTML = text;
Note: For that to work properly, you can't have other HTML elements inside the element that has words with colons in the actual markup. I you have for example SO in the code, it would break because of the http: in the link.
If you have that single word alone in an element, you would get the text and check for the colon:
var element = document.getElementById("id_1");
var text = element.innerHTML;
if (text.charAt(text.length - 1)) == ':') {
element.style.fontWeight = 'bold';
}

Remove tag if id matches but keep text

I have a highlighter function that formats the matched words to an anchor with yellow bg-color and I need a function to remove the anchor elements for the next search.
The markup of a matched word, for the first one looks like this:
<a id="searchword1" class="searchword" style="background-color: yellow; text-decoration: none; color: black;">my text</a>
I need to remove the anchor but leave my text there. There are other anchors in my document that I dont want to interfere with. I need to do this in pure Javascript (no jQuery).
An addational requirement: Don't create new lines after tag removal, leave it as it was.
Thanks to enhzflep, the code until now:
for (z=0;z<szam;z++){
var removal = parent.frames['pagina'].document.getElementById("searchword"+z);
var highlightedText = removal.innerHTML.toLowerCase;
removeh(removal,highlightedText,doc);
}
function removeh(node,high,doc) {
doc = typeof(doc) != 'undefined' ? doc : document;
if (node.hasChildNodes) {
var hi_cn;
for (hi_cn=0;hi_cn<node.childNodes.length;hi_cn++) {
removeh(node.childNodes[hi_cn],high,doc);
}
}
//1. Get element containing text
if (node.nodeType == 3) {
tempnode = node.nodeValue.toLowerCase();
if (tempnode.indexOf(high) != -1) {
nv = node.nodeValue;
nv = node.nodeValue;
ni = tempnode.indexOf(high);
//2. Get the text it contains
before = doc.createTextNode(nv.substr(0,ni));
dochighVal = nv.substr(ni,high.length);
after = doc.createTextNode(nv.substr(ni+high.length));
//3. Get the highlighted element's parent
var daddy = node.parentNode;
//4. Create a text node:
var newNode = document.createTextNode(dochighVal);
//5. Insert it into the document before the link
daddy.insertBefore(before, node);
daddy.insertBefore(newNode, node);
daddy.insertBefore(after, node);
//6. Remove the link element
daddy.removeChild(node);
}
}
}
Where num is the number of matched words.
For some reason this wont work, please help, I will accept the answer that solves this minor problem too.
Two answers had the method right but it is still buggy as it separates the resulting text with new lines. This makes the highlighter function to get the "my word" as separate temporary node values and won't be able to highlight a match for /my.word/.
If I understand you correctly, you wish to turn this:
<a id="searchword1" class="searchword" style="background-color: yellow; text-decoration: none; color: black;">my text</a>
into this:
my text
If that's the case, then it's very easy.
As it stands, it looks like you're asking for an child of the element you showed (the element doesn't have any children, other than the text-node. I expect your script is hosed by line 2 - when it tries to get a non-existent child)
//1. Get element containing text
var element = document.getElementById('searchWord1');
//2. Get the text it contains
var highlightedText = element.innerHTML;
//3. Get the highlighted element's parent
var parent = element.parentNode;
//4. Create a text node:
var newNode = document.createTextNode(highlightedText);
//5. Insert it into the document before the link
parent.insertBefore(newNode, element);
//6. Remove the link element
parent.removeChild(element);
If you are using jQuery it will be simple DEMO
$('#searchword1').contents().unwrap();
But if you only want to use js for this there is solution by user113716 on the Link
DEMO
var b= document.getElementsByClassName('searchword');
while(b.length) {
var parent = b[ 0 ].parentNode;
while( b[ 0 ].firstChild ) {
parent.insertBefore( b[ 0 ].firstChild, b[ 0 ] );
}
parent.removeChild( b[ 0 ] );
}

Categories