Extracting Partial Text (before the <br>) using getElementsByClassName - javascript

I'm having trouble grabbing the specific piece of text out of the Class attribute. The text has both a name and an ID. Both are important to me, but I need them split and placed in separate arrays.
<span class="locDescription"><b>Name1</b><br> ID1</span>
<span class="locDescription"><b>Name2</b><br>ID2</span>
<span class="locDescription"><b>Name3</b><br> ID3</span>
My first thought was to pop off the last item in each element (convert to string or list, delimit by a " " and pop off the last item). But, I realized that there is not always a space between the Name and ID so that doesn't work.
My second thought was to use the OuterHTML and grab everything before the <br> then do the same with the ID after the <br>.
However, this is what the returned text looks like which using outerHTML:
"<span class=\"locDescription\"><b>Name1</b><br>ID1</span>"
I could not find a way to simply grab before the <br>... that would seem like something one could do easily... maybe I'm missing it.
In lieu of that, I attempted to use indexing to grab the text:
var product_name = []
var elements = document.getElementsByClassName('locDescription');
for(var i=0; i<elements.length; i++) product_name.push(elements[i].outerHTML)
test1 = product_name[0].indexOf('><b>')
console.log(test1)
That came back as -1 so it's not interpreting the garble in that text. Any idea of how I can accomplish this? I think I'm going down a rabbit hole at the moment.

querySelector and childNodes
const spans = [...document.querySelectorAll(".locDescription")];
const details = spans.map(span => {
const name = span.querySelector("b").textContent;
const id = span.childNodes[2].nodeValue;
return { name, id };
});
console.log(details);
<span class="locDescription"><b>Name1</b><br> ID1</span>
<span class="locDescription"><b>Name2</b><br>ID2</span>
<span class="locDescription"><b>Name3</b><br> ID3</span>
const spans = Array.from(document.querySelectorAll(".locDescription"));
const details = spans.map(function(span){
const name = span.querySelector("b").textContent;
const id = span.childNodes[2].nodeValue;
return { name: name, id: id };
});
console.log(details);
<span class="locDescription"><b>Name1</b><br> ID1</span>
<span class="locDescription"><b>Name2</b><br>ID2</span>
<span class="locDescription"><b>Name3</b><br> ID3</span>

You can use the properties .previousSibling and .nextSibling of a Node, those properties include other nodes, meaning TextNodes as well.
Note that you might want to trim() the .textContent of those other Nodes you want, as .textContent returns the text how it is written in your HTML after escaping HTML-Name codes, that means including the white-spaces and line-breaks, if any.
Here is a quick example:
Query for <br>
Use .previousSibling/.nextSibling
Get their .textContent
(Optional) trim() the returned text
var brElement = document.querySelector('br');
console.log(brElement.previousSibling.textContent.trim());
console.log(brElement.nextSibling.textContent.trim());
<p><b>First text</b><br>
Second text</p>

You can use regex to find the two sides:
var element = document.getElementsByClassName("locDescription")[0];
var array = [];
array[0] = element.innerHTML.match(/.*(?=<br>)/)[0];
array[1] = element.innerHTML.match(/(?<=<br>).*/)[0];
console.log(array)
<span class="locDescription"><b>Name1</b><br> ID1</span>
If you want to exclude the <b> tags:
var element = document.getElementsByClassName("locDescription")[0];
var array = [];
array[0] = element.innerHTML.match(/(?<=<b>).*(?=<\/b>)/)[0]
array[1] = element.innerHTML.match(/(?<=<br>).*/)[0];
console.log(array)
<span class="locDescription"><b>Name1</b><br> ID1</span>

Related

Convert words to links and replace them in html

