Understanding element types - javascript

Let's say I have multiple buttons that use a class named submit. I add this reference to jQuery.
When the button is clicked; it should be disabled.
Scripts I could use:
A.$('.submit').click(function () { this.disabled = true; });
B.$('#submit').click(function () { this.prop('disabled'), true); });
C.$('#submit').click(function () { $(this).disabled = true; });
D.$('.submit').click(function () { $(this).prop("disabled", true); });
The correct answer is D.
So, personally, I was pretty sure it was C. (which is wrong) because I saw the # before submit. I do this alot with questions like these, where I try to assume I know what the correct selector is. Which I always assume # is the correct one.
In hindsight the question states it's a class so I believe that's where the . is appropriate. However, without being told it's a class, I would have just guessed.
Sometimes I see an id referenced like so #imnotaclass or what have you, which is confusing me.
Can someone better explain jquery selectors to me, when to use # , ., or
In jQuery there's documentation on the selectors. Is there not continuity between other languages ie, css, html. I noticed with those 2 I can pass in something and use # on all fronts. However it will be an id and yet it still works.
The reason I bring this up is to better understand; on an exam what the correct answer is.

If "submit" is a class name, then the correct answer would be A:
$('.submit').click(function () { this.disabled = true; });
because it is the only answer that selects an element with that class name and properly sets the disabled property inside the event handler.
The code inside the event handler is wrong for options B, C and D so there is no way that they could be considered correct.
The question seems to be checking your knowledge of three things: 1) CSS selector syntax, 2) how to set properties on a DOM element and 3) what is the value of this in a jQuery event handler and how you use it.
The two correct ways to set the disabled property inside the event handler are:
// use direct DOM property access
this.disabled = true;
// use jQuery's .prop()
$(this).prop("disabled", true);
As for CSS selector syntax basics:
A selector that starts with # targets an ID value identified with id="xxx" in the HTML or set as a property on the DOM element.
So "#submit" references a single element with an id as in
<button id="submit">Press Here</button>
A selector that starts with . targets a class name identified with class="xxx" in the HTML or set as a property on the DOM element.
So ".submit" references one or more objects with a given class name as in
<button class="submit">Press Here</button>
ID values must be unique in the document (only be used on one single element). Class names can be used on as many elements as desired.
If you want to see more about the selectors that jQuery uses, you can read this tutorial.
If you were going to use jQuery inside the event handler, it would be this:
$('.submit').click(function () {
$(this).prop('disabled', true);
});
As shown in the jQuery documentation for .prop().
If "submit" was an id value, then the correct answer would be:
$('#submit').click(function () {
$(this).prop('disabled', true);
});
Inside your jQuery event handler, the value of this will the DOM element that you registered for the event on. That means if you use something like this.id, then you must be referencing DOM properties or calling DOM methods.
If you want to call jQuery methods, then you would use $(this) to turn it into a jQuery object so you can then use jQuery methods or properties.
Keep in mind that every jQuery object contains an array of zero or more DOM elements. You can access the individual DOM elements in the jQuery object via the array syntax as in $(this)[0] or via the .eq() method as in $(this).eq(0) and a jQuery object has a .length property which tells you how many DOM elements are in the array as in $(this).length === 1.

