jquery: Get full css property set as string from an element [duplicate] - javascript

Is there a way in jQuery to get all CSS from an existing element and apply it to another without listing them all?
I know it would work if they were a style attribute with attr(), but all of my styles are in an external style sheet.

A couple years late, but here is a solution that retrieves both inline styling and external styling:
function css(a) {
var sheets = document.styleSheets, o = {};
for (var i in sheets) {
var rules = sheets[i].rules || sheets[i].cssRules;
for (var r in rules) {
if (a.is(rules[r].selectorText)) {
o = $.extend(o, css2json(rules[r].style), css2json(a.attr('style')));
}
}
}
return o;
}
function css2json(css) {
var s = {};
if (!css) return s;
if (css instanceof CSSStyleDeclaration) {
for (var i in css) {
if ((css[i]).toLowerCase) {
s[(css[i]).toLowerCase()] = (css[css[i]]);
}
}
} else if (typeof css == "string") {
css = css.split("; ");
for (var i in css) {
var l = css[i].split(": ");
s[l[0].toLowerCase()] = (l[1]);
}
}
return s;
}
Pass a jQuery object into css() and it will return an object, which you can then plug back into jQuery's $().css(), ex:
var style = css($("#elementToGetAllCSS"));
$("#elementToPutStyleInto").css(style);
:)

Two years late, but I have the solution you're looking for. Not intending to take credit form the original author, here's a plugin which I found works exceptionally well for what you need, but gets all possible styles in all browsers, even IE.
Warning: This code generates a lot of output, and should be used sparingly. It not only copies all standard CSS properties, but also all vendor CSS properties for that browser.
jquery.getStyleObject.js:
/*
* getStyleObject Plugin for jQuery JavaScript Library
* From: http://upshots.org/?p=112
*/
(function($){
$.fn.getStyleObject = function(){
var dom = this.get(0);
var style;
var returns = {};
if(window.getComputedStyle){
var camelize = function(a,b){
return b.toUpperCase();
};
style = window.getComputedStyle(dom, null);
for(var i = 0, l = style.length; i < l; i++){
var prop = style[i];
var camel = prop.replace(/\-([a-z])/g, camelize);
var val = style.getPropertyValue(prop);
returns[camel] = val;
};
return returns;
};
if(style = dom.currentStyle){
for(var prop in style){
returns[prop] = style[prop];
};
return returns;
};
return this.css();
}
})(jQuery);
Basic usage is pretty simple, but he's written a function for that as well:
$.fn.copyCSS = function(source){
  var styles = $(source).getStyleObject();
  this.css(styles);
}

Why not use .style of the DOM element? It's an object which contains members such as width and backgroundColor.

