Jquery selector syntax question - javascript

I encounter the following syntax:
$('#sourcePane input:checked~img');
I know it is selecting all input elements that are checked and also under the element of id= sourcePane ? right?
But what is ~img? what does ~ do?
also, the corresponding element in HTML is
<div data-module="Sources" data-module-id="sourcePane">
Why is it not id="sourcePane" but data-module-id="sourcePane" ??

a ~ b
This is the CSS 3 general sibling combinator. It means "Select all b elements that are next siblings to a.". It works like the adjacent sibling combinator a + b, but b does not have to immediately follow a.
data- Attributes
This is HTML5 syntax to create custom attributes. From the HTML5 spec:
Custom data attributes are intended to store custom data private to the page or application, for which there are no more appropriate attributes or elements.
Your selector will not work unless you either change your HTML to:
<div id="sourcePane" data-module="Sources" data-module-id="sourcePane">
or change your selector to:
$('[data-module-id="sourcePane"] input:checked~img');

The '~img' selects a sibling with the <img /> tag after the input:checked.
(see here: http://api.jquery.com/next-siblings-selector/#prevsiblings)

Related

What happen when you use select# as a css selector?

I found these two element selectors: select#usuario-select and #usuario-select. Would they return the same node in case I use them as a document.querySelector() parameter?
These are CSS selectors, as you said. document.querySelector looks for the first element matching the provided CSS selector. So:
document.querySelector('select#usuario-select') looks for the first select tag with id usuario-select ( <select id='usuario-select'>)
document.querySelector('#usuario-select') looks for the first any tag with an id usuario-select (<ANYTAG id='usuario-select'>)
They would return the same node if the first element with id usuario-select is a select tag.
You may find this link helpful.
[1]https://www.w3schools.com/jsref/met_document_queryselector.asp
This sign # just simply change the text of an element with id= usuario-select
To answer your first question, the # character is used as an ID Selector.
If you have a DOM element with the id attribute set; a corresponding ID Selector can be used to query for this node.
Example:
// This is a Class Selector. It'll query for the parent div because
// it has a `class` attribute with a matching identifier.
.parent {
background-color: black;
}
// This is an ID Selector. It'll query for the H1 text element because
// it has a `id` attribute with a matching identifier.
#name {
color: white;
text-align: center;
}
// This is an Element Selector AND an ID Selector. It'll query for
// and `<img/>` DOM node that has a matching `id` attribute value.
img#avatar {
float: left;
}
<div class="parent">
<img id="avatar" src="https://via.placeholder.com/300x300">
<h1 id="name">John Doe</h1>
</div>
MDN is a great resource for learning more about selectors:
Selectors
Simple selectors
Attribute selectors
Pseudo classes and pseudo elements
Combinators and multiple selectors
As for your final question of "would (a css selector) return the same node as (the) document.querySelector (function)?", yes.
The Document.querySelector documentation can be found here.
It states the following:
Syntax
element = document.querySelector(selectors);
Parameters:
selectors:
A DOMString containing one or more selectors to match.
This string
must be a valid CSS selector string; if it isn't, a SYNTAX_ERR exception is thrown.
As far I as understand your question,
"select#usuario-select" Vs. "#usuario-select"
select#usuario-select this will select select element with ID #usuario-select your selection is specifically target select element only.
While #usuario-select this will select an element with ID #usuario-select, you don't target which element.
Since rule of thumb of CSS, ID would be always unique; therefore only one element with specified ID will be selected and returned.
Back to your question, will they return the same? - It depends on your HTML.
Suppose your HTML Makeup is like this:
<select id="usuario-select">
<option value="a">Apple</option>
<option value="b">Banana</option>
</select>
Then, either document.querySelector("select#usuario-select") or document.querySelector("#usuario-select") will return the same node.
However, if your HTML Makup is like this:
<p id="usuario-select">Hey, I has ID "#usuario-select"</p>
Then, the first select expression document.querySelector("select#usuario-select") will return none because there is not select element with ID usuario-select, insead document.querySelector("#suario-select") will return the paragraph element, the same select expression for this is document.querySelector("p#usuario-select") also return the same.
Hope this help.

