Reputation: 1204
I have two elements with the following setup:
<span data-placeholder-class="test-class"></span>
<span data-placeholder-template="/some/template.hbs"></span>
I'm using underscore to loop over any elements containing either of these attributes and then performing relevant actions if they do.
Currently this is done like so
_.each($('[data-placeholder-class], [data-placeholder-template]'), function cb(element) {
// code goes here
})
Rather than have to define each data attribute to loop over I wondered if there was a way I could select all attributes that contain a common keyword, in this case placeholder. e.g.
_.each($('[data-placeholder-*]'), function cb(element) {
// code goes here
})
Anyone know if this is possible at all?
Upvotes: 7
Views: 1011
Reputation: 136568
I know this is a jquery question, but there is a vanilla way of doing it, thanks to XPath queries :
The starts-with()
XPath function will do exactly that.
So the query //*[@*[starts-with(name(), 'data-placeholder')]]
will give you what you are after.
unwrapped :
'//' + // from root to anywhere in the tree
'*' + // any kind of node
'[@*' + // with any attribute
'[starts-with(name(), "data-placeholder")]' + // which starts with "data-"
']'
function getElementsByStartOfAttribute(start_of_attr) {
var query = document.evaluate("//*[@*[starts-with(name(), '" + start_of_attr + "')]]",
document, null, XPathResult.ANY_TYPE, null);
var elements = [];
var el;
while (el = query.iterateNext()) {
elements.push(el);
}
return elements;
}
var placehodlers = getElementsByStartOfAttribute('data-placeholder');
console.log(placehodlers);
$(placehodlers).css('background', 'green');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span data-placeholder-class="test-class">should find me</span>
<span data-placeholder-template="/some/template.hbs">me too</span>
<span data-not-placeholder-template="/some/template.hbs">
data-not-placeholder-template
</span>
<span data-not-placeholder-template="/some/template.hbs">
data-not-placeholder-template
</span>
Upvotes: 1
Reputation: 564
SAMPLE HTML:
<span data-placeholder-class="test-class">test</span>
<span data-placeholder-template="/some/template.hbs">hahaha</span>
<span>hahahahaha</span>
<span data-test="/some/template.hbs">hahahahaha</span>
JS:
$('span').filter(function(ndx, item){
var data = Object.keys($(item).data())[0]; // gets data name
if (data === undefined) {
return;
}
// checks if data starts with placeholder
if (~(data.indexOf('placeholder'))) {
// do anything to that item here
return item;
}
}).css('color', 'green');
Fiddle: here
Hope this helps! :)
Upvotes: 0
Reputation: 249
You could consider using a separate function which creates your selector, so you won't have to type the selector in full (but you'll have to write the function of course).
e.q.:
function getSelector() {
return Array.prototype.map.call(arguments, function(key) {
return '[data-placeholder-' + key + ']';
}).join(',');
}
This will return your desired selector, and works with 1...N arguments.
getSelector('class', 'template')
// returns "[data-placeholder-template],[data-placeholder-class]"
_.each($(getSelector('class', 'template')), function cb(element) {
// code goes here
});
Upvotes: 3
Reputation: 1
You can iterate the attributes
of a collection of elements, push the element to an array if the element .attributes.name
matches a provided string variable
var spans = document.querySelectorAll("span");
function filterAttrs(elems, attr, matches = []) {
for (var elem of elems) {
for (var attrs of elem.attributes) {
// alternatively use `.indexOf()` or `RegExp()`
// to match parts of string of `.name` or `.value`
// of `.attributes` `NamedNodeMap`
if (attrs.name.slice(0, attr.length) === attr) {
matches.push({
"element": elem,
"attr": {
"name": attrs.name,
"value": attrs.value
}
})
}
}
}
return matches
}
var matches = filterAttrs(spans, "data-placeholder");
console.log(matches);
matches.forEach(function(match) {
match.element.textContent = "matches:" + JSON.stringify(match.attr);
match.element.style.color = "green";
});
<span data-placeholder-class="test-class"></span>
<span data-placeholder-template="/some/template.hbs"></span>
<span data-not-placeholder-template="/some/template.hbs">
data-not-placeholder-template
</span>
<span data-not-placeholder-template="/some/template.hbs">
data-not-placeholder-template
</span>
Upvotes: 1
Reputation: 222
var eles = $('span').filter(function() {
for (var attrName in $(this).data()) {
if (attrName.indexOf('placeholder') == 0) {
return true;
}
}
return false;
});
console.log(eles);
I hope this will help you :)
Upvotes: 0