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 ).
Related
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 />?
I'm not sure this is possible but I wondered if there is a way of targeting the last word in a line of text within a paragraph. Note that I'm not looking for the last word in the paragraph but the last word in a line of said paragraph.
I haven't the faintest idea of how to start with this so haven't got an attempt formulated.
Thanks for any help you can offer!
Mark
I found a JS library, jsLineWrapDetector, which can retrieve the lines from the text wrapped by DOM element.
var p = $("p")[0];
var lines = lineWrapDetector.getLines(p);
lines.forEach(function(line) {
var lastword = line.split(" ").pop();
});
You can get the text of p tag, split them on occurrence of space to create the array of word. then target the last element in returned array. Like this:
var wordarray = $('p').text().split(" ");
return wordarray [wordarray.length - 1];
You can use this function :
function getLastWord(paragraph, line) {
return paragraph.split("\n")[line].split(" ").pop();
}
Working Example
The code below will find the last word of each line (of a p tag), and throw all of them in the console. words[i - 1], or breakWord is the last word of each line. Hopefully, this helps.
var breakWord
var p = $('p');
p.each(function () {
var current = $(this);
var text = current.text();
var words = text.split(' ');
current.text(words[0]);
var height = current.height();
for (var i = 1; i < words.length; i++) {
current.text(current.text() + ' ' + words[i]);
if (current.height() > height) {
height = current.height();
breakWord = words[i - 1];
console.log(breakWord);
}
}
console.log(current);
});
This code will split the whole paragraph up into single words, put them in an array (words), and then check for line breaks. When a line break is found, it returns the last word of the line.
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
I have a HTML textarea with a string split across multiple lines. for example
cat
dog
horse
What I'm then trying to do is insert these strings into a html table. the HTML table ( I'm using jquery.datatables) seems to ignore the newlines. So what I'm
<textarea id='txttest' name="texttest" ></textarea>
I've tried replacing the text like so but both of these do not work.
var res = $("textarea#txttest").val().replace(/\/n/,"<br>");
or
var res = $("textarea#txttest").val().replace(/
/,"<br>");
I then insert the result into my datatable
$('table#table_flows').dataTable().fnAddData( [
res ] );
but the newlines are not being replaced by < br >
How do I do this?
thank you.
You have an extra slash in your .replace and you need to add a g to make it a global replace rather than just the first occurence.
Try
var res = $("textarea#txttest").val().replace(/\n/g,"<br>");
Example
Try this: split into an array using NewLine as separator, then rejoin the string array with <br />
var res = $("textarea#txttest").val().split("\n").join('<br />');
$('table#table_flows').dataTable().fnAddData( [ res ] );
Check the result here
I didn't try any example using replace(), like you were just doing. Instead, I put together an example using split() that splits the value at the \n character.
http://jsfiddle.net/TY22g/
var cell = document.getElementsByTagName("td")[0];
var textarea = document.getElementsByTagName("textarea")[0];
textarea.addEventListener("change", function() {
var array = textarea.value.split("\n");
var i = 0, length = array.length;
for (i; i < length; i++) {
cell.innerHTML += array[i] + "<br/>";
}
});
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(...).