5

Context :

  • HTML

     <div ng-me=""></div>
     <div ng-you=""></div>
      <p ng-you=""></p>
    

I want to select all elements which has attribute name starts with ng-.


Using jQuery , the following links are the closest threads to this issue :

  1. jQuery - How to select value by attribute name starts with .

  2. How to remove all Attributes by attribute name starts with .

However ,the first uses jQuery , and the second resolves removing issue of already selected elements NOT selection .

I try this :

document.querySelectorAll('[ng-*]')

And it does not work , but rather, it throws error.

Community
  • 1
  • 1
Abdennour TOUMI
  • 64,884
  • 28
  • 201
  • 207

5 Answers5

5

Here I use querySelectorAll to get all objects that I want to check.

Then I look at the attributes collection of each returned object

function attrStartsWith(sel,str) {
  var el = document.querySelectorAll(sel), res=[];
  
  for (var i = 0, n=el.length; i < n; i++){
    for (var j=0;j<el[i].attributes.length;j++) {
      if (el[i].attributes[j].name.indexOf(str)==0) {
        res.push(el[i]); 
      }
    }
  }
  return res;
}
console.log(attrStartsWith("*","ng")); // all
console.log(attrStartsWith("div","ng")); // divs
<div ng-a="a">a</div>
<div ng-b="b">b</div>
<p ng-c="c">c</p>
mplungjan
  • 134,906
  • 25
  • 152
  • 209
4

ES6 solution :

const attrStartsWith = (prefix) =>
  Array.from(document.querySelectorAll('*'))
   .filter(
      (e) => Array.from(e.attributes).filter(
        ({name, value}) => name.startsWith(prefix)).length
   )

Then :

attrStartsWith('ng-') // return an array of HTML elements which  have attributes name starts with "ng-"

versions of 2017-12-02

const queryByAttrNameStartsWith = (contextualSelector = '*') => {
  const elements = Array.from(document.querySelectorAll(contextualSelector));
  return (prefix) =>
    elements.filter(e =>
      Array.from(e.attributes).find(({ name, value }) =>
        name.startsWith(prefix)
      )
    );
};
//then
queryByAttrNameStartsWith('*')('data-'); // all elements that have attribute name that starts with 'data-'
queryByAttrNameStartsWith('div')('ng-'); // ony DIV elements that have attribute name that starts with 'ng-'
//.. so on

or :

NodeList.prototype.filterByAttrNameStartsWith = function(prefix) {
  return Array.from(this).filter(e =>
    Array.from(e.attributes).find(({ name, value }) => name.startsWith(prefix))
  );
};
//then
document.querySelectorAll('*')
 .filterByAttrNameStartsWith('data-'); // all elements that have attribute name that starts with 'data-'
document.querySelectorAll('div')
 .filterByAttrNameStartsWith('ng-'); // ony DIV elements that have attribute name that starts with 'ng-'
//.. so on
Community
  • 1
  • 1
Abdennour TOUMI
  • 64,884
  • 28
  • 201
  • 207
2

So I combined the efforts of gavgrif and mplungjan with what I made already:

HTML:

 <div ng-me="">1</div>
 <div ng-you="">2</div>
 <div not-me="">3</div>
 <div ng-yes="">4</div>

CSS:

.ng-class {
    background-color: red;
}

JavaScript:

var el = document.getElementsByTagName("*");
var list = [];

// Grab all elements on the page and check them for attributes
for (var i = 0, n = el.length; i < n; i++) {
     for (var j = 0; j < el[i].attributes.length; j++) {
        // If match, push into seperate array
        if (el[i].attributes[j].name.indexOf("ng") == 0)       
            list.push(el[i]);
     }
}

// Add a custom class to these elements
for(var i = 0; i < list.length; i++) {
    list[i].classList.add('ng-class');
}

Codepen example here

mplungjan
  • 134,906
  • 25
  • 152
  • 209
roberrrt-s
  • 7,249
  • 2
  • 41
  • 53
  • 1
    Your solution now is better than mine indeed, especially after the edit. (cleaner as well). fwiw: I upvoted it, and learned from it. – roberrrt-s Sep 08 '16 at 09:31
0

div [^="ng-"] should do it for you - What this does is specificy all elements that have attributes that start with "ng-" (and in his example applies a background color)

*[^="ng-"] {background-color:red}
gavgrif
  • 13,077
  • 2
  • 17
  • 22
  • 1
    Wouldn't the `* [^="ng-"]` selector be better? We don't know if OP has other elements beside `
    `
    – roberrrt-s Sep 08 '16 at 08:35
  • Also, this doesn't work, since it doesn't target the name of the attribute, only the value. – roberrrt-s Sep 08 '16 at 08:37
  • 1
    As @ Roberrrt says - I am incorrect - this is only targets the value of the attribute - not the name. I posted it - thought I was very clever then actually read up on selectors based on attribute and realised I am not very clever. I will leave the post up because it helpful for the OP and it may allow others to start thinking of specific slecectors based on attribute content. Thanks – gavgrif Sep 08 '16 at 08:45
  • This is css selector not accepted by `document.querySelectorAll` – Abdennour TOUMI Sep 08 '16 at 08:55
0

Necromancing.

ES 5 solution :

    function findElementsWithArributePrefix(selector, prefix)
    {
        return [].slice.call(document.querySelectorAll(selector)).filter(function (e)
        {
            return [].slice.call(e.attributes).filter(
                function (attr)
                {
                    return attr.name.startsWith(prefix);
                }
            ).length;
        });
    }

Then :

console.log("prfx", findElementsWithArributePrefix("*", "ng-"));
Community
  • 1
  • 1
Stefan Steiger
  • 68,404
  • 63
  • 337
  • 408