How to append uppercase text only? - javascript

I have an <h2> tag that is generated based on an image's alt text. I want to add a style to the parts of the text that are uppercase.
My plan is use javascript / jquery to find the uppercase text and wrap it in a <strong> tag, then use css to style this.
Any ideas how this can be done?
Thanks!

sometext.match(/[A-Z]+/g) gives you an array of all uppercase text in a string, so loop that to add style.
To match at least 2 uppercase characters use .match(/([A-Z]+){2}/g)
To surround all uppercase string parts with length >= 2 within a string with (for example) <b></b> use:
sometext.replace(/([A-Z]+){2}/g,function(a){return '<b>'+a+'</b>';});

function findUC() {
var h2 = $('h2').text();
var exploded = h2.split(' ');
var pattern = new RegExp('[^A-Z]');
var i;
var style = '';
for (i = 0; i < exploded.length; i++) {
if (!exploded[i].match(pattern)) {
style += '<span style="color:blue;">' + exploded[i] + '<span>';
} else {
style += exploded[i];
}
}
$('h2').text(style);
}
findUC();​
This will help you. Modify this according to your requirement. Working fiddle is here
For your requirement you mentioned, I'm editing this answer.
function findUC() {
var h2 = $('h2').text();
var exploded = h2.split(' ');
var pattern = new RegExp('[^A-Z]');
var i, j;
var style = '';
var character = '';
for (i = 0; i < exploded.length; i++) {
if (!exploded[i].match(pattern)) {
var firstletter = exploded[i].substr(0,1);
var lastletter = exploded[i].substr(1, exploded[i].length);
style += firstletter;
style += '<span style="color:blue;">' + lastletter + '<span>';
} else {
style += " "+exploded[i]+" ";
}
}
$('h2').text(style);
}
findUC();​
Fiddle is mentioned in my last comment. Try it out.
EDIT 3:
As you mentioned in comments I have modified the fiddle: try this fiddle

You can use regular expressions to find the uppercase passages. Just some regular expression like /[A-Z]{2,}/g. Due to the {2,} this will only match at least two uppercase characters following each other. As an alternative, you could use /\b[A-Z]+\b/g if you'd like to exclude words like HELlo. Once you've got the positions, you can use different approaches to connect/create the HTML code, e.g. $('<div/>').append(...).

Related

Javascript replace already replaced text

