What I'm am trying to do is get the html text inside parentheses and transform it to uppercase. I want the output to be:
Cat (IVA)
Dog (MANGO) etc.
What am I doing wrong?
// Transform text inside parentheses to upper case
let petName = $(".petName").text();
let regExp = /\(([^)]+)\)/;
for (var i = 0; i < petName.length; i++) {
let regExp = /\(([^)]+)\)/;
regExp.replace(petName[i].toUpperCase())
}
html
<div>
<h1 class="petName">Cat (Iva)</h1>
</div>
<div>
<h1 class="petName">Dog (Mango)</h1>
</div>
<div>
<h1 class="petName">Puppy (Mara)</h1>
</div>
Multiple things wrong here:
String objects are immutable in JS. regExp.replace(…) does not change the original, it only returns the altered result.`
You are not selecting any elements to begin with. The selector .petName h1 matches h1 elements that are descendants of an element with the class petName
you can not directly call a function while replacing, you need to do this via a callback function, that gets the match(es) passed to it.
let $petNames = $("h1.petName")
$petNames.each(function() {
$(this).text( $(this).text().replace(/\(([^)]+)\)/, function(match) {
return match.toUpperCase()
} ) )
})
This should do it. :)
$(".petName").each(function(i, el) {
const text = el.innerText;
const strToReplace = text.match(/(\(.*\))/)[0];
el.innerText = text.replace(strToReplace, strToReplace.toUpperCase());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<h1 class="petName">Cat (Iva)</h1>
</div>
<div>
<h1 class="petName">Dog (Mango)</h1>
</div>
<div>
<h1 class="petName">Puppy (Mara)</h1>
</div>
Related
I know that document.getElementById() won't work with several ids. So I tried this:
document.getElementsByClassName("circle");
But that also doesn't work at all. But if I use just the document.getElementById() it works with that one id. Here is my code:
let toggle = () => {
let circle = document.getElementsByClassName("circle");
let hidden = circle.getAttribute("hidden");
if (hidden) {
circle.removeAttribute("hidden");
} else {
circle.setAttribute("hidden", "hidden");
}
}
document.getElementsByClassName() returns a NodeList, and to convert it to an array of elements, use Array.from(). this will return an array containing all of the elements with the class name circle
Here is an example, which changes each element with the circle class:
const items = document.getElementsByClassName('circle')
const output = Array.from(items)
function change() {
output.forEach(i => {
var current = i.innerText.split(' ')
current[1] = 'hate'
current = current[0] + ' ' + current[1] + ' ' + current[2]
i.innerText = current
})
}
<p class="circle"> I love cats! </p>
<p class="circle"> I love dogs! </p>
<p class="square">I love green!</p>
<p class="circle"> I love waffles! </p>
<p class="circle"> I love javascript! </p>
<p class="square">I love tea!</p>
<button onclick="change()">Change</button>
You can try this.
const selectedIds = document.querySelectorAll('#id1, #id12, #id3');
console.log(selectedIds);
//Will log [element#id1, element#id2, element#id3]
Then you can do something like this:
for(const element of selectedIds){
//Do something with element
//Example:
element.style.color = "red"
}
Here is my code but I can't display the other numbers because I have indexed [0] and I don't know how I can display the other numbers.
Example string: "Hello, you can contact me at 0744224422 or 0192234422."
Result code : "Hello, you can contact me at <span>0744224422</span> or <span>0744224422</span>."
On this example: my code will replace "0192234422" by 0744224422 "which is logical" but I would like it to display 0192234422... How can I do it ?
Thanks
let selector = document.querySelectorAll('.message > div > .chat');
for (let index = 0; index < selector.length; index++) {
if (selector[index].innerText) {
let text = selector[index].innerText;
const regex = /(\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}/gim;
if (text.match(regex).length) {
const newTexte = ` <span>${text.match(regex)[0].trim()}</span> `;
selector[index].innerHTML = text.replace(regex, newTexte);
};
}
}
If you use the $ replacement character of the replace function, it will put the right text in there. Rather than trim just put parentheses around the non-whitespace portion of your regular expression and effectively let the capturing group become the trim operation.
let selector = document.querySelectorAll('.message > div > .chat');
for (let index = 0; index < selector.length; index++) {
if (selector[index].innerText) {
let text = selector[index].innerText;
const regex = /(\d[\s-]?)?([\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4})/gim;
if (text.match(regex).length) {
const newTexte = ` <span class="red">$2</span> `;
selector[index].innerHTML = text.replace(regex, newTexte);
};
}
}
.red {
background: yellow
}
<div class="message">
<div>
<div class="chat">Hello, you can contact me at 0744224422 or 0192234422.</div>
</div>
</div>
I'm going to try to call attention to the difference in the regular expressions below: (because I added one set of parentheses)
/(\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}/gim
( )
/(\d[\s-]?)?([\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4})/gim;
Do you have two separate instances of the selector? If not then the selector.length is only 1 which is why only the first number is shown. You can edit the html to have more than one instance of the selector (and style with display: inline so that it doesn't line break onto a new line) EX:
let selector = document.querySelectorAll('.message > div > .chat');
for (let index = 0; index < selector.length; index++) {
if (selector[index].innerText) {
let text = selector[index].innerText;
const regex = /(\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}/gim;
if (text.match(regex).length) {
const newTexte = ` <span>${text.match(regex)[0].trim()}</span> `;
selector[index].innerHTML = text.replace(regex, newTexte);
};
}
}
<div class="message">
<div>
<p class="chat" style="display:inline">
Hello, you can contact me at 0744224422 or </p>
<p class="chat" style="display:inline">0192234422</p>
<!-- add more numbers as needed in another <p class="chat" style="display:inline" ></p>-->
</div>
</div>
Thank you for your answers, but I would just like to add a <span></span> (or more) when a phone number is written in the string..
I'm trying to scrape text from an HTML string by using container.innerText || container.textContent where container is the element from which I want to extract text.
Usually, the text I want to extract is located in <p> tags. So for the HTML below as an example:
<div id="container">
<p>This is the first sentence.</p>
<p>This is the second sentence.</p>
</div>
Using
var container = document.getElementById("container");
var text = container.innerText || container.textContent; // the text I want
will return This is the first sentence.This is the second sentence. without a space between the first period and the start of the second sentence.
My overall goal is to parse text using the Stanford CoreNLP, but its parser cannot detect that these are 2 sentences because they are not separated by a space. Is there a better way of extracting text from HTML such that the sentences are separated by a space character?
The HTML I'm parsing will have the text I want mostly in <p> tags, but the HTML may also contain <img>, <a>, and other tags embeeded between <p> tags.
As a dirty hack, try using this:
container.innerHTML.replace(/<.*?>/g," ").replace(/ +/g," ");
This will replace all tags with a space, then collapse multiple spaces into a single one.
Note that if there is a > inside an attribute value, this will mess you up. Avoiding this problem will require more elaborate parsing, such as looping through all text nodes and putting them together.
Longer but more robust method:
function recurse(result, node) {
var c = node.childNodes, l = c.length, i;
for( i=0; i<l; i++) {
if( c[i].nodeType == 3) result += c.nodeValue + " ";
if( c[i].nodeType == 1) result = recurse(result, c[i]);
}
return result;
}
recurse(container);
Assuming I haven't made a stupid mistake, this will perform a depth-first search for text nodes, appending their contents to the result as it goes.
jQuery has the method text() that does what you want. Will this work for you?
I'm not sure if it fits for everything that's in your container but it works in my example. It will also take the text of a <a>-tag and appends it to the text.
Update 20.12.2020
If you're not using jQuery. You could implement the text method with vanilla js like this:
const nodes = Array.from(document.querySelectorAll("#container"));
const text = nodes
.filter((node) => !!node.textContent)
.map((node) => node.textContent)
.join(" ");
Using querySelectorAll("#container") to get every node in the container. Using Array.from so we can work with Array methods like filter, map & join.
Finally, generate the text by filtering out elements with-out textContent. Then use map to get each text and use join to add a space separator between the text.
$(function() {
var textToParse = $('#container').text();
$('#output').html(textToParse);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<p>This is the first sentence.</p>
<p>This is the second sentence.</p>
<img src="http://placehold.it/200x200" alt="Nice picture"></img>
<p>Third sentence.</p>
</div>
<h2>output:</h2>
<div id="output"></div>
You can use the following function to extract and process the text as shown. It basically goes through all the children nodes of the target element and the child nodes of the child nodes and so on ... adding spaces at appropriate points:
function getInnerText( sel ) {
var txt = '';
$( sel ).contents().each(function() {
var children = $(this).children();
txt += ' ' + this.nodeType === 3 ? this.nodeValue : children.length ? getInnerText( this ) : $(this).text();
});
return txt;
}
function getInnerText( sel ) {
var txt = '';
$( sel ).contents().each(function() {
var children = $(this).children();
txt += ' ' + this.nodeType === 3 ?
this.nodeValue : children.length ?
getInnerText( this ) : $(this).text();
});
return txt;
}
alert( getInnerText( '#container' ) );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
Some other sentence
<p>This is the first sentence.</p>
<p>This is the second sentence.</p>
</div>
You may use jQuery to traverse down the elements.
Here is the code :
$(document).ready(function()
{
var children = $("#container").find("*");
var text = "";
while (children.html() != undefined)
{
text += children.html()+"\n";
children = children.next();
}
alert(text);
});
Here is the fiddle : http://jsfiddle.net/69wezyc5/
I'm working on a project where I need to replace all occurrences of a string with another string. However, I only want to replace the string if it is text. For example, I want to turn this...
<div id="container">
<h1>Hi</h1>
<h2 class="Hi">Test</h2>
Hi
</div>
into...
<div id="container">
<h1>Hello</h1>
<h2 class="Hi">Test</h2>
Hello
</div>
In that example all of the "Hi"s were turned into "Hello"s except for the "Hi" as the h2 class.
I have tried...
$("#container").html( $("#container").html().replace( /Hi/g, "Hello" ) )
... but that replaces all occurrences of "Hi" in the html as well
This:
$("#container").contents().each(function () {
if (this.nodeType === 3) this.nodeValue = $.trim($(this).text()).replace(/Hi/g, "Hello")
if (this.nodeType === 1) $(this).html( $(this).html().replace(/Hi/g, "Hello") )
})
Produces this:
<div id="container">
<h1>Hello</h1>
<h2 class="Hi">Test</h2>
Hello
</div>
jsFiddle example
Nice results with:
function str_replace_all(string, str_find, str_replace){
try{
return string.replace( new RegExp(str_find, "gi"), str_replace ) ;
} catch(ex){return string;}}
and easier to remember...
replacedstr = str.replace(/needtoreplace/gi, 'replacewith');
needtoreplace should not rounded by '
//Get all text nodes in a given container
//Source: http://stackoverflow.com/a/4399718/560114
function getTextNodesIn(node, includeWhitespaceNodes) {
var textNodes = [], nonWhitespaceMatcher = /\S/;
function getTextNodes(node) {
if (node.nodeType == 3) {
if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
textNodes.push(node);
}
} else {
for (var i = 0, len = node.childNodes.length; i < len; ++i) {
getTextNodes(node.childNodes[i]);
}
}
}
getTextNodes(node);
return textNodes;
}
var textNodes = getTextNodesIn( $("#container")[0], false );
var i = textNodes.length;
var node;
while (i--) {
node = textNodes[i];
node.textContent = node.textContent.replace(/Hi/g, "Hello");
}
Note that this will also match words where "Hi" is only part of the word, e.g. "Hill". To match the whole word only, use /\bHi\b/g
here you go => http://jsfiddle.net/c3w6X/1/
var children='';
$('#container').children().each(function(){
$(this).html($(this).html().replace(/Hi/g,"Hello")); //change the text of the children
children=children+$(this)[0].outerHTML; //copy the changed child
});
var theText=$('#container').clone().children().remove().end().text(); //get the text outside of the child in the root of the element
$('#container').html(''); //empty the container
$('#container').append(children+theText.replace(/Hi/g,"Hello")); //add the changed text of the root and the changed children to the already emptied element
I have the following html elements from which I have to get some specific texts,
example "John Doe"
I'm a newbie in javascript but have been playing with getElementById etc but I can't seem to get this one right.
<div id="name">
<p><span id="nameheading">name: </span> John Doe</p>
</div>
Bellow is What I have tried:
function askInformation()
{
var nameHeading = document.getElementById("nameheading");
var paragraph = document.getElementsByTagName("p").item(0).innerHTML ;
var name = paragraph[4];
console.log(name); // prints letter (n)
}
I need help please
If you want to get the text following the span in the following:
<div id="name">
<p><span id="nameheading">name: </span> John Doe</p>
</div>
You can use something like:
// Get a reference to the span
var span = document.getElementById('nameheading');
// Get the following text
var text = span.nextSibling.data;
However that is highly dependent on the internal structure, it may be best to loop over text node children and collect the content of all of them. You may also want to trim leading and trailing white space.
You could also get a reference to the parent DIV and use a function like the following that collects the text children and ignores child elements:
// Return the text of the child text nodes of an element,
// but not descendant element text nodes
function getChildText(element) {
var children = element.childNodes;
var text = '';
for (var i=0, iLen=children.length; i<iLen; i++) {
if (children[i].nodeType == '3') {
text += children[i].data;
}
}
return text;
}
var text = getChildText(document.getElementById('name').getElementsByTagName('p')[0]);
or more concisely for hosts that support the querySelector interface:
var text = getChildText(document.querySelector('#name p'));
var paragraph = document.getElementsByTagName("p").item(0).innerHTML ;
var name = paragraph.replace('<span id="nameheading">name: </span>','').trim(); // John Doe