This is excerpted from the documentation. I'm posting this here as supporting information for #jfriend00's answer
Sizzle is the selector engine which jQuery uses.
Note: In supported browsers, jQuery will attempt to use document.querySelectorAll() to resolve CSS selector queries rather than it's internal selector engine if the requested selector does not use jQuery extensions that are not supported by document.querySelectorAll(). This is done for performance reasons
Selectors
CSS3
Sizzle supports virtually all CSS 3 Selectors, including escaped selectors (.foo\+bar), Unicode selectors, and results returned in document order. The only exceptions are those that would require additional DOM event listeners to keep track of the state of elements.
As such, the following pseudo-selectors are not supported:
:hover
:active
:visited, :link
Note: These CSS3 pseudo-selectors were unsupported prior to version 1.9:
:target
:root
:nth-last-child
:nth-of-type, :nth-last-of-type, :first-of-type, :last-of-type, :only-of-type
:lang()
Other selectors and conventions
Changes
Full selector lists in :not(); e.g. :not(a.b), :not(div > p), :not(div, p)
Nested pseudo-selectors; e.g. :not(:has(div:first-child))
Additions
[NAME!=VALUE]: Elements whose NAME attribute doesn't match the specified value. Equivalent to :not([NAME=VALUE]).
:contains(TEXT): Elements with textContent containing the word 'TEXT'. Case-sensitive.
:header: Header elements (h1, h2, h3, h4, h5, h6).
:parent: Elements with at least one child node (either text or an element).
:selected: (option) elements that are currently selected
Form Selector Additions
Note: In this context, input, button, select, and textarea are all considered to be input elements.
:input: Input elements
:button: Input elements that are buttons or have type "button"
:checkbox, :file, :image, :password, :radio, :reset, :submit, :text: Input elements with the specified type
Positional Selector Additions
In this context, "positional" refers to an element's placement in the collection after a selection, based on document order. For example, div:first would return an array containing the first div on the page, while div:first em would target the first div on the page and select all em elements within.
Note: Positional indexes begin at zero.
:first/:last: The first/last matching element
:even/:odd: Even/odd-numbered elements
:eq/:nth: The nth element; e.g. :eq(5) finds the 6th element
:lt/:gt: Elements at positions above/below the specified position
https://github.com/jquery/sizzle/wiki#selectors

Related

Grabbing a class within a class with javascript

Hello this is my first question and I'm an amateur developer so forgive me in advance. I'm trying to grab this specific instance of the value class. The website I am working on has hundreds of different values associated with the value class.
<li class = "vin">
<strong class = "title">VIN:</strong>
<span class="value">121212121212121212</span>
</li>
Below is what I've been doing and it hasn't been working.
var vinNum = document.getElementsByClassName('li.vin','span.value');
console.log(vinNum.innerText);
Thank you
Although the existing answers cover the "modern" way to do this already - you can use most of the getElementsBy... (all, I think - was gonna say except getElementById, but that is named in singular for a reason, and because of the meaning of an id special) methods on all elements.
https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByClassName:
The Element.getElementsByClassName() method returns a live HTMLCollection containing all child elements which have all of the given class names. When called on the document object, the complete document is searched, including the root node.
So you can use that twice, to first select an element with one specific class, and then another with a different class "within it", among the descendants of the former. (Not "child elements", as the quoted MDN reference wrongly puts it.)
var vinNumContainer = document.getElementsByClassName('vin')[0],
vinNumElement = vinNumContainer.getElementsByClassName('value')[0];
(Necessary checks for whether elements exist before accessing them, what to do if more than one element (of either one) exists, etc., left out for brevity ;-)
But a simple call to querySelector is of course a quicker way to do it.
Try
var vinNum = document.querySelector('li.vin span.value');
console.log(vinNum.innerText);
This works because rather than selecting by class you're selecting the li.vin element which has a span.value as a child. vinNumber is now a node element. When you call vinNum.innerText you should get the correct number. When you console.log(vinNum) in uour example you will most likely see undefined or the incorrect element.
You can use the document.querySelector function in order to search elements on your page based on class, ID, or anything else that can be selected using a CSS selector.
Using Mozilla's CSS Selector reference, we can see that the CSS selector syntax to select an element which is a direct child of some other element is A > B, where A is a selector matching the parent, and B is a selector matching the child.
So one way to do this is to use:
var vinNum = document.querySelector('li.vin > span.value')
The one-liner above will match the first span element of class value which is a child of a li element of class vin.
However, if you have multiple examples of this structure (a li of class vin with a span of class value within it), using this selector won't work. In fact, if you want to have access to each specific span of class value individually, perhaps the best way would be to add a unique id attribute to each of them.
If your structure looked like this:
<li class = "vin">
<strong class = "title">VIN:</strong>
<span class="value" id="v25">121212121212121212</span>
</li>
You could then use the following:
var vinNum = document.querySelector('#v25')
One last alternative for when you have a list of nested HTML elements all with the same structure is to use document.querySelectorAll, which will return all DOM nodes which match your query and allow you to use JavaScript to run through them and select the values you want.

