I have to retrieve hier2 object in jquery from following HTML code in ASPX page
<div>
<hier2:hierarchy >
<hier:x1></hier:x1>
<hier2:hierarchy >
</div>
I trier document.all.hier2 in IE 11 and its not working
what is the best approach to do this.
simply put:
document.getElementsByTagName("hier2:hierarchy");
returns a node list you can loop over containing all the hier2:hierarchy nodes.
More elaborate:
Those elements (or nodes) are part of the Document Object Model (DOM). In the past IE (and others) supported document.all. It's now deprecated. How to traverse the DOM. The DOM is a tree that contains a root and its children, grandchildren, etc.
basics:
document: This is the master object. The root of the page. All other elements are a descendant of this root.
document.documentElement: representing the HTML-element of the page.
Traversal:
document.getElementById: allows you to select a single element based upon its ID-attribute.
document.getElementsByTagName: allows you to select multiple nodes based upon the node name.
document.getElementsByClassName: allows you to select multiple nodes based upon the node's class.
document.querySelector: select a single node using css-selectors
document.querySelectorAll: same as the above, only for selecting multiple elements.
children or childNodes: a subtle difference, the first selects content nodes, while the latter selects all the nodes that are direct children (in the form of a node list) of an element.
parentNode or parentElement: select the parent element of the current element.
previousSibling or nextSibling: select the previous or next element.
Many more options here: https://developer.mozilla.org/en-US/docs/Web/API/Element
Some examples:
plain:
var elements = document.getElementsByTagName("hier2:hierarchy");
for (var i = 0; i < elements.length; i++)
{
document.querySelector("#display").innerHTML += elements[i].nodeName; //select the display div using css selector #display
}
<div>
<hier2:hierarchy>
<hier:x1></hier:x1>
</hier2:hierarchy>
</div>
<div id="display"></div>
In jQuery
$("hier2\\:hierarchy").each(function() {
$("#display").html(this.nodeName);
});
//$("hier2\\:hierarchy") is used to select the elements, mind the \\ to escape!
//each is used to traverse all the elements.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<hier2:hierarchy>
<hier:x1></hier:x1>
</hier2:hierarchy>
</div>
<div id="display"></div>
Special reminder here:
In using hier2:hierarchy will fail. You need to escape the : with \\: to
$("hier2\\:hierarchy")
Related
Suppose that I want to add a newly created paragraph (using document.createElement("p")) into an existing div (with class name "container") in one of my html files. Is there a way to do this by calling some methods?
Since there's a getElementById() method, I figured I would use a getElementByClassName() method too, but that doesn't exist; what exists is getElementsByClassName() instead. One way I can get around this is to just change my div to have an id rather than a class name, and use the getElementById() to add the paragraph into the div, but I wanted to know if there was some method that I could call that would help me retrieve a class element (rather than the elements within the class itself).
I've tried looking for this online, but what I've found are answers to "how to add class names to elements" instead, which is not what I want to know.
For one element, this will chose first in DOM order:
var p = document.createElement("p");
p.innerHTML = "p element";
document.querySelector(".container").appendChild(p);
<div class="container">container</div>
For all elements with chosen class:
[...document.querySelectorAll('.container')].forEach(el => {
var p = document.createElement("p");
p.innerHTML = "p element";
el.appendChild(p);
})
<div class="container">container</div>
<div class="container">container2</div>
HTML DOM elements' IDs have to be unique within a document - and so asking for an element by Id will return you just one element (or null if there isn't a matching element).
However a class name can be applied to multiple elements, so you would expect to get zero one or more elements when searching by class, hence the getElementsByClassName returns a collection.
So if you have a list of elements with the class name container, and you know your document (hopefully) only contains one element with that name, you can pick the first element returned by the getElementsByClassName - e.g. getElementsByClassName('container')[0]
Note - getElementsByClassName returns all elements to which the class has been directly applied, for the children of the element on which it is being called. I've interpreted your query as relating to the whole document in the context of your original question.
I would like to scan a page for all DOM elements of type HTMLButtonElement so that I can get their exact position. I would then use this position to place another button on top.
I've been scanning through all DOM elements by the following code snippet:
var all = document.getElementsByTagName("*");
var temp = document.createElement('button');
for (var i = 0, max = all.length; i < max; i++) {
//Loop through all[i] to see if it is an object of type HTMLButtonElement
}
As already pointed out in comments, you can simply use:
document.getElementsByTagName("button");
The Element.getElementsByTagName() method 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. Consequently, there is no need to call several times Element.getElementsByTagName() with the same element and arguments.
– MDN's article on Element.getElementsByTagName()
Be aware though that HTML also has the <input type="button" /> element as well. If you want to pull these as well, you'd be better off using document.querySelectorAll() which allows us to specify multiple comma-delimited selectors:
document.querySelectorAll('button, input[type=button]');
Furthermore, you can also define button behaviour on elements by setting the ARIA attribute role to "button":
<div role="button">...</div>
If you also want to pull these, you can also include [role=button] in the above querySelectorAll call.
I have an interface that switches between displaying different div elements. When it switches which element it displays, I need to access a specific child node of that div element, with each div element having their children arranged differently.
The childNodes and children property both return an object that can only select children with item(index) which is annoying to use as the relevant child element's index is different in each div. For Protractor, I used the webmanager.by(selector) which was able to search with other parameters than index. Is there something similar I can use to select the child node with data-relevant="true". I am also unsure if that attribute is the best way to specify in the HTML which child node is relevant.
This is an Angular application if that helps.
If you want to select the child node with data-relevant="true" from some parent element, you could use the selector method
element.querySelector()
That would return the first matching element...
in your specific case it could be something like
parent-element.querySelector( "[data-relevant='true']" );
or if you want to select all paragraphs p with the data-relevant attribute value true within the parent div: parentDiv.querySelectorAll( "p[data-relevant='true']" );
You can find some examples on
http://www.w3.org/TR/selectors-api/#processing-selectors
An alternative would be to use a special class to identify which child node is relevant...
you could get this element/or many elements with getElementsByClassName(someClassName)
Code Sample With .querySelectorAll() method:
<script type="text/javascript">
window.addEventListener("load", init, false);
function init(){
var parentDiv = document.getElementById("divWithChildren");
var relevantChildren = parentDiv.querySelectorAll( "[data-relevant='true']" );
alert (relevantChildren[2].id); // this will give the id of the 3rd child element with data-relevant='true'
}
</script>
I want to be able to refer to any element within an HTML DOM and also know what order the elements appear in. I'm hoping elements in the DOM get indexed somewhere from 0 to <number-of-elements-minus-1> so that I can identify specific elements and, separately, list those elements in the order they appear within the HTML.
For example, in this HTML, the elements would be numbered from 0 for the html element, to 9 for the second p element:
<html lang="en-US">
<head>
<title>Element 2. Page title</title>
</head>
<body>
<h1 id="mainHead">Element 4. How to uniquely identify/order DOM elements</h1>
<div id="boxedContent">
<p class="smallText">Element 6. I want to be able to <span class="stress">7. uniquely</span> identify each element and <i>8. also</i> determine the order in which elements appear, reading from top to bottom through the HTML.</p>
</div>
<p>Element 9</p>
</body>
</html>
I want a JavaScript/jQuery way of specifying, for example, the title element, first p element and the span. The HTML pages I'll be working with aren't mine, but if there's a whole-DOM element index that I can access I could get to these 3 elements using those index refs - i.e.
title: 2
first p: 6
span: 7
The index numbers would allow me to list the elements in order.
Is this possible? How do I do it?
A better option would be to use node.compareDocumentPosition(node) (no jQuery needed)
see: https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
Given a list of nodes you can sort them this way:
nodes.sort((a, b) =>
a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
);
You could do something like this:
var elems = document.getElementsByTagName('*');
This will create an array-like object of all DOM element.
Then, there are many ways you can get the index of a specific element in that array-like object.
You could do this:
var indexOfTitle = elems.indexOf(document.getElementsByTagName('TITLE'));
Or, you can create a for loop which loops through all the elements in the elems variable, and uses a property like tagName to find it, etc.
Is there a way in jQuery to, given an element and a selector, select the last match of that selector before that element from an in-order traversal of the DOM tree?
For example, given the DOM tree:
<html>
<body>
<div class="a" id="div0" />
<div>
<div class="a" id="div1"/>
</div>
<div class="b" id="div2"/>
<div id="element"/>
<div class="a" id="div3"/>
<div class="b" id="div4"/>
</body>
</html>
Using the selector .a and element #element, you'd get #div1, and using the selector .b and the element #element, you'd get #div2.
The use case is writing a GreaseMonkey script to work across different versions of Firefox with some slightly mangled HTML. I've got an element I can find consistently in all versions, but another element I want to find is either a previous sibling of an ancestor of the element or a descendent of a previous sibling of an ancestor of the element (depending on the version).
All I can really rely on is that it is the last match of the selector that occurs before the element I have when doing an in-order traversal of the DOM tree.
This should do it, using your first example:
var $collection = $(".a, #element");
var eleIndex = $collection.index($("#element"));
var prevEl = $collection.eq(eleIndex - 1);
alert(prevEl.attr("id"));
http://jsfiddle.net/WdsGa/
Sortof. This will work for sibling elements just fine:
$("div.a:first").nextUntil("#element").last();
however, your nested div.a will not work with that snippet, I'm not sure of an efficient way to solve that. It selects the first element matched by div.a, then all siblings after it until it finds an element that matches #element, and then gets the last of those selected elements. But, again, it only works with siblings.
This should do it
var last = $(".a, #element").eq($(".a, #element").length-1);