Say I'm looking for all elements with an attribute 'data-language', whose value begins with 'java' (would match both 'java' and 'javascript'). I know how to do this:
$('[data-language^="java"]')
But my question is: how do I get all elements that have an attribute (not the value of the attribute, but the actual attribute name itself) beginning with something? For example:
all elements that have an attribute name beginning with "data-s", or
all elements that have data attributes at all (attributes beginning with "data-").
There is no shortcut, you may use the attributes collection :
$(someselector).filter(function(){
var attrs = this.attributes;
for (var i=0; i<attrs.length; i++) {
if (attrs[i].name.indexOf("someStartOfName")==0) return true;
}
return false;
});
jQuery has a nice function for this.
http://api.jquery.com/data/
$("div").data() // returns all data attributes to this div
Related
I have the following code:
$("#modal-bool-element").change(function(e) {boolSettings($(e.target))});
function boolSettings(e) {
elem = e;
var boolSettingsParent = elem.closest("#bool-settings");
if (elem.is(":checked") == true) {
elem.val(true);
boolSettingsParent.find("#modal-bool-show").prop("disabled", false);
} else {
elem.val(false);
boolSettingsParent.find(".bool-reset, .bool-offset").hide();
boolSettingsParent.find("#modal-bool-show").val("never");
boolSettingsParent.find("#modal-bool-show").prop("disabled", true);
boolSettingsParent.find("#modal-bool-offsetValue, #modal-bool-reset, #modal-bool-offsetUnit").val("");
}
}
What I would like to do is to pass the value of an atrribute to find method along with the classname or id. That attr is elem.attr("model-id").
I have tried like this:
boolSettingsParent.find(`#modal-bool-show [model-id='{elem.attr(model-id)}']`)
But I am not getting any value. How can I achieve the desired result?
Remove the space:
boolSettingsParent.find(`#modal-bool-show[model-id='{elem.attr(model-id)}']`)
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^
The space means you're looking for a descendant element of #modal-bool-show with that attribute. Without the space, it means you only want #modal-bool-show if it also has that attribute value.
You mentioned a class but haven't shown picking one. To do that, you'd tack on a class selector:
boolSettingsParent.find(`#modal-bool-show[model-id='{elem.attr(model-id)}'].some-class`)
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^
BUT, just the id should be sufficient unless you want to skip the element if it doesn't have that attribute and/or class, because you can't have more than one element in the DOM with the same id — doing so is invalid. So adding more things to the selector is fine if you want the selector not to match anything if the element with that id doesn't have the attribute and/or class, but if you're doing it so the selector matches the "right" element with that id, that's a problem because it means you have more than one element with the same id.
I assumed in the above that you were using some templating system that handled the {...} for you, but if you meant to use a substitution in JavaScript's template literal, they use the format ${...}, not {...}. So:
boolSettingsParent.find(`#modal-bool-show[model-id='${elem.attr(model-id)}'].some-class`)
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^
Simply, i'm trying to use jQuery to append a numeric value (currently stored in an array) to the end of the "id" attribute of a number of specified elements.
$('#headerAfirstLink, #headerAsecondLink, #headerAthirdLink, #headerAfourthLink').attr("id", // Append modCount[0].toString() to each existing ID);
The struggle I am having is in working out how to append the numeric value as opposed to simply set the ID equal to the numeric value. I don't want to lose the existing ID.
In the example, the preferred resulting ID's should be:
#headerAfirstLink1, #headerAsecondLink1, #headerAthirdLink1, #headerAfourthLink1
(If modCount[0] == 1).
I'm sure it is crucifyingly simple but would appreciate some guidance.
Thanks
You can use .attr(attributeName, function) syntax to update the attribute value for each of the respective element.
$('#headerAfirstLink, #headerAsecondLink, #headerAthirdLink, #headerAfourthLink')
.attr("id", function(index, oldId) {
// oldId is the attribute value
return oldId + modCount[0];
});
Just in case, to update the attribute of all the elements whose ID starts with header, you can use attribute starts with selector.
$('[id^="header"]').attr('id', function(index, oldId) {
return oldId + modCount[0];
});
Try to use .attr("attrName" , callBack) signature to achieve what you want.
$('#headerAfirstLink, #headerAsecondLink, #headerAthirdLink, #headerAfourthLink')
.attr("id", function(_,id){
return id + modCount[0];
});
Don't confuse the first parameter passed with callBack. It is index. I just used an underscore there as it is not required in our case. Simply to hide its visual.
Or the best/maintainable approach would be setting a common class (ex: test) to those four elements and use a class selector there instead of multiple selector.
$('.test').attr('id', function(_, id) {
return id + modCount[0];
});
Inspired by this question and dealing with a similar situation, I wonder whether anyone can explain the rationale behind the decision to have element.id return an empty string when the id attribute is not present.
If the spec was to return null or undefined I could simply write
var allIds = $('#my-frm input').map(function() { return this.id; }).get();
Instead I have to either add a qualifier to the selector, as in
var allIds = $('#my-frm input[id]').map(function() { return this.id; }).get();
or use the other solution proposed to the above-mentioned question (which has to get the id twice in case it is present)
var allIds = $('#my-frm input').map(function() { return (this.id) ? this.id : null; }).get();
or I can use the jquery attribute getter, which seems unnecessary to wrap each element into a jquery object first, but I'm mentioning it for completeness and to show that jquery went the other direction with the .attr() method.
var allIds = $('#my-frm input').map(function() { return $(this).attr('id'); }).get();
I'm curious if there is a practical reason behind the javascript element.id behavior.
Update:
I finally located the relevant spec, which defines the current behavior (it doesn't explain why it was defined this way)
https://www.w3.org/TR/2015/REC-dom-20151119/#element
interface Element : Node {
readonly attribute DOMString? namespaceURI;
readonly attribute DOMString? prefix;
readonly attribute DOMString localName;
readonly attribute DOMString tagName;
attribute DOMString id;
attribute DOMString className;
...
Either when an element is created that has an id attribute whose value is not the empty string or when an element's id attribute is set to a value other than the empty string, set the element's ID to the new value.
When an element's id attribute is removed or set to the empty string, unset the element's ID.
Some IDL attributes are defined to reflect a particular content attribute of a given name. This means that on getting, these steps must be run:
Get an attribute for the context object using content attribute's name and let value be the result.
If value is null, return the empty string.
Return value.
On setting, set an attribute for the context object using the name of the attribute and the given value.
The id attribute must reflect the "id" content attribute.
I'm curious if there is a practical reason behind the javascript
element.id behavior.
See Element.id
The Element.id property represents the element's identifier,
reflecting the id global attribute.
If the spec was to return null or undefined
3.2.5.1 The id attribute
Identifiers are opaque strings. Particular meanings should not be
derived from the value of the id attribute.
Note There are no other restrictions on what form an ID can take; in particular, IDs can consist of just digits, start with a digit,
start with an underscore, consist of just punctuation, etc.
Note An element's unique identifier can be used for a variety of purposes, most notably as a way to link to specific parts of a
document using fragment identifiers, as a way to target an element
when scripting, and as a way to style a specific element from CSS.
It's funny how the result is kind of opposite of the intent. Because I
want to avoid calling a separate method to check for the existence of
id
To substituting $.map() for .map() , Array.prototype.filter() with parameter Boolean for .get() to return id that is not empty string
var allIds = $.map($("input"), function(el) {
return el.id
}).filter(Boolean);
jsfiddle https://jsfiddle.net/gqvfuzqr/
Say I'm looking for all elements with an attribute 'data-language', whose value begins with 'java' (would match both 'java' and 'javascript'). I know how to do this:
$('[data-language^="java"]')
But my question is: how do I get all elements that have an attribute (not the value of the attribute, but the actual attribute name itself) beginning with something? For example:
all elements that have an attribute name beginning with "data-s", or
all elements that have data attributes at all (attributes beginning with "data-").
There is no shortcut, you may use the attributes collection :
$(someselector).filter(function(){
var attrs = this.attributes;
for (var i=0; i<attrs.length; i++) {
if (attrs[i].name.indexOf("someStartOfName")==0) return true;
}
return false;
});
jQuery has a nice function for this.
http://api.jquery.com/data/
$("div").data() // returns all data attributes to this div
I'm used to JQuery but not to pure Javascript.
I have this:
document.getElementById("div-id a").style.javascript_property = "color: red;";
OF COURSE it doesn't work.
What i want is that all a-tags in one specific div with an id='div-id' to become red.
in jquery i would write:
$('#div-id a').css('color', 'red');
But i need it in pure js.
Use:
var div = document.getElementById("div-id");
var list = div.getElementsByTagName("a");
for (var i = 0; i < list.length; i++) {
list[i].style.color = "red";
}
The getElementById method takes a string representing an id, not a selector. The clue is in the name. The querySelectorAll method takes a string representing a selector, but it returns a nodeList, so you would have to loop over it like an array.
The property name which you have called javascript_property needs to match the CSS property name (with hyphenated-words turned into camelCase) (so it should be "color").
The value you give it needs to match the CSS properties value, not the entire rule (so "red").
None of this, however, is pure JavaScript. It is DOM (except for querySelectorAll which is from the Selectors API).