I have a string containing names which could be dynamic(1 or more).....i want to convert those names to hyperlinks...and those hyperlinks will contain those names ..
eg. In string "john,jim,jean".....john will be hyperlinked and redirects to "www.abc.com/john" and so on......
I have already accessed the elements by jquery using....as the are inside elements i used .children().text() the split and save them in regs[]
<label>Ids: <span> john,jim,jean</span></label>
var strr=$('label:contains("IDs:")').children().text();
var regs = strr.split(",")
var reg_length = regs.length;
I dont want to change the text in html, just want to convert them in hyperlinks.
like when click on john will redirect towww.abc.com/john and so on the others name.
without changing the visible string john,jim,jean
i see you used jquery, so i will also
regs = regs.map( s => $(`<a href='www.abc.com/${s}'>${s}</a>`) )
uses map to create the elements from each item of the array, with the help of string templates and jquery.
I hope this is what you are looking for
let spanDom = $("label").find("span");
let str = $(spanDom).text().trim();
let s = str.split(",");
$(spanDom).empty();
s.forEach(function( name ) {
$(spanDom).append("<a href='www.abc.com/"+name+"'>"+name+"</a>,");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label>Ids: <span> john,jim,jean</span></label>
try
let w = ["john", "jim", "jean" ]; // list of known words to link
data.innerHTML = data.innerHTML.replace(/\w+/g,
x=> w.includes(x) ? `${x}` : x)
<label id='data'>Ids: <span> john,jim,jean</span></label>
This is totally achievable provided your strings follow a common separation pattern like a comma (,) or a space. I'll assume that your names in the string are separated by commas and spaces ", " I'll show it without jQuery.
Firstly the <span> element containing the string needs to have an ID. Also, I'm adding a <p> as a placeholder for the hyperlinks.
<span id="names">John, Jim, Jean </span>
<p id="hps"></p>
Now the JavaScript:
nameString = document.getElementById("names").innerHTML; //get the string from <span>
nameArray = nameString.split(", ");
//This method will take the string and break it down wherever it finds the occurrence of the argument (here ", ") and remove these characters and the individual broken down strings are returned as an array
//nameArray has all the names stored in an array
//Let's create an array links that will hold all your <a> elements
links = new Array();
len = nameArray.length; //Get the length of the array i.e. number of names
for (i = 0; i < len; i++) {
links[i] = document.createElement("a"); //create an <a> tag
links[i].setAttribute("href", "www.abc.com/"+nameArray[i]); //Set its href
links[i].innerHTML = nameArray[i]; //Add Link names i.e. contents inside <a></a>
document.getElementById("hps").appendChild(links[i]); //append these links as childs to the <p> parent tag
}

Assigning javascript array elements class or id for css styling

I'm trying to assign class and id to items in an array I created in js and input into my html. I'm doing this so I can style them in my stylesheet. Each item will not be styled the same way.
I'm a beginner so trying to keep it to code I can understand and make it as clean as possible, i.e. not making each of these items an element in the html.
This part works fine:
var pool =['A','B','3','J','R','1','Q','F','5','T','0','K','N','C','R','U']
var letters = pool.join('');
document.getElementById('key').innerHTML = letters;
This part not so much:
var char1 = letters[1];
char1.classList.add('hoverRed');
There is a similar question here that didn't work for me, it just showed [object][object][object] when I ran it.
Your code attempts to apply a style to an array element, but CSS only applies to HTML. If you wish to style one character in a string, that character must be wrapped in an HTML element (a <span> is the best choice for wrapping an inline value).
This code shows how to accomplish this:
var pool =['A','B','3','J','R','1','Q','F','5','T','0','K','N','C','R','U']
var letters = pool.join('');
// Replace a specific character with the same character, but wrapped in a <span>
// so it can be styled
letters = letters.replace(letters[1], "<span>" + letters[1] + "</span>");
// Insert the letters string into the div
var theDiv = document.getElementById('key');
// Inject the string into the div
theDiv.innerHTML = letters;
// Get a reference to the span:
var theSpan = theDiv.querySelector("span");
// Add the style to the <span> that wraps the character, not the character itself
theSpan.classList.add('hoverRed');
.hoverRed {
color:red;
}
<div id="key"></div>
And, this snippet shows how you could apply CSS to any letter:
var pool =['A','B','3','J','R','1','Q','F','5','T','0','K','N','C','R','U'];
// Leave the original array alone so that it can be manipulated any way needed
// in the future, but create a new array that wraps each array element within
// a <span>. This can be accomplished in several ways, but the map() array method
// is the most straight-forward.
var charSpanArray = pool.map(function(char){
return "<span>" + char + "</span>";
});
// Decide which character(s) need CSS applied to them. This data can come from anywhere
// Here, we'll just say that the 2nd and 5th ones should.
// Loop through the new array and on the 2nd and 5th elements, apply the CSS class
charSpanArray.forEach(function(element, index, array){
// Check for the particular array elements in question
if(index === 1 || index === 4){
// Update those strings to include the CSS
array[index] = element.replace("<span>","<span class='hoverRed'>");
}
});
// Now, turn the new array into a string
var letters = charSpanArray.join('');
// For diagnostics, print the string to the console just to see what we've got
console.log(letters);
// Get a reference to the div container
var theDiv = document.getElementById('key');
// Inject the string into the div
theDiv.innerHTML = letters;
.hoverRed {
color:red;
}
<div id="key"></div>
You're on the right track, but missed one key thing.
In your example, pool contains characters. When you combine them using join, you get a string. Setting that string as the innerHTML of an element doesn't give the string super powers, it's still just a string.
In order to get a classList, you need to change your letters into elements and work with them.
I've included an es6 example (and a working plunker) of how to get the functionality you want below.
let pool = ['A','B','3','J','R','1','Q','F','5','T','0','K','N','C','R','U']
const letterToElement = function(char) {
//Create the element
let e = document.createElement("SPAN");
//Create the text node
let t = document.createTextNode(char);
//Put the text node on the element
e.appendChild(t);
//Add the class name you want
e.className += "hoverRed";
return e;
};
//create your elements from your pool and append them to the "key" element
window.onload = function() {
let container = document.getElementById("key");
pool.map(l => letterToElement(l))
.forEach(e => container.appendChild(e));
}
https://plnkr.co/edit/mBhA60aUCEGSs0t0MDGu

How to replace text in js?

Assuming I have the following:
var s = "This is a test of the battle system."
and I had an array:
var array = [
"is <b>a test</b>",
"of the <div style=\"color:red\">battle</div> system"
]
Is there some function or way I could make it such that I can process the string s such that the output would be:
var p = "This is <b>a test</b> of the <div style=\"color:red\">battle</div> system."
Based on the arbitrary elements in the array?
Note that the array elements should be executed in sequence. So looking at the first element in array 1, find the correct place to "replace" in string "s". Then looking at array element 2, find the correct place to "replace" in string "s".
Note that the string could contain numbers, brackets, and other characters like dashes (no <> though)
Update: after Colin DeClue's remark I think you want to do something different than I originally thought.
Here is how you can accomplish that
//your array
var array = [
"is <b>a test</b>",
"of the <div style=\"color:red\">battle</div> system"
];
//create a sample span element, this is to use the built in ability to get texts for tags
var cElem = document.createElement("span");
//create a clean version of the array, without the HTML, map might need to be shimmed for older browsers with a for loop;
var cleanArray = array.map(function(elem){
cElem.innerHTML = elem;
return cElem.textContent;
});
//the string you want to replace on
var s = "This is a test of the battle system."
//for each element in the array, look for elements that are the same as in the clean array, and replace them with the HTML versions
for(var i=0;i<array.length;i++){
var idx;//an index to start from, to avoid infinite loops, see discussion with 6502 for more information
while((idx = s.indexOf(cleanArray[i],idx)) > -1){
s = s.replace(cleanArray[i],array[i]);
idx +=(array[i].length - cleanArray[i].length) +1;//update the index
}
}
//write result
document.write(s);
Working example: http://jsbin.com/opudah/9/edit
Original answer, in case this is what you meant after all
Yes. Using join
var s = array.join(" ");
Here is a working example in codepen
I suppose you've an array of original --> replacement pairs.
To extract the text from an HTML a trick that may work for you is actually creating a DOM node and then extract the text content.
Once you have the text you can use the replace method with a regular expression.
One annoying thing is that searching for an exact string is not trivial because there is no escape predefined function in Javascript:
function textOf(html) {
var n = document.createElement("div");
n.innerHTML = html;
return n.textContent;
}
var subs = ["is <b>a test</b>",
"of the <div style=\"color:red\">battle</div> system"];
var s = "This is a test of the battle system"
for (var i=0; i<subs.length; i++) {
var target = textOf(subs[i]);
var replacement = subs[i];
var re = new RegExp(target.replace(/[\\[\]{}()+*$^|]/g, "\\$&"), "g");
s = s.replace(re, replacement);
}
alert(s);

splitting an html line into separate variables with JS

In pure javascript (not using JQuery/dojo/etc), what is the best/easiest/quickest way to split a string, such as
var tempString = '<span id="35287845" class="smallIcon" title="time clock" style="color:blue;font-size:14px;" contenteditable="false">cookie</span>';
into
var id = 'id="35287845"';
var class = 'class="smallIcon"';
var title = 'title="time clock"';
var style = 'style="color:blue;font-size:14px;"';
var contenteditable = 'contenteditable="false"';
Things to note:
a "space" cannot be used as a proper delimiter, since it may appear in a value, such as title, above (time clock).
maintaining the double quotes around each variable, such as id="35287845" is important
the opening/closing span tags can be discarded, as well as the content, which in this case, is "cookie"
Here is one approach, which is to place the input string as innerhtml into a javascript created dom element and then leverage the attributes array
//Input html string
var tempString = '<span id="35287845" class="smallIcon" title="time clock" style="color:blue;font-size:14px;" contenteditable="false">cookie</span>';
//make element to contain html string
var tempDiv = document.createElement("div");
//place html string as innerhtml to temp element
tempDiv.innerHTML = tempString;
//leverage attributes array on element
var attributeArray = tempDiv.firstChild.attributes;
//log results
console.log(attributeArray);
Note that you may now do something like
var classString = attributeArray.class;
or
var titleString = attributeArray.title;
Edit
Here is a function that will do it:
function getAttributesFromString(htmlString)
{
var tempDiv = document.createElement("div");
tempDiv.innerHTML = htmlString;
return tempDiv.firstChild.attributes;
}
I think you are trying to get the properties in the span, check this response telling you how to do it.
Get all Attributes from a HTML element with Javascript/jQuery
also you could get the properties and make the string concatenating the the values with your strings.
(You can fin a explanation in pure javascript there)

Get element by id with regex

I had a quick question regarding RegEx...
I have a string that looks something like the following:
"This was written by <p id="auth">John Doe</p> today!"
What I want to do (with javascript) is basically extract out the 'John Doe' from any tag with the ID of "auth".
Could anyone shed some light? I'm sorry to ask.
Full story:
I am using an XML parser to pass data into variables from a feed. However, there is one tag in the XML document () that contains HTML passed into a string. It looks something like this:
<item>
<title>This is a title</title>
<description>
"By <p id="auth">John Doe</p> text text text... so on"
</description>
</item>
So as you can see, I can't use an HTML/XML parser for that p tag, because it's in a string, not a document.
Here's a way to get the browser to do the HTML parsing for you:
var string = "This was written by <p id=\"auth\">John Doe</p> today!";
var div = document.createElement("div");
div.innerHTML = string; // get the browser to parse the html
var children = div.getElementsByTagName("*");
for (var i = 0; i < children.length; i++)
{
if (children[i].id == "auth")
{
alert(children[i].textContent);
}
}
If you use a library like jQuery, you could hide the for loop and replace the use of textContent with something cross-browser.
No need of regular expressions to do this. Use the DOM instead.
var obj = document.getElementById('auth');
if (obj)
{
alert(obj.innerHTML);
}
By the way, having multiples id with the same value in the same page is invalid (and will surely result in odd JS behavior).
If you want to have many auth on the same page use class instead of id. Then you can use something like:
//IIRC getElementsByClassName is new in FF3 you might consider using JQuery to do so in a more "portable" way but you get the idea...
var objs = document.getElementsByClassName('auth');
if (objs)
{
for (var i = 0; i < objs.length; i++)
alert(obj[i].innerHTML);
}
EDIT: Since you want to parse a string that contain some HTML, you won't be able to use my answer as-iis. Will your HTML string contain a whole HTML document? Some part? Valid HTML? Partial (broken) HTML?
Perhaps something like
document.getElementById("auth").innerHTML.replace(/<^[^>]+>/g, '')
might work. innerHTML is supported on all modern browsers. (You may omit the replace if you don't care about removing HTML bits from the inner content.)
If you have jQuery at your disposal, just do
$("#auth").text()
What I want to do (with javascript) is
basically extract out the 'John Doe'
from any tag with the ID of "auth".
You can't have the same id (auth) for more than one element. An id should be assigned once per element per page.
If, however, you assign a class of auth to elements, you can go about something like this assuming we are dealing with paragraph elements:
// find all paragraphs
var elms = document.getElementsByTagName('p');
for(var i = 0; i < elms.length; i++)
{
// find elements with class auth
if (elms[i].getAttribute('class') === 'auth') {
var el = elms[i];
// see if any paragraph contains the string
if (el.innerHTML.indexOf('John Doe') != -1) {
alert('Found ' + el.innerHTML);
}
}
}
Assuming you only have 1 auth per string, you might go with something like this:
var str = "This was written by <p id=\"auth\">John Doe</p> today!",
p = str.split('<p id="auth">'),
q = p[1].split('</p>'),
a = q[0];
alert(a);
Simple enough. Split your string on your paragraph, then split the second part on the paragraph close, and the first part of the result will be your value. Every time.
If the content of the tag contains only text, you could use this:
function getText (htmlStr, id) {
return new RegExp ("<[^>]+\\sid\\s*=\\s*([\"'])"
+ id
+ "\\1[^>]*>([^<]*)<"
).exec (htmlStr) [2];
}
var htmlStr = "This was written by <p id=\"auth\">John Doe</p> today!";
var id = "auth";
var text = getText (htmlStr, id);
alert (text === "John Doe");

Categories

Resources