I had tried many different solutions. This was the only one that worked for me in that it was able to pick up on styles applied at class level and at style as directly attributed on the element. So a font set at css file level and one as a style attribute; it returned the correct font.
It is simple! (Sorry, can't find where I originally found it)
//-- html object
var element = htmlObject; //e.g document.getElementById
//-- or jquery object
var element = htmlObject[0]; //e.g $(selector)
var stylearray = document.defaultView.getComputedStyle(element, null);
var font = stylearray["font-family"]
Alternatively you can list all the style by cycling through the array
for (var key in stylearray) {
console.log(key + ': ' + stylearray[key];
}

#marknadal's solution wasn't grabbing hyphenated properties for me (e.g. max-width), but changing the first for loop in css2json() made it work, and I suspect performs fewer iterations:
for (var i = 0; i < css.length; i += 1) {
s[css[i]] = css.getPropertyValue(css[i]);
}
Loops via length rather than in, retrieves via getPropertyValue() rather than toLowerCase().

Related

Using Native JavaScript, change the title attribute of an object if it has a certain CSS class

So by using native javascript, how would I go about saying
"if this object has this css class, add this to the title attribute"
document.addEventListener("DOMContentLoaded", function(event) {
if(element.classlist.contains("current_page_item")||element.classlist.contains("current-page-ancestor")){
}
});
That is as far as I've gotten, I'm trying to stick to native javascript just so we don't have to load up any libraries and can keep the site as minimalist as possible.
You can use getElementsByClassName()
var x = document.getElementsByClassName("current_page_item");
Then loop and add title
x.forEach(function(element){
element.title = "title";
});
or
for (var i = 0; i < x.length; i++) {
x[i].title ="title";
}
To answer to your comment, to apply the title to the "a" element that is a child of the div element that has the "current_page_item" class
for (var i = 0; i < x.length; i++) {
var y = x[i].getElementsByTagName("a");
y[0].title = "title";
}
Similar to Rohit Shetty's reply, you could also use the querySelector:
let elements = document.querySelector(".current_page_item");
elements.forEach(function(e) {
e.title = "title";
);
You can use getElementsByClassName()
var x = document.getElementsByClassName("current_page_item");
for(var i=0;i<x.length;i++){
x[i].title += "BLAH";
}
I don't now if I have understood well.
But let's try.
First, locate the elements.
const nodes = document.querySelectorAll('.current_page_item, .current_page_item')
// nodes are the elements of one of the classes names
Then, apply the class Names to title.
function containsOfTheClasses (node) {
return classNames.some(x => node.classList.contains(x))
}
nodes.forEach(function (node) {
node.title += classNames.filter(containsOfTheClasses).join(' ')
})

How to get a ALL the css properties set on an element with jquery [duplicate]

Is there a way in jQuery to get all CSS from an existing element and apply it to another without listing them all?
I know it would work if they were a style attribute with attr(), but all of my styles are in an external style sheet.
A couple years late, but here is a solution that retrieves both inline styling and external styling:
function css(a) {
var sheets = document.styleSheets, o = {};
for (var i in sheets) {
var rules = sheets[i].rules || sheets[i].cssRules;
for (var r in rules) {
if (a.is(rules[r].selectorText)) {
o = $.extend(o, css2json(rules[r].style), css2json(a.attr('style')));
}
}
}
return o;
}
function css2json(css) {
var s = {};
if (!css) return s;
if (css instanceof CSSStyleDeclaration) {
for (var i in css) {
if ((css[i]).toLowerCase) {
s[(css[i]).toLowerCase()] = (css[css[i]]);
}
}
} else if (typeof css == "string") {
css = css.split("; ");
for (var i in css) {
var l = css[i].split(": ");
s[l[0].toLowerCase()] = (l[1]);
}
}
return s;
}
Pass a jQuery object into css() and it will return an object, which you can then plug back into jQuery's $().css(), ex:
var style = css($("#elementToGetAllCSS"));
$("#elementToPutStyleInto").css(style);
:)
Two years late, but I have the solution you're looking for. Not intending to take credit form the original author, here's a plugin which I found works exceptionally well for what you need, but gets all possible styles in all browsers, even IE.
Warning: This code generates a lot of output, and should be used sparingly. It not only copies all standard CSS properties, but also all vendor CSS properties for that browser.
jquery.getStyleObject.js:
/*
* getStyleObject Plugin for jQuery JavaScript Library
* From: http://upshots.org/?p=112
*/
(function($){
$.fn.getStyleObject = function(){
var dom = this.get(0);
var style;
var returns = {};
if(window.getComputedStyle){
var camelize = function(a,b){
return b.toUpperCase();
};
style = window.getComputedStyle(dom, null);
for(var i = 0, l = style.length; i < l; i++){
var prop = style[i];
var camel = prop.replace(/\-([a-z])/g, camelize);
var val = style.getPropertyValue(prop);
returns[camel] = val;
};
return returns;
};
if(style = dom.currentStyle){
for(var prop in style){
returns[prop] = style[prop];
};
return returns;
};
return this.css();
}
})(jQuery);
Basic usage is pretty simple, but he's written a function for that as well:
$.fn.copyCSS = function(source){
  var styles = $(source).getStyleObject();
  this.css(styles);
}
Why not use .style of the DOM element? It's an object which contains members such as width and backgroundColor.
I had tried many different solutions. This was the only one that worked for me in that it was able to pick up on styles applied at class level and at style as directly attributed on the element. So a font set at css file level and one as a style attribute; it returned the correct font.
It is simple! (Sorry, can't find where I originally found it)
//-- html object
var element = htmlObject; //e.g document.getElementById
//-- or jquery object
var element = htmlObject[0]; //e.g $(selector)
var stylearray = document.defaultView.getComputedStyle(element, null);
var font = stylearray["font-family"]
Alternatively you can list all the style by cycling through the array
for (var key in stylearray) {
console.log(key + ': ' + stylearray[key];
}
#marknadal's solution wasn't grabbing hyphenated properties for me (e.g. max-width), but changing the first for loop in css2json() made it work, and I suspect performs fewer iterations:
for (var i = 0; i < css.length; i += 1) {
s[css[i]] = css.getPropertyValue(css[i]);
}
Loops via length rather than in, retrieves via getPropertyValue() rather than toLowerCase().

Getting the names of all classes / ids contained within a css file?

Is there a way, or a tool, which can be used to get a list of the names of all the classes / ids contained within a css file?
I need to build an xml mapping of all css classes / ids, and doing it manually is very tedious for css files that contain thousands of styles.
Include your css file into any html file.
In console execute the following code:
Array.prototype.forEach.call(document.styleSheets[0].cssRules,function(a){console.log(a.selectorText)})
In the console will be the listing of all css tags used in your stylesheet.
You can iterate over document.styleSheets to get each style sheet, then iterate over the rules to find everything that matches a class or ID selector. The following is a simplistic approach that provides a general approach, the regular expressions to get the classes and IDs from the rules needs more work.
function getClassesAndIds() {
var sheet, sheets = document.styleSheets;
var rule, rules;
var classes = [];
var ids = [];
var temp;
for (var i=0, iLen=sheets.length; i<iLen; i++) {
sheet = sheets[i];
rules = sheet.rules;
for (var j=0, jLen=rules.length; j<jLen; j++) {
rule = rules[j];
// Get the classes
temp = rule.cssText.match(/\.\w+/g);
if (temp) {
classes.push.apply(classes, temp);
}
// Get the IDs
temp = rule.cssText.match(/\#\w+/g);
if (temp) {
ids.push.apply(ids, temp);
}
}
}
// Return an array of the class and ID arrays
return [classes,ids];
// or as an object
// return {classes:classes, ids:ids};
}
window.onload = function() {
console.log(getClassesAndIds());
};
From memory there were some quirks in older IE around sheets and rules but right now it evades me…
See my working example here :)
https://codepen.io/pixelfast/pen/rNrovmj
<script>
function getEm() {
url = document.getElementById("url").value;
fetch(url)
.then((response) => response.text())
.then((data) => {
var cssText = data;
var classRegex = /\.([\w-]+)/g;
var idRegex = /#([\w-]+)/g;
var classes = [];
var ids = [];
var match;
while ((match = classRegex.exec(cssText)) !== null) {
classes.push(match[1]);
}
while ((match = idRegex.exec(cssText)) !== null) {
ids.push(match[1]);
}
console.log("Classes: " + classes);
console.log("IDs: " + ids);
document.getElementById("classes").innerHTML = classes + "<hr>";
document.getElementById("ids").innerHTML = ids;
});
}
</script>
<!-- HTML -->
<input style="width:400px" type="text" id="url" value="https://getbootstrap.com/docs/5.3/assets/css/docs.css">
<button onclick="getEm()">Get Em</button>
<hr>
<div id="classes"></div>
<div id="ids"></div>
In my case, i need all class names (there are selectors which is start with ".icon-" ) in icons.css for listing all defined font icons.
const {cssRules} = Object.values(document.styleSheets)
.find(sheet =>
Object.values(sheet.cssRules).find(rule =>
(rule.selectorText || '').match(/^.icon/)
)
) || {cssRules: {}}
console.log(Object.values(cssRules).map(i => i.selectorText))

Finding All CSS Rules (including "invalid rules") Via Javascript

I am trying to use document.styleSheets to add a shim for CSS calc functionality.
Basically I am looping over each stylesheet and it's subsequent rules and looking for calc to occur somewhere, and doing the calculation in JavaScript and applying it to the associated element.
This is MUCH faster than looping over every element on the page and trying to find if it has a failed calc rule, but the problem is I do not see a way to pull in errored CSS rules through this method. Both rules and cssRules arrays contain only CSS that the browsers considers valid.
My question is this, is there a way to get these invalid CSS values through this method?
The code I am using is below, and works, but only on browsers that support calc anyways, which is useless to me. I need to be able to get ALL of the css rules as they appeared in the loaded CSS document in order to make this work.
Is this possible or am I barking up an imaginary fantasy tree of cross-browser calc awesomeness?
calcShim = function(){
var stylesheets = document.styleSheets;
var calcs = [];
for (var i=0, j=stylesheets.length; i<j; i++){
var stylesheet = stylesheets[i];
var rules = stylesheet.cssRules;
if (rules && rules.length > 0){
for (var k=0, l=rules.length; k<l; k++){
var rule = rules[k];
var ruleText = String(rule.cssText);
if (ruleText.match("calc")){
calcs.push(ruleText);
};
};
}
};
for (var i=0, j=calcs.length; i<j; i++){
var string = calcs[i];
var reference = calcs[i].match(/^[^{]{1,}/g)[0];
var objects = $(reference);
for (var k=0, l=objects.length; k<l; k++){
var object = $(objects[k]);
var parent = object.parent();
if (parent.is(":visible")){
var parentWidth = parseInt(parent.width());
var percent = parseInt(string.match(/(?:calc\()([0-9]{1,3})(?=%)/)[1])/100;
var operator = string.match(/(?:calc[^)]{1,})([\+\-\*\/])(?=\s[0-9]{1,3}px)/)[1];
var value = parseInt(string.match(/(?:calc[^)]{1,}[\+\-\*\/]\s)([0-9]{1,3})(?=px)/)[1]);
var mathString = (parentWidth*percent) + " " + operator + " " + value;
var result = eval(mathString);
object.css({"width": result});
}
};
};
};
I am aware this code could be better/cleaner, I was just trying to come up with a proof of concept.

jquery remove based on before content

Is it possible to write a JQuery function that will remove everything with a specific :before content.
here is an example statement to give you something to show me with code:
remove all elements in the document that have a :before pseudo element with content set to "delete me"
Mhh, you can try something like this:
var sheets = document.styleSheets;
var len = sheets.length;
var ba = /:before|:after/;
// Loop throught all stylesheets
for (var i = 0; i < len; i++) {
// work out which method to get the CSS rules
var sheet = sheets[i],
rules = sheet.cssRules || sheet.rules;
// Loop through all rules
for (var r = 0, rule; rule = rules[r++];) {
// if this rule uses one of the test selectors
if (rule.selectorText.match(ba)) {
if (rule.style.content.indexOf('delete me') !== -1) {
var elems = document.querySelectorAll(rule.selectorText.split(':')[0]);
for (var e = 0, elem; elem = elems[e++];) {
// remove the node
document.body.removeChild(elem);
}
}
}
}
}
http://fiddle.jshell.net/6m5kB/1/
there is simple answer just add class on that element with before and remove it through that class. pseudo-element does not exist in dom that why you cannot directly remove them through jquery or js

Categories

Resources