Reputation: 61
first of all thanks to everyone who is willing to help me. My problem is quite big, so basically i want a method, that could identify all current pseudo names on my given HTML element. Then check what CSS styles were added or modified through those pseudo classes and append them to new HTML element. All this should be on pure JS and cross-browser as much as possible.
Part of this problem i solved myself, but i don't have enough knowledge of javascript or imagination to finish this and can't find any good examples of similar solutions at least partially.
constructor() {
this._options = {
pseudoElements: ['active', 'checked', 'disabled', 'empty', 'enabled', 'first-child', 'first-of-type', 'focus', 'hover', 'in-range', 'invalid', 'last-child', 'last-of-type', 'link', 'not(*)', 'nth-child(*)', 'nth-last-child(*)', 'only-of-type', 'only-child', 'optional', 'out-of-range', 'read-only', 'read-write', 'required', 'root', 'target', 'valid', 'visited', 'after', 'before']
}
}
_handleElmCss(domElm, newElm) {
// could not think any better solution then getting all CSS without pseudo then checking with pseudo the same Style object difference. I need as fast as possible way, because i am working with hundred of thousands elements.
var computedStyle = getComputedStyle(domElm);
for (var i = 0, len = this._options.pseudoElements.length; i < len; i++) {
var pseu_name = this._options.pseudoElements[i];
if (this._containsPseudo(domElm, ':' + pseu_name)) {
var differentParameters = this._getComputedDifference(pseu_name, computedStyle, domElm);
console.log(differentParameters);
}
};
}
_getComputedDifference(pseu_name, computed2, domElm) {
var computed1 = getComputedStyle(domElm, ':' + pseu_name);
var array1 = [], array2 = [];
// I belive there is a faster way to convert getComputedStyle to key-value array.
for (var i = 0; i < computed1.length; i++) {
var key = computed1[i];
var value = computed1.getPropertyValue(key);
if (key != "" && key != null) {
array1[i] = value; // i believe this part is incorrect, i mean array-key should be the "key" variable, but i get JS errors.
}
}
for (var i = 0; i < computed2.length; i++) {
var key = computed2[i];
var value = computed2.getPropertyValue(key);
if (key != "" && key != null) {
array2[i] = value; // i believe this part is incorrect, i mean array-key should be the "key" variable, but i get JS errors.
}
}
return array1.filter(val => !array2.includes(val));
}
_containsPseudo(node, selector) {
// this method works only with :empty, :hover and so on. :before and :after does not work.
var nativeMatches = (node.matches || node.msMatchesSelector);
try {
return(nativeMatches.call(node, selector));
} catch (error) {
return false;
}
}
This code is copied from my library and may contain some missing parts or type errors.
Originaly by this post title i need help with checking if any given element contains any pseudo class or not, but if someone knows solution to other my problems mentioned above, please free to comment. Thank you.
Parts that this script should do by my imagination(I may be wrong):
Upvotes: 6
Views: 9312
Reputation: 162
You can use getComputedStyle() (W3C Reference) with second param pseudoElt
to get it.
Check this example:
var el = document.querySelector('#elt'),
pseudo = window.getComputedStyle(el, ':before');
alert(pseudo.getPropertyValue("content"));
#elt:before {
content: "This element has pseudo class"
}
<div id="elt"></div>
EDIT
You may like to see this in action:(function from another so answer)
<style>
#elt {
color:red;
}
#elt2 {
color:blue;
}
#elt:before {
}
#elt2:first-child {
}
#elt2:after {
}
</style>
<div id="elt">#ELT1</div>
<div id="elt2">#ELT2</div>
<div id="container"></div>
<hr>
<script type="text/javascript">
function ruleSelector(selector) {
function uni(selector) {
return selector.replace(/::/g, ':')
}
return Array.prototype.filter.call(Array.prototype.concat.apply([], Array.prototype.map.call(document.styleSheets, function(x) {
return Array.prototype.slice.call(x.cssRules);
})), function(x) {
return uni(x.selectorText) === uni(selector);
});
}
lists = {pseudos: ['active', 'checked', 'disabled', 'empty', 'enabled', 'first-child', 'first-of-type', 'focus', 'hover', 'in-range', 'invalid', 'last-child', 'last-of-type', 'link', 'not(*)', 'nth-child(*)', 'nth-last-child(*)', 'only-of-type', 'only-child', 'optional', 'out-of-range', 'read-only', 'read-write', 'required', 'root', 'target', 'valid', 'visited', 'after', 'before']};
document.write("<h1>#elt</h1>");
for (var i = 0, len = lists.pseudos.length; i < len; i++) {
var pseudo = lists.pseudos[i];
if(ruleSelector("#elt:"+pseudo).length)
document.write("<strong>#elt has :"+pseudo+"</strong><br>");
else
document.write("<small>#elt hasn't :"+pseudo+"</small><br>");
}
document.write("<h1>#elt2</h1>");
for (var i = 0, len = lists.pseudos.length; i < len; i++) {
var pseudo = lists.pseudos[i];
if(ruleSelector("#elt2:"+pseudo).length)
document.write("<strong>#elt2 has :"+pseudo+"</strong><br>");
else
document.write("<small>#elt2 hasn't :"+pseudo+"</small><br>");
}
</script>
I've just adapted the code, as you can do too. Enjoy.
Upvotes: 4