I have two textareas written in HTML like this:
<textarea id="checked-words"></textarea>
<br />
<textarea id="words" onkeyup="displayColoredText()"></textarea>
<div id="text-to-insert"></div>
(into the div element, I will insert text, using JavaScript)
My task is to write into the div section the text from the second textarea and make red the occurrences of strings from the first textarea.
Example
If the first textarea contains the following words: aaa, aab and the second contains aaab, all of the characters have to be red. If the second one contains abaa, none of the characters will be red in the div section.
Here is my JavaScript function which displays and colorize the text:
function displayColoredText() {
//Displays the colored text below the second textarea
//Find the two textareas
var firstTextArea = document.getElementById('checked-words');
var secondTextArea = document.getElementById('words');
//Split by spaces
var checkedWords = firstTextArea.value.split(" ");
var text = secondTextArea.value.split(" ");
var textToInsert = secondTextArea.value;
for(i in checkedWords) {
console.log(checkedWords.length);
textToInsert = textToInsert.replace(new RegExp(checkedWords[i], 'g'), '<span class="insertRed">' + checkedWords[i] + '</span>');
}
document.getElementById('text-to-insert').innerHTML = textToInsert;
}
My problem is, that an already replaced text won't be considered, for example, if the first textarea contains aaa and aab and if the second one contains aaab, only the first three characters will be red, instead of the whole string. How can I resolve this?
EDIT: Screenshot of the problem
Your original input from the second text area is pure text, not HTML, so this is the "state" of the data you want to do this in.
This would be my way of implementing it as mentioned in comments, recording which positions have a match first, and then simply looping over all characters in the end to wrap them in a span each:
function displayColoredText() {
//Displays the colored text below the second textarea
//Find the two textareas
var firstTextArea = document.getElementById('checked-words');
var secondTextArea = document.getElementById('words');
//Split by spaces
var checkedWords = firstTextArea.value.split(" ");
var text = secondTextArea.value;
// empty array with keys 0 to length-1 set to undefined
var markedMatches = new Array(secondTextArea.value.length);
for (var i = 0, l = checkedWords.length; i < l; ++i) {
var checkedWord = checkedWords[i],
start = 0,
matchPos;
// check for match from current starting position
while ((matchPos = text.indexOf(checkedWord, start)) !== -1) {
// mark positions from current match start to that plus length of match
for (var k = matchPos, m = matchPos + checkedWord.length; k < m; ++k) {
markedMatches[k] = true;
}
// advance starting position to continue searching
start = matchPos + 1;
}
}
var textToInsert = '';
for (var i = 0, l = text.length; i < l; ++i) {
// wrap in span if markedMatches contains true at this position
textToInsert += (markedMatches[i] ? '<span class="match">' + text[i] + '</span>' : text[i]);
}
document.getElementById('text-to-insert').innerHTML = textToInsert;
}
https://jsfiddle.net/t9xjzkaw/
As I said, you could get more sophisticated in collecting the matches as intervals, or putting multiple adjoining matching characters into a single span element, instead of wrapping each one on its own ... but this does the basic job.
Your problem is how your strings get replaced. Your first string is 'aaa aab'. After replacing for 'aaa' in 'aaab', you get '<span class="insertRed">aaa</span>b'. Trying to find 'aab' in this string will come up with no results. You have to replace from your original string and somehow combine the two. I'm not sure how to do this, but I hope this sets you on the right track.
EDIT:
I think this will work:
Instead of replacing the text in the string, place the beginning coordinate in an array and the end coordinate in a second array. Keep doing this for every word found. Then at all of the beginning coordinates, insert the string '<span class="insertRed">'. At all of the end coordinates, insert the string '<span>'. Here is the JS:
function displayColoredText() {
//Displays the colored text below the second textarea
//arrays with coordinates
var beginnings = [];
var ends = [];
//Find the two textareas
var firstTextArea = document.getElementById('checked-words');
var secondTextArea = document.getElementById('words');
//Split by spaces
var checkedWords = firstTextArea.value.split(" ");
var text = secondTextArea.value.split(" ");
var textToInsert = firstTextArea.value;
for(i in checkedWords) {
console.log(checkedWords.length);
if (firstTextArea.value.indexOf(checkedWords[i]) != -1) {
beginnings.push(firstTextArea.value.indexOf(checkedWords[i]));
ends.push(firstTextArea.value.indexOf(checkedWords[i]) + checkedWords[i].length);
}
}
beginnings.sort(function(a, b){return b-a});
ends.sort(function(a, b){return b-a});
for (b in beginnings) {
textToInsert = textToInsert.slice(0, ends[b]) + "</span>" + textToInsert.slice(ends[b]);
textToInsert = textToInsert.slice(0, beginnings[b]) + '<span class="insertRed">' + textToInsert.slice(beginnings[b]);
}
document.getElementById('text-to-insert').innerHTML = textToInsert;
}
This code is untested, so tell me if something doesn't work and I will change it. Basically, what I am doing is instead of replacing occurrences, I find them first, place them in arrays, and insert the correct text at those coordinates. I hope this helps!

Insert line break every 3 lines in javascript?