adding onclick event on class

I am trying to write a greasemonkey script which adds an onClick listener on a button (define below) and do some specific things. I was trying to get this button obj using document.getElementsByTagName but it returned null. I tried to iterate over document.anchors and it returned null as well. how can i get this element object and add onclick event to it.
<a class="editicon" aria-label="Edit this field" role="button" href="#"><img src="https://url-to/images/edit.png?3423434"></a>
There is already an onclick added to this object, I don't want to replace it.
UPDATE
Adding my Greasemonkey script
// ==UserScript==
// #name cr
// #namespace my_namespace
// #version 1
// #grant none
// ==/UserScript==
(function(){
console.log('test ...')
var editicon = document.getElementsByTagName('editicon');
console.log(editicon);
})();
First, your question talks about a button, but your code does not include one. Instead of using an <a> element and then disabling its native navigation function with href="#", it would be semantically better to use an actual <button> element.
Second, you should not use inline HTML event attributes (onclick, onmouseover, etc.) as they:
Create "spaghetti code" that doesn't scale, is hard to read, leads to duplication and doesn't follow the "separation of concerns" methodology.
Create global anonymous wrapper functions around your event attribute value that alter the this binding of your code.
Don't follow the W3C Event Standard of using the addEventListener() API.
Now, there are several ways to get a reference to a DOM element and some are better than others depending on your HTML structure and how many elements you are trying to get. document.getElementsByTagName() returns a "node list" of all the elements that were found. Even if no elements were found, you still get this list as the returned object (the list will just be empty when no elements were found). To extract a particular element from the result, you'll need to pass an index into that list, which is an "array-like" object. Additionally, getElementsByTagName returns a "live" node list, meaning that it will re-scan the document upon every interaction to ensure that the most current list is provided. While this can be beneficial in some circumstances, it comes with a performance cost.
This, for example, would extract the first a element in the document:
var myElement = document.getElementsByTagName("a")[0];
But, since you are only expecting a single element, that is overkill. To get just one element, and if that element has an id attribute on it, you can/should use: document.getElementById("theIdHere"); as getElementById() is generally the fastest way to find a single element in your HTML structure.
Additionally, there are other ways to get an element or elements, like querySelector() and querySelectorAll(), which allow you to use CSS selector syntax in your JavaScript queries.
For your code, see the following snippet:
// Get a reference to the first <button> element in the document
var b = document.querySelector("button");
// Or, if the element has an id, the best solution would be:
var b = document.getElementById("btn");
// Add a click event handler to the element
b.addEventListener("click", handleClick);
// Function that will be called when anchor is clicked
function handleClick(){
alert("You clicked me!");
}
button { background-color:rgba(0,0,0,0); }
img { width: 50px; }
<button class="editicon" aria-label="Edit this field" role="button" id="btn"><img src="https://s-media-cache-ak0.pinimg.com/736x/5a/42/c6/5a42c6224e3ce7fa9837965270bfcdd9--smiley-face-images-smiley-faces.jpg"></button>

.Remove() not working in deleting a textbox with id in the form of an collection

