I'm trying to print all the h3 of my website into a list within the console but its not working? I've even tried it on a random online site to check if it would work and it doesn't make a difference... The irony is its the same code i've used before to do it on my website but It's not working
Heres what im running in the console
for(i = 0; i < 300; i++) {console.log(document.getElementsByTagName("H3")
[i].innerHTML)};
Heres a sample of what my website html would be...
<h3>Hello</h3>
<h3>There</h3>
<h3>My</h3>
<h3>Fried</h3>
What Im trying to get to print to the console...
Hello
There
My
Friend
I've tried adjusting the upper limit of 300, I could do i.e document.getElementsByTagName["H3"].arrayLength or whatever and store that in a value as upper limit but thats besides the point. Its not working...
You are querying the DOM on each iteration instead of getting all elements, and then iterating them:
const elements = document.getElementsByTagName("H3")
for(i = 0; i < elements.length; i++) {console.log(elements[i].innerHTML)}
<h3>Hello</h3>
<h3>There</h3>
<h3>My</h3>
<h3>Fried</h3>
You can also use document.querySelectorAll() and convert the NodesList to an array using Array.from():
const elements = document.querySelectorAll('h3')
const arr = Array.from(elements, el => el.innerHTML)
console.log(arr.join(' '))
<h3>Hello</h3>
<h3>There</h3>
<h3>My</h3>
<h3>Fried</h3>
Related
I am trying to do some element manipulation on a Node.js server where I need to take a string of HTML, then replace some of the nodes with other node types. This was working fine when I was doing it with a DOM but as soon as I don't have a DOM it does not work.
In a very simple example, I want to do something like this... where I find all the div elements and replace with spans.
const html = '<html><div>hello</div><div>hello</div></html>';
const obj = $(html);
const filter = $(obj).find('div');
for (let j = filter.length; j >= 0; j--) {
$(filter[j]).replaceWith("<span>goodbye</span>");
}
console.log(obj);
I can't just do a find and replace on the string as I don't want all elements I am doing a filter based on various things before I do this.
It is not working saying that the node is not an element. Is there a way I can do this? I have also tried using JSDOM to do this but again, no luck.
I want the console here to show the HTML element with two spans rather than two divs, I have tried adding a jsfiddle for this however I am getting a different error on here too, if anyone can help it would be appreciated.
http://jsfiddle.net/vkn285a1/1/
** UPDATE **
From the answer below, I have updated but I am now getting my desired result, thank you.. I had to change to use SVG which is what I am actually parsing and it worked a treat
const html = "<svg><g><text>hello</text><text>hello</text></g></svg>";
const obj = $.parseHTML(html);
const filter = $(obj).find("text");
for (let j = filter.length; j >= 0; j--) {
$(filter[j]).replaceWith("<span>goodbye</span>");
}
Your issue is following:
const obj = $(html);
this obj is NULL.
You have to use parseHTML function to get object from string as following.
const html = '<html><div>hello</div><div>hello</div></html>';
const obj = $.parseHTML(html);
Then obj will be an array of divs in html tag of string.
After that, you can try anything for those objects that are not NULL.
I am currently building a Chrome extension which has to find specific pages in a website specifically the Log In / Sign In page, the Sign Up / Register page, the About page and the Contact Us page.
I am trying to achieve this by first getting the list of elements in the page (which I have already done). Now I need to check the innerHTML of the element such that it is a leaf node in the DOM and contains a part of the keyword, and I am trying to do this with a regex. I managed to build a regex which successfully returns what's in between a start or end tag of an element (i.e. the tag name along with its attributes), but not the innerHTML. Below is what I have done so far (with the example for the About page:
var list = document.body.getElementsByTagName("*");
var aboutElement = /^[^<.+>].*About.*[^(<.+>]$/i;
for (var i = 0; i <= list.length; i++) {
if ((aboutElement.test(list[i].innerHTML)) || (aboutElement.test(list[i].alt))) {
list[i].click();
}
}
Any idea what I should add to it such that it only matches leaf nodes (nodes which do not contain other nodes) and not what's in a start or end tag? I also think that with what I've done it's going to match everything in the innerHTML because of the .* part so I may need to change that as well. Any help would be greatly appreciated!
Thanks to two of the answers in the comments I managed to solve the problem. I used .textContent and changed the regex as shown below and it worked.
var list = document.body.getElementsByTagName("*");
var aboutElement = /^(.*?\s*(\bAbout\b)[^$]*)$/i;
for (var i = 0; i <= list.length; i++) {
if ((aboutElement.test(list[i].textContent)) || (aboutElement.test(list[i].alt))) {
list[i].click();
}
}
I have the following piece of code to generate an select list on the fly. The code works okay when the records retrieved are between 0-300 records. However when I try to work with records over this number, 671 records to be exact, the browsers(IE,FF,Chrome,Opera) hang and it seems the javascript is taking up a lot of resources and the browsers become slow after the select option is finally generated after a 5 minute wait....
I am looking for a way to make this more efficient and prevent such hangups as I will work with records upto 5000
$("#idea_selectrel").on("change",function(){
var attributeid = $("option:selected",this).val();
$.post("/OCSRM/PopulateHTMLTablesServlet.do",{"attributeid":attributeid,"table":'idearelations'},function(data){
if(!$.isEmptyObject(data))
{
$("#idea_selectrelvalue option:not(:first)").remove();
var html='';
var len = data.length;
for(var i=0,len = data.length; i<len; i++ )
{
var relvalue = [data[i].relvalue];
var description = [data[i].description];
html +='<option value="'+relvalue+'">'+relvalue+' - '+description+'</option>';
$("#idea_selectrelvalue").append(html).show();
}
}
else
{
alert('No data found.');
}
},'json');
//alert(attributeid);
});
Your code is building up a long string of HTML containing the options. It's also appending the string over and over again to the <select> element.
Move the .append() to after the loop:
for(var i=0,len = data.length; i<len; i++ )
{
var relvalue = [data[i].relvalue];
var description = [data[i].description];
html +='<option value="'+relvalue+'">'+relvalue+' - '+description+'</option>';
}
$("#idea_selectrelvalue").append(html).show();
Not being able to test the code but from what I can tell you're not clearing the html variable inside the loop, currently, the html will be added recursively for every iteration, and every iteration is updating the DOM, which will get pretty large, fast.
I'm not sure if this is by design, but if it's not, try moving the append outside of the loop.
var html='';
var len = data.length;
for(var i=0,len = data.length; i<len; i++ )
{
var relvalue = [data[i].relvalue];
var description = [data[i].description];
html +='<option value="'+relvalue+'">'+relvalue+' - '+description+'</option>';
}
$("#idea_selectrelvalue").append(html).show();
That is a lot of DOM elements that will be slow to load even if created without JS. Assuming you don't have a way to pre-generate the select on the server and send it down, you could try not appending the value in the loop. You could build out a string of option values and then, after the string is created, set the html of the select to the generated string. The DOM manipulation in the loop could be a culprit at that level. However, it is important to note that large or deeply nested DOM elements can be a performance concern regardless.
I'm currently trying to populate a selection list from an external javascript array. It works but I'm trying to populate only certain values using an ID column, which is failing. I'm using check-boxes and an 'If' statement to see which box is checked, and populate the appropriate array values based on this selection. I'm then using another 'If' within a for loop to match the ID value in the array, and add the matching values to the selection. However, it seems that it is completely disregarding the condition and reading the entire array in to selection list. It could be an obvious mistake with my code as I am only a novice.
function populateIslandList () {
var form = document.forms["island_form"];
var islands = form.islands;
if (islands[0].checked){alert("works");
for (i = 0; i < pislands.length; i++)
if (pislands[i][1] = 1){
document.forms["location"].islands.options[i] =
new Option(pislands[i][0], i)}};
if (islands[1].checked){alert("works");
for (i = 0; i < pislands.length; i++)
if (pislands[i][1] = 2){
document.forms["location"].islands.options[i] =
new Option(pislands[i][0], i)}};
}
Your first mistake is here:
var islands = document.getElementById("island_form");
document.getElementById() returns a single DOM element, not a list of objects. So, thus islands[0] and islands[1] are going to be undefined and islands[0].checked will make a script error.
You can only have one DOM element with a given id. You can have multiple elements with a class name so maybe you should switch to using class names and be using document.getElementsByClassName("something")
FYI, you should be looking in the browser error console or debug console to see script errors as this should have given you an indication of some trouble here.
Please bear with me on this question; I have only recently started coding in Javascript and for this reason I would like a strong foundation before breaking into jQuery.
I have the following Javascript code:
var app = {
text: document.getElementById('text'),
output: document.getElementById('output'),
createDiv: document.createElement('div')
};
function postData(){
app.output[0].appendChild(app.createDiv.firstChild);
app.createDiv.classname = 'text';
document.getElementsByClassName('username').innerHTML += app.text.value;
}
onClick I want the value of app.text to print (using innerHTML) ABOVE the output div. Any ideas or questions? Sorry if I am being vague or not making sense, I have been staring at this for 4 hours now and am probably just burned out!
You'll have to create a text node and insert it before each element in the NodeList returned by document.getElementsByClassName:
var node = document.createTextNode(app.text.value);
var elements = document.getElementsByClassName('username');
for (var i = 0; i < elements.length; i++) {
var elem = elements[i];
elem.parentNode.insertBefore(node.cloneNode(), elem)
}
And just to tempt you with the jQuery version:
$('.username').before(app.text.value);
I'm not sure what you're asking, but I see the following problems with your code:
app.output[0]: there should be no [0], app.output is already an element (you got it by id). So use app.output.appendChild(app.createDiv.firstChild);. Still, this makes no sense; as Barmar said, you just created that div, so it doesn't have any children at that point.
app.createDiv.classname: should be className
document.getElementsByClassName('username').innerHTML: this returns multiple elements, maybe you want document.getElementsByClassName('username')[0].innerHTML?