Hi I'm still a newbie at javascript so I want to create a script that inserts a line break after every 3 lines. So here's my code I got so far
var num = `http://url.com
http://url2test.com
http://url3nag.com
http://url4lalala.com
http://url5papapapapa.com
http://url6ddadadadad.com
http://url7etet.com
http://url8testtest.com`;
var newNum = num.toString().match(/.{3}/g).join('</br>');
console.log(newNum);
It is doing it wrong. It seems to be inserting every 3characters instead of lines. Can anyone help me fix the code?
You can use the replace function. Try the below code.
var num = `http://url.com
http://url2test.com
http://url3nag.com
http://url4lalala.com
http://url5papapapapa.com
http://url6ddadadadad.com
http://url7etet.com
http://url8testtest.com`;
var newNum = num.replace(/(.*\n.*\n.*\n)/g, '$1<br>');
console.log(newNum);
EDIT
I have made a few changes to the RegEx in the code below. This will allow you to specify the number of lines between which <br> need to be added.
var num = `http://url.com
http://url2test.com
http://url3nag.com
http://url4lalala.com
http://url5papapapapa.com
http://url6ddadadadad.com
http://url7etet.com
http://url8testtest.com`;
var newNum = num.replace(/((.*\n){3})/g, '$1<br>');
console.log(newNum);
In the above RegEx, the .* will match all characters till the end of line and the \n will match the new line character.
(.*\n){3}
I have enclosed this in parenthesis to mark it as a group and used {3} to indicate that the preceding group repeats 3 times.
((.*\n){3})
Then the whole RegEx is enclosed in a parenthesis to use it as the first matched group that can be referenced in the replace section using $1.
You can replace the {3} with any number.
You should avoid using string manipulation when using HTML string. Also using BR to break line is not a good idea as well. You should use a block element instead.
var num = `http://url.com
http://url2test.com
http://url3nag.com
http://url4lalala.com
http://url5papapapapa.com
http://url6ddadadadad.com
http://url7etet.com
http://url8testtest.com`;
var content = document.querySelector('.content');
var urls = num.split('\n');
var temp;
for(var i = 0; i< urls.length; i++) {
if(!temp || (i+1) % 3 === 0) {
if (temp) content.appendChild(temp);
temp = document.createElement('div');
}
var span = document.createElement('span');
span.classList.add('link')
span.innerHTML = urls[i];
temp.appendChild(span);
}
content.appendChild(temp);
.link {
margin: 5px;
}
<div class='content'>
Reference:
Is it sometimes bad to use <BR />?

How to remove html tag from string but keep html entities intact

I would like to remove the HTML tags (element) from a string without touching the html entities such as &nbps; & é < etc..
For now I am using this :
stringWithTag = "<i> I want to keep my -> <- element space, but remove the tags <b>Please Help</b></i>";
var div = document.createElement('div');
div.innerHTML = stringWithTag;
console.log("INPUT with html entity ");
console.log(stringWithTag);
htmlNoTag = div.textContent || div.innerText || "";
console.log("\nOUTPUT that should still have entity , but not...");
console.log(htmlNoTag);
cf jsfiddle : https://jsfiddle.net/az4st8LL/
But I always miss the element entity (in that exemple &nbsp should still be visible but it is not the case).
I would like to avoid using a regex to remove all html tags if possible.
Does anyone has a solution to this ?
Thanks,
Since you want to avoid using regex, try
function stripTags(html) {
var result = "";
var add = true, c;
for (var i = 0; i < html.length; i++) {
c = html[i];
if (c == '<') add = false;
else if (c == '>') add = true;
else if (add) result += c;
}
return result;
};
This will not work for
<i>I want to keep my -> <- element space, but remove the tags <b>Please Help</b></i> since you used < and > but will turn <i> I want to keep my element space, but remove the tags <b>Please Help</b></i> into I want to keep my element space, but remove the tags Please Help
You might want to consider using a regex anyway (stolen from this answer):
string.replace(/<(?:.|\n)*?>/gm, '')
stringWithTag = "<i> I want to keep my element space, but remove the tags <b>Please Help</b></i>";
console.log(stringWithTag.replace(/<(?:.|\n)*?>/gm, ''));
I cheated a little bit by removing the "->" and "<-" from your string - since the regex matches everything between "<" and ">", those characters broke the demo.
You can use a regex that searches for tags and reverse it. Then replace your string with this regex and encodeURIComponent values. Then you can decodeURIComponent when you need to use it.
var stringWithTag = "<i> I want to keep my -> <- element space, but remove the tags <b>Please Help</b></i><i> I want to keep my -> <- element space, but remove the tags <b>Please Help</b></i><i> I want to keep my -> <- element space, but remove the tags <b>Please Help</b></i><i> I want to keep my -> <- element space, but remove the tags <b>Please Help</b></i>";
var tags = stringWithTag.match(/(<[^>]>|<\/[^>]>)/g);
var startIndex = 0;
var str = "";
tags.reduce(function(p,c){
var i = stringWithTag.indexOf(p, startIndex)+ p.length;
var j = stringWithTag.indexOf(c, startIndex);
str += p+ encodeURIComponent(stringWithTag.substring(i,j)) + c;
startIndex = j;
return c
})
var div = document.createElement('div');
div.innerHTML = str;
//console.log("INPUT with html entity ");
//console.log(stringWithTag);
htmlNoTag = div.textContent || div.innerText || "";
//console.log("\nOUTPUT that should still have entity , but not...");
console.log(decodeURIComponent(htmlNoTag));
Reference
encodeURIComponent
decodeURIComponent