I have a hidden textbox with id in the form of a part of a collection. I use the ID in this way so as to have them bind to my model. This is the simplified version of my code.
<input id="Model.Bed[0].Id" name="Model.Bed[0].Id" type="hidden" value="bed1">
I am using Jquery to remove it but while it does not throw any error, it does not get deleted. This is my code.
$('#Model.Bed[0].Id').remove();
Am I missing something?
Your jQuery selector returns 0 items because it is an invalid selector expression( [ has a different meaning)
Try the name selector. This should work
$("[name='Model.Bed[0].Id']").remove();
Keep in mind that it is allowed to have more than one element with same name attribute value. So use based on your DOM.
Also, If you have this input element generated in a loop and you have some button inside this loop for executing your remove code, you should consider using relative selectors. closest() and find() methods are handy in this case.
For example,
// Register click event with element with css class "someDeleteBtn"
$(".someDeleteBtn").click(function(e){
e.preventDefault();
$(this).closest(".containerDiv") //get to outside container
.find(".myHdnBed") // find the hidden input with this css class
.remove(); // remove
});
To escape special characters in an ID selector, you can use \ like so:
$('#Model\\.Bed\\[0\\]\\.Id').remove();
which works: http://codepen.io/anon/pen/XpqJxV
Read more here: https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/
In the end though, you really shouldn't have a value like that as an ID in the first place.

add attribute to DOM element

I have a modal form that is generated using bootstrap 3. It doesn't look like there is a reliable way to determine when that form is being shown onscreen. I am attempting to create one. I attached two events to my DOM element that signal when it is shown and when it is hidden.
jq_modal_login_form = $('#modal-login-form')[0]
jq_modal_login_form.on('shown.bs.modal', function () {
jq_modal_login_form.active_onscreen = true;
});
jq_modal_login_form.on('hidden.bs.modal', function () {
jq_modal_login_form.active_onscreen = false;
});
I tried to give an attribute named active_onscreen to the DOM element above. When I look at the DOM element in the debugger later, the attribute is not present.
I should mention that I am VERY new to javascript. Is attribute even the right word to use here? It looks like attribute is a bit of a misnomer as well. It could be an attribute of the object but could also be an attribute of the object.attributes attribute, right? I assume the later is where styling ect., goes and is not what I want to change. Does anyone have some insight as to what I should be doing here?
In jQuery:
$('selector').attr('attribute_name', 'value');
However, you can should only use predefined attributes as creating custom attributes requires additional setup (see this question) that is not necessary in your case.
In your case, you may just want to add a active_onscreen class to the element. Classes are meant to be used to identify elements (and not just for CSS), so they are perfect for this applicaiton. You would use this to add a class to an element:
$('selector').addClass('active_onscreen').
When it is no longer active, you would use this to remove the class:
$('selector').removeClass('active_onscreen').
What you are doing here is adding a property of the DOM object - not an attribute of the element.
Adding an attribute does not necessarily make the property mirror it. Only built-in properties do this.
If you want to set an attribute, but not the property, you can use jQuery's .attr() method.
If you just want to see if a given modal is open, Bootstrap does that for you. You can check the bs.modal data attribute:
$("element").data('bs.modal').isShown;
or a class (but this method is prone to race conditions):
$('#myModal').hasClass('in');

How do i get all children (ie children of children) with Javascript?

I need a javascript function or a CSS Selector (or even a ProtoypeJS function) which gets me ALL elements (ie. descendants) under a particular element.
I understand there are CSS selectors such as : 'p, a, div', which would get me all the elements of those three types. However I need to get EVERYTHING without specifying type.
ie. I want something like
myElement.getElements('*')
You can use querySelectorAll
myElement.querySelectorAll('*')
Note: Supported in IE8+
Compatible with all versions of IE, not just IE8+...
myElement.getElementsByTagName("*")
* is treated as a special case for getElementsByTagName to return all descendants regardless of tag name. (This is different to querySelectorAll, where * is a genuine selector that matches all elements)
The method that will get you all child elements as an extended PrototypeJS array is childElements() http://api.prototypejs.org/dom/Element/prototype/childElements/
element.childElements()
For other situations you might want to narrow down the child elements that are returned you can use select()
element.select('div')
will return all the div children of element
It's easy enough to do this with CSS alone. The * (universal) selector targets all elements. If you want to target all children of a specific element, then you can simply do this:
element * {}

Categories

Resources