How to get the first <ul> element from a document in JavaScript? - javascript

First of all, sorry If it isn't clear in the beginning, but let me explain: I want to get the div with a class and the first <ul> from a document (I'm using blogger). I already have a JS that picks up the first image and creates a thumbnail like this:
//<![CDATA[
function bp_thumbnail_resize(image_url,post_title)
{
var show_default_thumbnail=true;
if(show_default_thumbnail == true && image_url == "") image_url= default_thumbnail;
image_tag='<img src="'+image_url.replace('/s72-c/','/')+'" class="postimg" alt="'+post_title+'"/>';
if(image_url!="") return image_tag; else return "";
}
//]]>
and below,
document.write(bp_thumbnail_resize("<data:post.thumbnailUrl/>","<data:post.title/>"));
Now the structure that I want (because I cannot display the full post in the homepage due to the size of other elements):
<div class="Title1">
<h3>Title</h3>
</div>
<ul>
<li>DESCRIPTION1</li>
<li>DESCRIPTION2</li>
</ul>

There are number of ways in which you can do that. Few are
var firstUL = document.getElementsByTagName('ul')[0];
var firstUL = document.querySelector("ul");
If you also have Jquery in use
$( "ul" ).first();
or
$("ul:first")

How to get the first element from a document in JavaScript?
You could try something as simple as:
var firstUlElement = document.getElementsByTagName('ul')[0];
The getElementsByTageName method of document
returns a live HTMLCollection of elements with the given tag name. The
subtree underneath the specified element is searched, excluding the
element itself. The returned list is live, meaning that it updates
itself with the DOM tree automatically.
as it is stated here.

var firstUl = document.querySelector('ul');

Related

Inserting div into existing div with class only