Split a string of HTML into an array by particular tags

Given this HTML as a string "html", how can I split it into an array where each header <h marks the start of an element?
Begin with this:
<h1>A</h1>
<h2>B</h2>
<p>Foobar</p>
<h3>C</h3>
Result:
["<h1>A</h1>", "<h2>B</h2><p>Foobar</p>", "<h3>C</h3>"]
What I've tried:
I wanted to use Array.split() with a regex, but the result splits each <h into its own element. I need to figure out how to capture from the start of one <h until the next <h. Then include the first one but exclude the second one.
var html = '<h1>A</h1><h2>B</h2><p>Foobar</p><h3>C</h3>';
var foo = html.split(/(<h)/);
Edit: Regex is not a requirement in anyway, it's just the only solution that I thought would work for generally splitting HTML strings in this way.
In your example you can use:
/
<h // Match literal <h
(.) // Match any character and save in a group
> // Match literal <
.*? // Match any character zero or more times, non greedy
<\/h // Match literal </h
\1 // Match what previous grouped in (.)
> // Match literal >
/g
var str = '<h1>A</h1><h2>B</h2><p>Foobar</p><h3>C</h3>'
str.match(/<h(.)>.*?<\/h\1>/g); // ["<h1>A</h1>", "<h2>B</h2>", "<h3>C</h3>"]
But please don't parse HTML with regexp, read RegEx match open tags except XHTML self-contained tags
From the comments to the question, this seems to be the task:
I'm taking dynamic markdown that I'm scraping from GitHub. Then I want to render it to HTML, but wrap every title element in a ReactJS <WayPoint> component.
The following is a completely library-agnostic, DOM-API based solution.
function waypointify(html) {
var div = document.createElement("div"), nodes;
// parse HTML and convert into an array (instead of NodeList)
div.innerHTML = html;
nodes = [].slice.call(div.childNodes);
// add <waypoint> elements and distribute nodes by headings
div.innerHTML = "";
nodes.forEach(function (node) {
if (!div.lastChild || /^h[1-6]$/i.test(node.nodeName)) {
div.appendChild( document.createElement("waypoint") );
}
div.lastChild.appendChild(node);
});
return div.innerHTML;
}
Doing the same in a modern library with less lines of code is absolutely possible, see it as a challenge.
This is what it produces with your sample input:
<waypoint><h1>A</h1></waypoint>
<waypoint><h2>B</h2><p>Foobar</p></waypoint>
<waypoint><h3>C</h3></waypoint>
I'm sure someone could reduce the for loop to put the angle brackets back in but this is how I'd do it.
var html = '<h1>A</h1><h2>B</h2><p>Foobar</p><h3>C</h3>';
//split on ><
var arr = html.split(/></g);
//split removes the >< so we need to determine where to put them back in.
for(var i = 0; i < arr.length; i++){
if(arr[i].substring(0, 1) != '<'){
arr[i] = '<' + arr[i];
}
if(arr[i].slice(-1) != '>'){
arr[i] = arr[i] + '>';
}
}
Additionally, we could actually remove the first and last bracket, do the split and then replace the angle brackets to the whole thing.
var html = '<h1>A</h1><h2>B</h2><p>Foobar</p><h3>C</h3>';
//remove first and last characters
html = html.substring(1, html.length-1);
//do the split on ><
var arr = html.split(/></g);
//add the brackets back in
for(var i = 0; i < arr.length; i++){
arr[i] = '<' + arr[i] + '>';
}
Oh, of course this will fail with elements that have no content.
Hi I used this function to convert html String Dom in array
static getArrayTagsHtmlString(str){
let htmlSplit = str.split(">")
let arrayElements = []
let nodeElement =""
htmlSplit.forEach((element)=>{
if (element.includes("<")) {
nodeElement = element+">"
}else{
nodeElement = element
}
arrayElements.push(nodeElement)
})
return arrayElements
}
Happy code

