How to set all computed styles as literal styles on an element? - javascript

This question is similar (I think) to this question on SO: How to move all computed CSS styles from one element and apply them to a different element using JavaScript?
What I want to do is find all styles that have been applied by way of css sheets and set the explicitly (as in using a style= attribute) on the element. The reason I want to do this is so that MS Word (2010) will pick up the styling if I open it there
Here's my code
var $this = $(this);
var styles = window.getComputedStyle(this, null);
$this.css(styles);
I also tried with
var styles = document.defaultView.getComputedStyle(this, null);
When I put a try catch around the last line ($this.css(styles), I am getting an error message "invalid calling object". I don't understand what the problem is

Well, the following snippet does what you want, though I don't think it's what you needed. MS Word is NOT a browser, I'm not sure if it supports all the styles or if jQuery works there...
var $this = $('b');
var styles = window.getComputedStyle($this[0]);
$this.css(
Object.values(styles).reduce(
(a, e) => 0*(a[e] = styles[e]) || a, {}
)
)
console.log(`style="${$this.attr('style')}"`)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<b>I have styles</b>

Related

Find all divs/elements with background image containing URL and remove text

I read this Replacing background image using jQuery not working and quite a few other things but I'm having issues with this one.
I'm trying to find all divs/elements that contain a background-image: url();. IF they contain a background image with https://website.com/imagepath/image.jpg I want to remove the "https://website.com" piece and leave it as a local url only i.e. "/imagepath/image.jpg"
I'd like to do this in pure JS but I'm not opposed to jQuery
This would be incredibly taxing on performance and I would not recommend doing it this way.
You would have to go through every single element on the page and check its computed style and then update that if it matches your provided string.
const searchStr = 'https://website.com/imagepath/image.jpg';
const replaceStr = 'https://website.com/newimage.jpg';
const body = document.getElementsByTagName('body')[0];
const elements = Array.from(body.getElementsByTagName('*'));
elements.map(element => {
const style = window.getComputedStyle(element);
if (!!style.backgroundImage.includes(searchStr)) {
element.style.backgroundImage = replaceStr;
}
});

Converty jQuery closest to ES6 to add CSS for bg

Objective
Get the url of each image and add that as a background to it's parent article, in a vuejs project
Question
How should I refactor the code originally written in jQuery?
JS - original from other author
$(".polaroid").wrap("<div class='polaroid-frame'><div class='polaroid-image'>");
$(".polaroid").each(function() {
var $this = $(this);
var imgLink = $this.attr("src");
var bg = "url("+imgLink+")";
$this.closest(".polaroid-image").css({
"background-image": bg
});
});
JS - refactored for my project
$(".polaroid article img").each(function() {
var $this = $(this);
var imgLink = $this.attr("src");
var bg = "url("+imgLink+")";
$this.closest("article").css({
"background-image": bg
});
});
My demo on codepen
Background
I am taking code from another project but it was written in jQuery. I don't want to use jQuery, instead i just need to write this in ES6, or just plain javascript.
I so far found one related question, Finding closest element without jQuery , but it was too different to be able to make much use of it.
I looked at the mozilla documentation https://developer.mozilla.org/en-US/docs/Web/API/Element/closest , which leads me to think my code should translate to
el.closest("article");
but then how would I wrap that in a way that would pass the CSS values. I looked up documentation from w3 https://www.w3schools.com/js/js_htmldom_css.asp and found this example
document.getElementById("p2").style.color = "blue";
So I think I should do
document.[unclear what to do here].style.background-image = /* what goes here for the variable? */;
From your refactored JS, to translate it into plain JS, you need to
(1) Iterate over the selected elements (can be done easily with querySelectorAll)
(2) Get the element's src attribute
(3) Set the closest article's background-image to that src
So, it should be pretty simple:
document.querySelectorAll('.polaroid article img').forEach((img) => {
const { src } = img;
img.closest('article').style.backgroundImage = `url(${src})`;
});
Note that when setting style properties directly, sometimes the CSS string you'd want to use (eg. background-image) wouldn't be valid syntax in Javascript. In these cases, generally turn the words-separated-by-dashes into camelCase. (backgroundImage)

Get all elements with `position:fixed` in an HTML page?

Reason for doing that: I'm debugging css of my webpage.. some elements appeared and they're not supposed to appear. I suspect it is the issue with element positioning.. therefore I want to find these positioned element and check one by one.
This one is using jQuery. I hope you are find with it.
var find = $('*').filter(function () {
return $(this).css('position') == 'fixed';
});
I think this one works using a pure javascript:
var elems = document.body.getElementsByTagName("*");
var len = elems.length
for (var i=0;i<len;i++) {
if (window.getComputedStyle(elems[i],null).getPropertyValue('position') == 'fixed') {
console.log(elems[i])
}
}
Here is an ES6 version that gives you an array of these elements for further processing:
let fixedElements = [...document.body.getElementsByTagName("*")].filter(
x => getComputedStyle(x, null).getPropertyValue("position") === "fixed"
);
document.querySelector('*[style="position:fixed"]')
The * item specifies all tag names. The [] indicate that you're looking for an attribute. You want your style attribute to have position:fixed.
If you aren't using jQuery, this is probably going to be your simplest option.
Warnings that apply to all answers:
This is a slow operation. On a large-enough page, this operation can take 100ms or more, which is a lot for a single operation. You shouldn't need this unless you're developing a browser extension.
Now sticky elements can act as fixed elements in some cases
Having said that, here's the shortest and most efficient version to do this:
const fixed = [].filter.call(document.all, e => getComputedStyle(e).position == 'fixed');
Here's a version that includes sticky elements, but they're not exactly equivalent, it depends on what you're looking for:
const all = [].filter.call(
document.all,
e => ['fixed', 'sticky'].includes(getComputedStyle(e).position)
);
If you're feeling modern, replace document.all with document.querySelectorAll('*'), but the former will likely work forever.
Try this:
var elements = $('*').filter(function () {
return this.style.position == 'fixed';
});
It will give you all elements having position fixed.

Programatically create new CSS rules in a stylesheet

For creating new CSS rules in a stylesheet, as of now, I only know .insertRule() (excluding the non-standard ways).
Are there any other ways of creating more CSS rules? Something, for example:
Warning: this is not standard, it is just an example to display the intent
var rule = new CSSStyleRule();
rule.selectorText = '.selector';
rule.style.display = 'block';
rule.style.color = 'red';
ruleSet.append(rule);
Anything like or somewhat like the above works as an answer. Instead of new, it may be document.createCssRule() or stylesheet.createCssRule()...
I just this it would be useful for a piece of software I'm developing which left me if there's a programatically way of modifying values in such interface where to add new stuff is not restricted to a parsed string.
Do not worry about IE9 and below when answering, please.
Note: (to unclose) This is not about how to find and modify current CSS rules, this is about making new ones without using the text parser which is what .insertRule() is without building a complete CSS string like .insertRule() requires.
You can add an empty rule, get it, and modify it:
function appendRule(sheet) {
var len = sheet.cssRules.length;
sheet.insertRule('*{}', len);
return sheet.cssRules[len];
}
var rule = appendRule(document.styleSheets[0]);
rule.selectorText = '.selector';
rule.style.display = 'block';
rule.style.color = 'red';
<span class="selector">I should become red.</span>
<span>I should be at the next line and not become red.</span>
However, modifying selectorText does not seem to work on Firefox.
You could append a new style element to your head and just append rules to it:
function addStyle(newRules){
if(document.getElementById("jsAddedRules")){
document.getElementById("jsAddedRules").innerHTML+=newRules;
}else{
var style=document.createElement("style");
style.setAttribure("id","jsAddedRules");
style.innerHTML=newRules;
document.getElementsByTagName("head")[0].appendChild(style);
}
}
And then just call your function when you want to add rules:
addStyle(
".selector{\
display:block;\
color:red;\
}"
);

how to remove css property using javascript?

is it possible to remove a CSS property of an element using JavaScript ?
e.g. I have div.style.zoom = 1.2,
now i want to remove the zoom property through JavaScript ?
You have two options:
OPTION 1:
You can use removeProperty method. It will remove a style from an element.
el.style.removeProperty('zoom');
OPTION 2:
You can set it to the default value:
el.style.zoom = "";
The effective zoom will now be whatever follows from the definitions set in the stylesheets (through link and style tags). So this syntax will only modify the local style of this element.
removeProperty will remove a style from an element.
Example:
div.style.removeProperty('zoom');
MDN documentation page:
CSSStyleDeclaration.removeProperty
div.style.removeProperty('zoom');
element.style.height = null;
output:
<div style="height:100px;">
// results:
<div style="">
You can use the styleSheets object:
document.styleSheets[0].cssRules[0].style.removeProperty("zoom");
Caveat #1: You have to know the index of your stylesheet and the index of your rule.
Caveat #2: This object is implemented inconsistently by the browsers; what works in one may not work in the others.
You can try finding all elements that have this class and setting the "zoom" property to "nothing".
If you are using jQuery javascript library, you can do it with $(".the_required_class").css("zoom","")
Edit: Removed this statement as it turned out to not be true, as pointed out in a comment and other answers it has indeed been possible since 2010.
False: there is no generally known way for modifying stylesheets from JavaScript.
You can also do this in jQuery by saying $(selector).css("zoom", "")
This should do the trick - setting the inline style to normal for zoom:
$('div').attr("style", "zoom:normal;");
actually, if you already know the property, this will do it...
for example:
var txt = "";
txt = getStyle(InterTabLink);
setStyle(InterTabLink, txt.replace("zoom\:1\.2\;","");
function setStyle(element, styleText){
if(element.style.setAttribute)
element.style.setAttribute("cssText", styleText );
else
element.setAttribute("style", styleText );
}
/* getStyle function */
function getStyle(element){
var styleText = element.getAttribute('style');
if(styleText == null)
return "";
if (typeof styleText == 'string') // !IE
return styleText;
else // IE
return styleText.cssText;
}
Note that this only works for inline styles... not styles you've specified through a class or something like that...
Other note: you may have to escape some characters in that replace statement, but you get the idea.
To change all classes for an element:
document.getElementById("ElementID").className = "CssClass";
To add an additional class to an element:
document.getElementById("ElementID").className += " CssClass";
To check if a class is already applied to an element:
if ( document.getElementById("ElementID").className.match(/(?:^|\s)CssClass(?!\S)/) )

Categories