I'm trying to create a new div in Javascript with two spans in it, each containing a string of text. They are then meant to be inserted before div.two in div.inner.
The div I'm trying to insert it into only has a class and I cannot target it by any ID, unfortunately.
I have also created a codepen here: https://codepen.io/lisaschumann/pen/BXqJKY
Any help is massively appreciated!
HTML
<html>
<div class="inner">
<div class="one"></div>
<div class="two"></div>
</div>
</html>
JS
window.onload=function(){
var infobox = document.createElement("div");
infobox.classList.add('infobox');
var spanOne = document.createElement("div");
var spanOneText = document.createTextNode('Important text 1');
var spanTwo = document.createElement("div");
var spanTwoText = document.createTextNode('Important text 2');
spanOne.appendChild(spanOneText);
spanTwo.appendChild(spanTwoText);
infobox.appendChild(spanOne);
infobox.appendChild(spanTwo);
var targetDiv = document.getElementsByClassName("inner");
targetDiv.insertBefore(infobox, targetDiv.childNodes[1]);
}
Errors:
Cannot read property '1' of undefined
at window.onload
The main issue is that getElementsByClassName returns a live collection of nodes rather than one node and so you would need to access the correct node in that list similar to an array: targetDiv[0], perhaps.
The easier method is to use querySelector to grab the element you want using its class, for example:
var parent = document.querySelector(".inner");
var two = document.querySelector(".two");
parent.insertBefore(infobox, two);
But! there's even a shortcut method you can use here that allows you to add an HTML string direct to the DOM which might save you a bit of time, and some code.
// Create the HTML
const html = `
<div>
<span>Text alpha</span>
<span>Text beta</span>
</div>`;
// Grab the element containing your "two" class
const two = document.querySelector('.inner .two');
// Using insertAdjacentHTML to add the HTML before the two element
two.insertAdjacentHTML('beforebegin', html);
<div class="inner">Inner
<div class="one">one</div>
<div class="two">two</div>
</div>
insertAdjacentHTML
This doesn't work because of these lines
var targetDiv = document.getElementsByClassName("inner");
targetDiv.insertBefore(infobox, targetDiv.childNodes[1]);
document.getElementsByClassName returns a NodeList. targetDiv.childNodes is undefined, because childNodes doesn't exist on a NodeList.
You need to either use a list operation like Array.prototype.forEach, change getElementsByClassName to getElementByClassName (note the s) or access the first node in the node list using the array indexer syntax.
I assume you meant to do something like this:
var targetDiv = document.getElementByClassName('inner')
targetDiv.insertBefore(infobox, targetDiv.childNodes[1])
This will insert a node in between the first and second child of the first DOM node with the class inner.
Try this out , targetDiv is an array by default due to the getElementsByClassName method , even though it has a single element.Hence you need to specify the index i.e. 0 ( as it's the first element of the array)
var targetDiv = document.getElementsByClassName("inner")[0]; targetDiv.insertBefore(infobox, targetDiv.children[1]); }
Using JQuery
$(document).ready(function(){
$(`<div>Important text 1<span></span>Important text 2<span></span></div>`).insertBefore( ".inner .two" );
)
I would encourage you to use JQuery and then shift to vanilla javascript later on. You can do simple tasks like this in just few lines of code and it is also easily debuggable because of that

Getting Element

I am new to this and I have this element and I have to somehow "get it". There are few more element above it, there's just an element I need:
<a class="btn_green" href="javascript:void(0)" onclick="ShowPopup( 440, "some_text", "some_text" ); return false;">
<span>Some text</span>
</a>
Thanks for help!
$('a.btn_green') will return an array of you could use the Array index to access the proper value if the index is known and does not change
var $a = $('a.btn_green');
var el = $a[2];
You can use getElementsByClassName.
document.getElementsByClassName('btn_green')
This will return an array of all the elements that match. If you have only one element you can access it at index 0.
document.getElementsByClassName('btn_green')[0]
If you added an ID to the element,and then use getElementById
<a id="YOUR_ID_HERE" class="btn_green" href="javascript:void(0)" onclick="ShowPopup( 440, "some_text", "some_text" ); return false;">
document.getElementById('YOUR_ID_HERE')
You can do something like this in standard JS you would do something similar to this:
var button = document.getElementsByClassName('btn_green');
If you're just looking to get that specific element I would suggest adding an id
<a class="btn_green" id="myButton" href="javascript:void(0)" onclick="ShowPopup( 440, "some_text", "some_text" ); return false;">
<span>Some text</span>
</a>
And here is the JS
var button = document.getElementById('myButton');
Details are commented in the Snippet. The anchor in OP's code is atrocious so I made the markup simpler, but the code provided here will work an any anchor(s) under certain conditions described below.
SNIPPET
/* Plain JavaScript */
/* If there is only one element that has the class="btn_green" */
// By className
var btnByClassName = document.querySelector(".btn_green");
/* If it is the only link (anchor)
*/
// By tagName
var btnByTagName = document.querySelector("a");
/* If theres more than one element with the class="btn_green" */
// By className
var btnsByClassName1 = document.querySelectorAll(".btn_green");
// or
var btnsByClassName2 = document.getElementsByClassName("btn_green");
/* The two methods above will collect all elements with the
specified className. The group of elements collected is known
as a HTML Collection or NodeList. If you need to specifically
target one of them out of a group, say like the 2nd one, you have
to count from 0. Ex. the second element in a NodeList would be 1.
*/
/* Continuing from the previous example above, we can single out a
single element by placing the 0 count number of that element:
*/
var btnsByClassNameA = document.querySelectorAll(".btn_green")[1];
//or
var btnsByClassNameB = document.getElementsByClassName("btn_green")[1];
/* A different type of NodeList/HTML Collection can be had by
targeting the tagName, this example we are targeting the first
anchor:
*/
var btnsByTagName1 = document.querySelectorAll("a")[0];
//or
var btnsByTagName2 = document.getElementsByTagName("a")[0];
/* Note: Although these methods are able to get a group of
elements, they are able to get an element if it is the only
one of it's kind by using [0].
*/
/* jQuery */
/* jQuery makes it easier and does most of the thinking for us.
You must make sure that your page has the jQuery library loaded.
Look at the HTML section below, you'll see a <script... tag. You
must have that tag inside the <head></head> or before the </body>
otherwise you code will not function.
*/
/* Note the variable has a $ prefix. This is optional and it's
purpose is to show other developers that the variable represents a
jQuery Object.
*/
// By className
var $btnsByClassName = $(".btn_green");
// By tagName
var $btnsByTagName = $("a");
/* This part is not part of the question, it is just to show that
these references are working */
$btnsByTagName.on('click', aTonOfStuff);
function aTonOfStuff() {
btnByClassName.style.backgroundColor = "black";
btnByTagName.style.color = "lime";
for (let i = 0; i < btnsByClassName1.length; i++) {
btnsByClassName1[i].style.fontSize = "40px";
btnsByClassName2[i].style.fontVariant = "small-caps";
}
btnsByClassNameA.style.backgroundColor = "#0E0";
btnsByClassNameB.style.color = "#000";
btnsByTagName1.style.lineHeight = "2";
btnsByTagName2.style.textDecoration = "overline";
$btnsByClassName.fadeOut("slow");
$btnsByTagName.fadeIn("slow");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Click any link.</p>
<a class="btn_green" href="#/">First Green Button Anchor Link</a>
<a class="btn_green" href="#/">Second Green Button Ancor Link</a>
Something like $('a.btn_green') would "get" that <a> element but it is not guaranteed to get it uniquely. You may need to use something like the :nth-child pseudo-selector to do this if you cannot modify the source. Without more context it is impossible to say what a selector would be that would uniquely retrieve either the <a> or the <span> element.
Here is a jQuery tutorial and here is a CSS selector reference, just in case you need them.
Edit
One weird thing happening on the page is $ no longer seems to be bound to jQuery. They must be loading something which uses $ after jQuery which is causing selectors like $('a.btn_green') to return null. You can replace $ with jQuery instead.
I tried the using jQuery('.btn_green_white_innerfade.btn_medium') to find the element, but it looks like there are three elements on the page which share that selector. So I looked further up in the source and found that the button I think you want is within a div with the id market_buyorder_info. This led me to the following code to get the element uniquely:
jQuery('#market_buyorder_info').find('.btn_green_white_innerfade.btn_medium')
And this code to trigger a click in the console:
jQuery('#market_buyorder_info').find('.btn_green_white_innerfade.btn_medium').click()

Split Javascript String into an array of strings by looking for keyword

Working on a personal project that parses through an HTML document inserted into a textarea and produces a new HTML document with added modifications.
What my issue is, I want split certain divs with class="dog" into an array with each element in the array being divs of class of dog.
HTML:
<div class="dog">
<div class="mouth"></div>
<dig class="legs"></dig>
</div>
<div class="dog">
<div class="mouth"></div>
<dig class="legs"></dig>
</div>
JS Idea:
dogs[x] = intext.slice(intext.indexOf('<div class="dog"'), /*next instance of dog*/);
Array would look like:
dog[0] = <div class="dog">
<div class="mouth"></div>
<dig class="legs"></dig>
</div>
I tried using .indexOf('<div class="dog"') to try and create an array of indexes so I can use it to split the main string but no luck.
Any ideas of how I can accomplish this?
There exists a feature called query selectors. With these you can select all elements with a certain class, or all elements of a certain tag, ...
This will suit your specific need: querySelectorAll
the regular querySelector() will only select the first element which is why you need to use querySelectorAll(). It will give you a list of elements with which you can continue working.
Example:
var dogDivs = document.querySelectorAll(".dog");
EDIT:
As you have just now mentioned it is text from a textarea, as suggested by an other answer you could first load it into your DOM structure. Preferrably in a hidden element so that the user is unaware of it.
First you need to load the content onto the DOM:
document.createElement("div").innerHtml(intext);
Then you can find the dog elements as the other answers have suggested:
var elements = document.getElementsByClassName('dog');
Be careful when loading user inputted data into the DOM, this can open doors to being hacked.
You should never parse html as a string. Use a DOMParser to convert it to a document and then you can use all the standard methods
var parser = new DOMParser();
var doc = parser.parseFromString(stringContainingHTMLSource, "Text Area Content");
divs = doc.getElementsBYTagName("div");
Then you can use the built in Document interface. For your specific case, here are a few methods you can use.
get an array of all divs:
document.getElementsByTagName("div");
get an array of all divs with a specific class:
document.getElementsByClassName("dog");
get an array of all divs with a specific id:
document.getElementById("id");
The full list of very useful methods can be found on MDN.
var elements = document.getElementsByClassName('dog');
var arr = [].slice.call(elements);
arr is the array you want to have. elements is HTMLCollection, and doesn't have array prototype methods.
You can try getting all elements with class dog:
var dogs = document.getElementsByClassName("dog");
But this will return all elements with class dog. Then you can try this snippet:
function splitByClass(tag, cl) {
var els = document.getElementsByClassName(cl);
var res = [];
for (i = 0; i < els.length; i++) {
if (els[i].tagName.toLowerCase() == tag.toLowerCase()) {
res.push(els[i]);
}
}
return res;
}
console.log(splitByClass("div","dog"));
If you want to parse it as text without converting it into a DOM object which could potentially error if there is any mistakes with the users input formatting. Try a solution like the one I suggested here for searching XML code:
https://stackoverflow.com/a/34299948/1011603
This will let you search for a start tag, eg and an end tag, you just need to tweak the .substring sizing for the size of your search start/end tag eg the div.
For the thing you are doing you don't use the slice tool. This would be used for a String and you don't use the index of because that's just searching a string for a specific part.
What you do want to use is the
document.querySelectorAll(".example");
You will put the class dog where the .example is as the same format.
This command will return an array of all of the possible divs
If you need any more help, go to this link
http://www.w3schools.com/jsref/met_document_queryselectorall.asp

javascript elements/tags array DOM node access

what's the different between using:
// assuming using elements/tags 'span' creates an array and want to access its first node
1) var arrayAccess = document.getElementsByTagName('elementName')[0]; // also tried property items()
vs
// assuming I assign an id value to the first span element/tag
// specifically calling a node by using it's id value
2) var idAccess = document.getElementById('idValue');
then if I want to change the text node....when using example 1) it will not work, for example:
arrayAccess.firstChild.nodeValue = 'some text';
or
arrayAccess.innerText/innerHTML/textContent = 'some text';
If I "access" the node through its id value then it seems to work fine....
Why is it that when using array it does not work? I'm new to javascript and the book I'm reading does not provide an answer.
Both are working,
In your first case you need to pass the tag name instead of the element name. Then only it will work.
There might be a case that you trying to set input/form elements using innerHTML. At that moment you need to use .value instead of innerHTML.
InnerHTML should be used for div, span, td and similar elements.
So your html markup example:
<div class="test">test</div>
<div class="test">test1</div>
<span id="test">test2</span>
<button id="abc" onclick="renderEle();">Change Text</button>
Your JS code:
function renderEle() {
var arrayAccess = document.getElementsByTagName('div')[0];
arrayAccess.innerHTML = "changed Text";
var idEle = document.getElementById('test');
idEle.innerHTML = "changed this one as well";
}
Working Fiddle
When you use document.getElementsByTagName('p'), the browser traverses the rendered DOM tree and returns a node list (array) of all elements that have the matching tag.
When you use document.getElementById('something'), the browser traverses the rendered DOM tree and returns a single node matching the ID if it exists (since html ID's are unique).
There are many differences when to use which, but one main factor will be speed (getElementById is much faster since you're only searching for 1 item).
To address your other question, you already have specified that you want the first element in the returned nodeList (index [0]) in your function call:
var arrayAccess = document.getElementsByTagName('elementName')[0];
Therefore, arrayAccess is already set to the first element in the returned query. You should be able to access the text by the following. The same code should work if you used document.getElementById to get the DOM element:
console.log(arrayAccess.textContent);
Here's a fiddle with an example:
http://jsfiddle.net/qoe30w2w/
Hope this helps!

How to access HTML element without ID?

For instance in the snippet below - how do I access the h1 element knowing the ID of parent element (header-inner div)?
<div id='header-inner'>
<div class='titlewrapper'>
<h1 class='title'>
Some text I want to change
</h1>
</div>
</div>
Thanks!
function findFirstDescendant(parent, tagname)
{
parent = document.getElementById(parent);
var descendants = parent.getElementsByTagName(tagname);
if ( descendants.length )
return descendants[0];
return null;
}
var header = findFirstDescendant("header-inner", "h1");
Finds the element with the given ID, queries for descendants with a given tag name, returns the first one. You could also loop on descendants to filter by other criteria; if you start heading in that direction, i recommend you check out a pre-built library such as jQuery (will save you a good deal of time writing this stuff, it gets somewhat tricky).
If you were to use jQuery as mentioned by some posters, you can get access to the element very easily like so (though technically this would return a collection of matching elements if there were more than one H1 descendant):
var element = $('#header-inner h1');
Using a library like JQuery makes things like this trivial compared to the normal ways as mentioned in other posts. Then once you have a reference to it in a jQuery object, you have even more functions available to easily manipulate its content and appearance.
If you are sure that there is only one H1 element in your div:
var parent = document.getElementById('header-inner');
var element = parent.GetElementsByTagName('h1')[0];
Going through descendants,as Shog9 showed, is a good way too.
It's been a few years since this question was asked and answered. In modern DOM, you could use querySelector:
document.querySelector('#header-inner h1').textContent = 'Different text';
<div id='header-inner'>
<div class='titlewrapper'>
<h1 class='title'>
Some text I want to change
</h1>
</div>
</div>
The simplest way of doing it with your current markup is:
document.getElementById('header-inner').getElementsByTagName('h1')[0].innerHTML = 'new text';
This assumes your H1 tag is always the first one within the 'header-inner' element.
To get the children nodes, use obj.childNodes, that returns a collection object.
To get the first child, use list[0], that returns a node.
So the complete code should be:
var div = document.getElementById('header-inner');
var divTitleWrapper = div.childNodes[0];
var h1 = divTitleWrapper.childNodes[0];
If you want to iterate over all the children, comparing if they are of class “title”, you can iterate using a for loop and the className attribute.
The code should be:
var h1 = null;
var nodeList = divTitleWrapper.childNodes;
for (i =0;i < nodeList.length;i++){
var node = nodeList[i];
if(node.className == 'title' && node.tagName == 'H1'){
h1 = node;
}
}
Here I get the H1 elements value in a div where the H1 element which has CSS class="myheader":
var nodes = document.getElementById("mydiv")
.getElementsByTagName("H1");
for(i=0;i<nodes.length;i++)
{
if(nodes.item(i).getAttribute("class") == "myheader")
alert(nodes.item(i).innerHTML);
}
Here is the markup:
<div id="mydiv">
<h1 class="myheader">Hello</h1>
</div>
I would also recommend to use jQuery if you need a heavy parsing for your DOM.

Categories

Resources