Regular expression to separate smileys from text

I am trying to create a regular expression in Javascript to separate any occurrence of :) from the surrounding text.
Given the following:
:)This is a line of text :) with several smileys in it :). So there.,:):)
I would like to get the resulting 8 groups:
:)
This is a line of text
:)
with several smileys in it
:)
. So there.,
:)
:)
At the moment I use ([^:)]+) which only groups the surrounding text without the smileys. What adjustment could I make so that the smileys are also grouped?
I'd suggest:
var str = ":)This is a line of text :) with several smileys in it :). So there.,:):)",
matches = str.split(/(\:\))/);
console.log(matches);​
JS Fiddle demo.
Added filtering to remove the empty matches from the above:
var str = ":)This is a line of text :) with several smileys in it :). So there.,:):)",
matches = str.split(/(\:\))/),
matched = [];
for (var i = 0, len = matches.length; i < len; i++) {
if (matches[i].length) {
matched.push(matches[i]);
}
}
console.log(matched);​
JS Fiddle demo.
A further version, with actual on-screen output:
var str = ":)This is a line of text :) with several smileys in it :). So there.,:):)",
matches = str.split(/(\:\))/),
matched = [], li,
list = document.createElement('ol');
document.body.appendChild(list);
for (var i = 0, len = matches.length; i < len; i++) {
if (matches[i].length) {
matched.push(matches[i]);
li = document.createElement('li');
txt = document.createTextNode(matches[i]);
li.appendChild(txt);
list.appendChild(li);
}
}
console.log(matched);​
JS Fiddle demo.
split:
var string = "Given the following: :)This is a line of text :) with several smileys in it :). So there.,:):)";
var groups = string.split(/:\)/);
This will return an array in which each element is a part of text without :).
Since the text has been split on each :), we can construct the result you want by adding a :) between each parts of text:
var parts = [groups[0]];
for (var i = 1; i < groups.length; ++i) {
parts.push(':)');
parts.push(groups[i]);
}
The result is this:
:)
This is a line of text
:)
with several smileys in it
:)
. So there.,
:)
:)
Try this here: http://jsfiddle.net/Gxr6U/3/
If you want to replace smilies by images, you could do this:
var frags = document.createDocumentFragment();
frags.appendChild(document.createTextNode(groups[0]));
for (var i = 1; i < groups.length; ++i) {
var img = document.createElement('img');
img.src='http://../smiley.png';
frags.push(img);
frags.appendChild(document.createTextNode(groups[i]));
}
If you just want to remove smilies:
var text = groups.join('');
The following will successfully group the string you mentioned as you want:
your_match = your_string.match(/(:\)|[^:)]*)/g)
However, like your original RegExp, you will encounter problems if a : or ) appears without being in a smiley. These characters will disappear from the match groups if not within a smiley.
You can use this pattern:
/:\)|(?:[^:]+|:(?!\)))+/g
This matches either :) or any character except : or a : that is not followed a ).

Categories

Resources