I have come across this bit of jQuery and I am failing to understand what the xPath (?) means in this context:
var all_line_height = $(this).find("*[style*='line-height']");
I haven't seen this before, is it looking for an element that contains line-height in its style attribute?
I did a small test and it doesn't pick up on it.
That's not XPath. It's a selector, which selects any element whose style attribute contains line-height from the currently selected element (this).
$(this) // selects the current element
.find(...) // Select all elements which match the selector:
*[style*='line-height'] // Any element (*),
// whose style attribute ([style])
// contains "line-height" (*='line-height')
It could be implemented as follows:
// HTML:
// <div id="test">
// <a style="line-height:10px;color:red;">...
$("#test").click(function(){
// this points to <div id="test">
var all_line_height = $(this).find("*[style*='line-height']");
alert(all_line_height.length); //Alerts 1
})
Related
I need to be able to select and modify an element in an HTML document. The usual way to find an element using jQuery is by using a selector that selects by attribute, id, class or element type.
However in my case I have the element's HTML DOM and I want to find the element on my document that matches this DOM.
Important :
I know I can use a class selector or ID selector etc.. but sometimes the HTMLs I get don't have a class or an ID or an attribute to select with, So I need to be able to select from the element's HTML.
For example here is the element I need to find :
<span class='hello' data='na'>Element</span>
I tried to use jQuery's Find() but it does not work, here is the jsfiddle of the trial : https://jsfiddle.net/ndn9jtbj/
Trial :
el = jQuery("<span class='hello' data='na'>Element</span>");
jQuery("body").find(el).html("modified element");
The following code does not make any change on the element that is present in my HTML and that corresponds to the DOM I have supplied.
Is there any way to get the desired result either using native Javascript or jQuery?
You could filter it by outerHTML property if you are sure how browser had parsed it:
var $el = jQuery("body *").filter(function(){
return this.outerHTML === '<span class="hello" data="na">Element</span>';
});
$el.html("modified element");
el = jQuery('<i class="fa fa-camera"></i>');
This does not say "find the element that looks like <i class="fa fa-camera"></i>". It means "create a new i element with the two classes fa and fa-camera. It's the signature for creating new elements on the fly.
jQuery selectors look like CSS, not like HTML. To find the i element with those two classes, you need a selector like i.fa.fa-camera.
Furthermore $("document") looks for an HTML element called document. This does not exist. To select the actual document, you need $(document). You could do this:
$(document).find('i.fa.fa-camera').html("modified html")
or, more simply, you could do this:
$('i.fa.fa-camera').html('modified html');
You indicate in a comment to your question that you need to find an element based on a string of HTML that you receive. This is, to put it mildly, difficult, because, essentially, HTML ceases to exist once a browser has parsed it. It gets turned into a DOM structure. It can't just be a string search.
The best you can do is something like this:
var searchEl = jQuery('<i class="fa fa-camera"></i>');
var tagName = searchEl.prop('tagName');
var classes = [].slice.apply(searchEl.prop('classList'));
$(tagName + "." + classes.join('.')).html('modified html');
Note that this will only use the tag name and class names to find the element. If you also want IDs or something else, you'd need to add that along the same lines.
You should use Javascript getting the elements by something like
document.getElementById...
document.getElementsByClassName...
document.getElementsByTagName...
Javascript is returning the elements with the Id, Class or Tag Name you chose.
You can get en element with document.querySelector('.fa-camera')
with querySelector you can select IDs and Classes
You can simply refer to it by its class names.
$('.fa.fa-camera').html("modified html");
Similar to this answer https://stackoverflow.com/a/1041352/409556
Here is a full example:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$('.fa.fa-camera').html("modified html");
});
</script>
</head>
<body>
<i class="fa fa-camera"><h1>Some HTML</h1></i>
</body>
</html>`
The one thing that you could use is to check attributes (class and id goes here too in some way) that element have, and the build jQuery selector or DOM querySelector to find the element you need. The hardest part would be to find element based on innerHTML property - "Element" text inside it, for this one you'll probably have to grab all similar element and then search through them.
<span class='hello' data='na'>Element</span>
jQuery('body').find('span.hello[data=\'na\']').html('modified element')
Take notice of 'span' - that's tag selector, '.hello' - class, '[data="na"]' data attribute with name of data.
Jsfiddle link here that extends your example;
I am writing a small library where I am in need of selecting a relative element to the targeted element through querySelector method.
For example:
HTML
<div class="target"></div>
<div class="relative"></div>
<!-- querySelector will select only this .target element -->
<div class="target"></div>
<div class="relative"></div>
<div class="target"></div>
<div class="relative"></div>
JavaScript
var target = document.querySelectorAll('.target')[1];
// Something like this which doesn't work actually
var relativeElement = target.querySelector('this + .relative');
In the above example, I am trying to select the .relative class element relative only to the .target element whose value is stored in target variable. No styles should apply to the other .relative class elements.
PS: the selectors can vary. So, I can't use JavaScript's predefined methods like previousElementSibling or nextElementSibling.
I don't need solution in jQuery or other JavaScript libraries.
Well it should be ideally:
var relativeElement = target.querySelector('.relative');
But this will actually try to select something inside the target element.
therefore this would only work if your html structure is something like:
<div class="target">
<div class="relative"></div>
</div>
Your best bet would probably in this case be to use nextElementSibling which I understand is difficult for you to use.
You cannot.
If you insist on using the querySelector of the subject element, the answers is there is no way.
The spec and MDN both says clearly that Element.querySelector must return "a descendant of the element on which it is invoked", and the object element you want does not meet this limitation.
You must go up and use other elements, e.g. document.querySelector, if you want to break out.
You can always override Element.prototype.querySelector to do your biddings, including implementing your own CSS engine that select whatever element you want in whatever syntax you want.
I didn't mention this because you will be breaking the assumption of a very important function, easily breaking other libraries and even normal code, or at best slowing them down.
target.querySelector('.relative');
By using querySelector on the target instead of document, you scope the DOM traversal to the target element.
It is not entirely clear from your explanation, but by related i assume you mean descendant?
To get all target elements you can use
document.querySelectorAll('.target')
And then iterate the result
I found a way which will work for my library.
I will replace "this " in the querySelector with a unique custom attribute value. Something like this:
Element.prototype.customQuerySelector = function(selector){
// Adding a custom attribute to refer for selector
this.setAttribute('data-unique-id', '1');
// Replace "this " string with custom attribute's value
// You can also add a unique class name instead of adding custom attribute
selector = selector.replace("this ", '[data-unique-id="1"] ');
// Get the relative element
var relativeElement = document.querySelector(selector);
// After getting the relative element, the added custom attribute is useless
// So, remove it
this.removeAttribute('data-unique-id');
// return the fetched element
return relativeElement;
}
var element = document.querySelectorAll('.target')[1];
var targetElement = element.customQuerySelector('this + .relative');
// Now, do anything with the fetched relative element
targetElement.style.color = "red";
Working Fiddle
So what I'm trying to achieve is a way to check if any of an element's parents' href begin with something. Here's how far I've come:
$('.element').click(function(e){
if($(this).is('[href^="X"')){
// How to check if the clicked element's href begins with X
}
});
But this is not what I want. I wanna check if any of the element's parents have a href beginning with something.
Any ideas?
Gustaf
I'd suggest, given that nesting an <a> element is invalid so that there can be only one ancestor <a> element (or no ancestor <a> elements, obviously):
$('.element').click(function(e){
// here we use a terribly-, but meaningfully-, named variable
// to hold the Boolean result of the assessment;
// the assessment looks from the clicked element up through
// the ancestors for the first <a> element matching the
// attribute-starts-with selector ([href^=x])
// this will return either 1 or 0 elements.
// we check the length; if it's equal to 1 then the ancestor
// has an href starting with x, if it's 0 then there is either
// no ancestor <a> element or no ancestor <a> element with a
// href matching the attribute-starts-with selector:
var ancestorAnchorStartsWithX = $(this).closest('a[href^=x]').length === 1;
});
It's worth noting, as #A. Wolff did, in the comments below, that:
…closest() [checks the] element itself too.
Which means that if the clicked element itself matches the selector supplied to closest (and is therefore an <a> element with an href beginning with x) then the assessment will return true, even though it's not an ancestor element. I considered this a feature – while writing out the selector – but I forgot to detail that in the answer itself.
If this is considered a bug, then an option using parents('a[href^=x]') in place of closest('a[href^=x]') will be more appropriate to your use-case.
References:
CSS:
Attribute-selectors.
jQuery:
click().
closest().
$(".element").click(function(e) {
var res = $(this).parents("[href^=X]").is("*");
console.log(res);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<a href="Xabc123">
<div class="element">click</div>
</a>
This is what you want:
$('.element').click(function(e){
var $parents=$(this).parents();
var matches=$parents.filter('[href^="x"]');
if(matches.length){
}
}
});
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!
Suppose I want to get innerHTML of below <li> by its data-itemindex. i even don't know it is possible or not.
<li id="li:90" class="liGrid" data-itemindex="3" data-itemid="li:90" >
winoria</li>
i tried
alert($("li").find("[data-itemindex=3]").html());
alert($("li[data-itemindex='3']").text());
from How to select elements with jQuery that have a certain value in a data attribute array
but doesnt help me.
Use the CSS tag selector to locate the matching element/s within the DOM:
$("[data-itemindex=3]")
You can even do some more advanced selectors using a similar syntax:
[title~=flower] /* Selects all elements with a title attribute containing the word "flower" */
[lang|=en] /* Selects all elements with a lang attribute value starting with "en" */
a[src$=".pdf"] /* Selects every <a> element whose src attribute value ends with ".pdf" */
a[src^="https"] /* Selects every <a> element whose src attribute value begins with "https" */
Full documentation.
You can use:
$('li[data-itemindex="3"]').text();
or
$('li[data-itemindex="3"]').html()
Working Demo
Try This:
var data = $('li').data('itemindex', 3).text();
alert(data);