jQuery selector : 'starts-with && ends-with' doesnt work on element with multiple classes

The issue is simply as following, when I try to select a class that starts with a keyword , and ends with another keyword, this works fine, if and only if the element has a single class, if element has multiple classes, the selector will return an empty collection.
Here is code to explain the issue
// try removing custom-class from first element --> returns 2
alert($("div[class^='start'][class*='end']").length) // will return 1 by default , only 1 element has single class.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="custom-class start-mid-end" data-custom="1st Div">
</div>
<div class="start-mid-end" data-custom="2nd Div">
</div>
That's because for the element with class="custom-class start-mid-end", the value of its class attribute begins with custom, not start. Remember, the attribute selectors operate on the attribute value as a single string; they don't care that the class attribute is "special" in HTML.
Regarding a solution to your problem: there aren't any without caveats. As the most practical workaround, I would suggest using multiple classes instead of just one. For example, instead of just prefix-X-suffix also add the classes prefix- -suffix and then you can select your elements simply with
$("div[.prefix-.-suffix]")
Another option would be to use filter to customize the class selection logic, e.g.
$("div").filter(function() { return /\bstart\S*end\b/.test(this.className); })
The regex \bstart\S*end\b matches any sequence of non-whitespace characters with the prefix start and the suffix end, which is what you are after.
The selectors you use refer to the whole attribute string, so class="start what ever end" will be a match.

How do you grab an element relative to an Element instance with a selector?

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

Replacing the inner.html of an unknown named element based on condition

I run into this problem frequently and never know the best approach. Imagine I have a structure that includes several instances of the following html:
<div class="known">
<div class="another unknown">
<div class="unknown">
<h4>Something a something</H4>
</div>
</div>
</div>
For each div of class known, I want to change the inner html of that div only if it contains a div inside it with some particular tag, in this case <h4>.
What is the best way to achieve that. I know that I could do it by taking the inner html of class known and doing a regex match. But is there a more robust way based on tags?
Simple, just use a selector that spans over the div.known and restrict it's context to div h4. If the selector selects at lease one element then the div.class has children as you expect.
if( $('.known div h4').length > 0 ){
$('.known').html('Some html');
}
Yes! You can do this.
var head = Array.prototype.slice.call(document.querySelectorAll("h4 #known"));
for(var i = 0; i < head.length; i++)
{
while(head[i].className !== "known")
head[i] = head[i].parent();
}
Now head will be an array of all the DOM elements have the tag known and have h4's in them.
With jQuery, you can use .has() to narrow your selection and even chain other methods, as in:
$(".known").has("h4").css("background","red");
Check out this fiddle for example. Notice that clicking the button will change the color of any div.known only if that element contains an h4 tag as a descendant.
Documentation on jQuery's .has() -- https://api.jquery.com/has/

Meaning and usage of jquery find('>')

I'm working on a javascript code which does :
$('div').html(<some text>).find('>')
Looking at the jQuery documentation, I can't understand what find('>') is supposed to do.
Moreover, when experimenting in navigator console, I get strange results :
$('div').html('to<br/>to').find('>') -> [ <br>​, <br>​, <br>​]
$('div').html('to<a/>to').find('>') -> [ <a>​</a>​, <a>​</a>​, <a>​</a>​]
Why a 3 times repetiton ?
So, can anyone enlighten me about this strange find('>') ?
> is the Child Combinator CSS selector. .find('>') will pull all direct children of the element.
As mentioned in comments, the repetitions must be due to your document having multiple div elements.
Update
From your comment:
I thought the line was creating a div then setting some html into it.
$('div') itself selects all div elements which exist within document. If you want to create a div element, you can instead do this:
$('<div/>', { html: 'to<br/>to' });
If you're new to jQuery, I'd strongly advise checking out http://try.jquery.com and http://learn.jquery.com.
As someone pointed out, '>' selects the child elements of an element.
Why 3? Because surely you have 3 divs, so
$('div') //selects 3 divs
.html(...) // adds content to each div
.find('>'); //return the direct descendants of each element in the jQuery object
//as a new jQuery object

Categories

Resources