CSS style to inline style via JavaScript - javascript

I want to add all CSS styles of a specific element to its inline style attribute. For example:
I have:
<div id="d"></div>
and:
#d { background: #444444; width: 50px; height: 20px; display: inline-block; }
Now I want a JavaScript function that turns my div into this:
<div id="d" style="background: #444444; width: 50px; height: 20px; display: inline-block;"></div>
Please help me. And, by the way, I don't want any CSS styles to re-write any existing inline style.

You can do something like this:
function applyStyle(el) {
s = getComputedStyle(el);
for (let key in s) {
let prop = key.replace(/\-([a-z])/g, v => v[1].toUpperCase());
el.style[prop] = s[key];
}
}
let x = document.getElementById('my-id');
applyStyle(x);
Where x is the element you want to apply the style to.
Basically this function gets the computed style of the element and then copies each property (like padding, background, color, etc.) to the inline style of the element.
I don't know why you need to do this, but it's a really dirty approach in my opinion. I would personally advise against it.

It appears this library will do what you're looking for: https://github.com/lukehorvat/computed-style-to-inline-style
Convert a HTML element's computed CSS to inline CSS.
Uses Window.getComputedStyle internally.

This one?
function transferComputedStyle(node) {
var cs = getComputedStyle(node, null);
var i;
for (i = 0; i < cs.length; i++) {
var s = cs[i] + "";
node.style[s] = cs[s];
}
}
function transferAll() {
var all = document.getElementsByTagName("*");
var i;
for (i = 0; i < all.length; i++) {
transferComputedStyle(all[i]);
}
}
Simply call transferAll onload, or whereever.

I think the issue with the accepted answer (thank you for that!) is that one of the properties it tries to transfer on the element style from the Computed Style is the cssText.
If we exclude from the transfer cssText and also other properties that are actually methods, it works!
So building on the accepted answer and this answer, I've got:
var el = document.querySelector("#answer-25097808 > div > div.answercell.post-layout--right > div.s-prose.js-post-body > pre"); // change yourId to id of your element, or you can write “body” and it will convert all document
var els = el.getElementsByTagName("*");
for(var i = -1, l = els.length; ++i < l;){
el = els[i]
s = getComputedStyle(el)
for (let styleKey in el.style) {
for (let computedStyleKey in s) {
let computedStyleKeyCamelCase = computedStyleKey.replace(/\-([a-z])/g, v => v[1].toUpperCase());
if ((typeof el.style[styleKey] != "function") && (styleKey != 'cssText')){
if(styleKey == computedStyleKeyCamelCase) {
el.style[styleKey] = s[computedStyleKey];
}
}
}
}
}
P.S.: the above code should run in the Developer Tools console (tried it in Chrome)

Using jQuery it can be done easily. Here is the sample code:
If you are new in jQuery and you don't know how to add and work then follow this link
$(document).ready(function(){
$("#d").css('background-color', '#444444').css('width', '50px').css('height', '20px').css('display', 'inline-block');
});
For javascript code I am not confident but for jQuery I am sure that it will work.
Correct me if I am wrong.

Related

Updating Inline Styling with removeAttribute() and setAttribute() not updating

Updated inline styling of a certain paragraph tag is not displaying new updates.
I am using the following example that I found on Stack overflow:
var para = document.getElementsByTagName('div');
var len = para.length;
for (var i = 0; i < len; ++i) {
if(para[i].innerHTML.indexOf("SOME TEST") !== -1) {
para[i].removeAttribute('style');
para[i].setAttribute('style', 'FONT-SIZE: 100px !important; FONT-FAMILY: Arial !important; color:red;');
}
}
When I look at the inspector tool, I am able to see the styling I implemented. However, the styling is not taking place.
What am I doing wrong? I am trying to make this work for IE8 and below
You need to use an alternative for old versions of IE, which neither support using setAttribute() to set styles nor event handlers. This also works in other browsers too:
var para = document.getElementsByTagName('div');
var len = para.length;
for (var i = 0; i < len; ++i) {
if(para[i].innerHTML.indexOf("SOME TEST") !== -1) {
para[i].style.cssText = 'FONT-SIZE: 100px !important; FONT-FAMILY: Arial !important; color:red;';
}
}
On the other hand, I agree with the suggestion others have made that class switching is better when you're not using JS to calculate a value dynamically.
A better approach for styling an element using attributes, would be using custom element attributes and specific CSS rules for those attributes.
Note : If you want to pass HTML validations, your attribute names must be prefixed with 'data-'. They should also not contain any uppercase letters.
In the following example, you will see how the styles declared with the [data-myAttribute] CSS selector are applied when the attribute is set to the element :
var myElement = document.getElementById('myElement');
// click event handler compatible with IE8
myElement.onclick = function clickHandler(e){
// toggle the 'data-myAttribute' attribute
if( myElement.hasAttribute('data-myAttribute') ){
myElement.removeAttribute('data-myAttribute');
}else{
myElement.setAttribute('data-myAttribute', true);
}
}
[data-myAttribute]{
text-decoration : underline;
color : red;
}
<div id="myElement">click me</div>

Javascript way to locate all elements with margin: auto

I'm looking for an easy way to locate elements on the page that have margin-left and margin-right set to auto.
I got this script, that helps me some of the time:
(function() {
var elementsList = [];
for (var i = 0; i < document.styleSheets.length; i++) {
var styleSheet = document.styleSheets[i];
if (styleSheet.rules) {
for (var j = 0; j < styleSheet.rules.length; j++) {
var rule = styleSheet.rules[j];
if (rule && rule.style && rule.style.marginLeft == 'auto' && rule.style.marginRight == 'auto') {
var smallList = document.querySelectorAll(rule.selectorText);
if (smallList.length)
elementsList = elementsList.concat(smallList);
}
}
}
}
return elementsList
})();
While this function gets some of the job done, it doesn't catch most cases of margin: auto I've seen in websites.
Can you show me a better way?
If you're OK to use JQuery
As said by Martin Ernst for yonatan's answer: 'This will select only elements with marginLeft/Right="auto".'
Besides, as described in the comments, elements must be hidden in order to work with FF and safari.
This should work using JQuery:
$(document).ready(function() {
var visibleElements = $('body *:visible');
$('body *').hide();
var elements = $('body *').filter(function() {
return $(this).css('margin-left') == 'auto' && $(this).css('margin-right') == 'auto';
})
// show only elements that were visible
visibleElements.show();
});
Tip: if for some reason, you need to not load external scripts, just copy the content of the minified jquery script at the begining of yours.
use jQuery:
$('*').filter(function(i, d){return d.style.marginLeft == "auto" && d.style.marginRight == 'auto';});
I hate to say this, but this one has less success then my own version.
This problem is not trivial. Even in the days of window.getComputedStyle() it's hard to get a crossbrowser reliable answer for marginLeft/Right when margins are set to auto. So this is shurely not a complete answer but will try helping to find one.
margin-left and margin-right are also auto when the margin-shorthand is used:
#elem {margin: auto;} // or:
#elem {margin: 100px auto;} // or:
#elem {margin: 100px auto 30px;} // or:
#elem {margin: 100px auto 30px auto;}
You have to find those notations too when you are searching in the stylesheets. Include this function just before var elementsList=[]; in your code:
function expand(margin) {
var parts = margin.split(' ');
for (var i = 3; i; i--) parts[i] = parts[i] || parts[i - 2] || parts[0];
return parts[1] == 'auto' && parts[3] == 'auto';
}
Then change your inner if-condition to:
if (rule && rule.style &&
(rule.style.marginLeft == 'auto' && rule.style.marginRight == 'auto' || expand(rule.style.margin))
) {
var smallList = document.querySelectorAll(rule.selectorText);
if (smallList.length) elementsList = elementsList.concat(smallList);
}
Now you get also the rules where margin is used. But some problems stay with your code:
Same elements may be listed multiple times when they match more than one rule
It's not shure that all listet elements are really rendered with marginLeft/Right = auto. Maybe that css becomes overridden by another more specific rule.
As dfsq mentioned in his comment there can be inline-styles you can't find this way.

IE9 get hover color javascript [duplicate]

I made a function that overwrite the the :hover of some elements on a page. It fades between the normal and the :hover effect. That for i had to create a .hover class in my CSS file. I think this is a little unclean. How could i read the the :hover pseudo class contents?
Using getComputedStyle as on the accepted answer won't work, because:
The computed style for the hover state is only available when the element is actually on that state.
The second parameter to getComputedStyle should be empty or a pseudo-element. It doesn't work with :hover because it's a pseudo-class.
Here is an alternative solution:
function getCssPropertyForRule(rule, prop) {
var sheets = document.styleSheets;
var slen = sheets.length;
for(var i=0; i<slen; i++) {
var rules = document.styleSheets[i].cssRules;
var rlen = rules.length;
for(var j=0; j<rlen; j++) {
if(rules[j].selectorText == rule) {
return rules[j].style[prop];
}
}
}
}
// Get the "color" value defined on a "div:hover" rule,
// and output it to the console
console.log(getCssPropertyForRule('div:hover', 'color'));
Demo
You could access document.styleSheets and look for a rule that is applied on that specific element. But that’s not any cleaner than using a simple additional class.
UPDATE: I somehow got this wrong. The below example doesn't work. See #bfavaretto's comment for an explanation.
In Firefox, Opera and Chrome or any other browser that correctly implements window.getComputedStyle is very simple. You just have to pass "hover" as the second argument:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style type="text/css">
div {
display: block;
width: 200px;
height: 200px;
background: red;
}
div:hover {
background: green;
}
</style>
</head>
<body>
<div></div>
<script type="text/javascript">
window.onload = function () {
var div = document.getElementsByTagName("div")[0];
var style = window.getComputedStyle(div, "hover");
alert(style.backgroundColor);
};
</script>
</body>
</html>
But I don't believe there's yet a solution for Internet Explorer, except for using document.styleSheets as Gumbo suggested. But there will be differences. So, having a .hover class is the best solution so far. Not unclean at all.
If there are any people here who use the questions accepted answer but it won't work, here's a nice function that might:
function getPseudoStyle(id, style) {
var all = document.getElementsByTagName("*");
for (var i=0, max=all.length; i < max; i++) {
var targetrule = "";
if (all[i].id === id) {
if(all[i].selectorText.toLowerCase()== id + ":" + style) { //example. find "a:hover" rule
targetrule=myrules[i]
}
}
return targetrule;
}
}
There is an alterantive way to get :hover pseudo class with javascript. You can write your styles of hover pseudo class in a content property.
p::before,
p::after{
content: 'background-color: blue; color:blue; font-size: 14px;';
}
then read from it via getComputedStyle() method:
console.log(getComputedStyle(document.querySelector('p'),':before').getPropertyValue('content'));

Show hide multiple tables

I was wondering if someone could help me out with a command;
If have the following script:
<script type="text/javascript">
function show_table(id){
document.getElementById('table1').style.display='none';
document.getElementById('table2').style.display='none';
document.getElementById('table3').style.display='none';
document.getElementById('table4').style.display='none';
document.getElementById('table6').style.display='none';
document.getElementById('table'+id).style.display='block';
}
</script>
And it shows the tables just fine that I have, but now I want to use a command to open two tables at the same time, so with one click on the below reference link;
Table6
Is it possible to use it with a double onclick="" command? I would like to open as example table(6) and table(2). What should I write? By the way I can only use javascript, no PHP.
I tried something like this, but is does not do the job
Table6 and Table2
Try this version, which can take a number or an array:
function show_table(id) {
var ix;
for (ix = 1; ix <= 6; ++ix) {
document.getElementById('table' + ix).style.display='none';
}
if (typeof id === "number") {
document.getElementById('table'+id).style.display='block';
} else if (id && id.length) {
for (ix = 0; ix < id.length; ++ix) {
document.getElementById('table'+ix).style.display='block';
}
}
}
Then you can say show_table([1, 2]) instead of just show_table(1).
function show_table(ids) {
var idArr = ids.split(",");
document.getElementById('table1').style.display='none';
document.getElementById('table2').style.display='none';
document.getElementById('table3').style.display='none';
document.getElementById('table4').style.display='none';
document.getElementById('table6').style.display='none';
for(var i = 0; i< idArr.length; i++) {
document.getElementById('table'+idArr[i]).style.display='block';
}
}
<a href="#" onclick="show_table('6,2')">
If you prefer minimum force aproach, try this:
function hide_all_tables(){
document.getElementById('table1').style.display='none';
document.getElementById('table2').style.display='none';
document.getElementById('table3').style.display='none';
document.getElementById('table4').style.display='none';
document.getElementById('table6').style.display='none';
}
function show_table(id){
document.getElementById('table'+id).style.display='block';
}
And then use the code this way:
Table6 and Table2
I have never used a 'double onclick command' and to be honest don't think they work, or are good practice. Why don't you just house both show table comands in a javascript function and call the function onclick?
If i am understanding you correctly.
You can change them all at once without looping, if the tables have logical associations (they must, right?).
The idea is to assign them a class (or multiple classes) and change the whole class at once:
<script>
function f(classname, show)
{
var mysheet=document.styleSheets[0];
/* Each class in the styleSheet is called a 'rule' */
var myrules=mysheet.cssRules;
var value = show ? '' : 'none'; /* show or hide? */
for (i=0; i<myrules.length; i++){
/* find the class we want to change */
if(myrules[i].selectorText==classname){
/* change the rule */
myrules[i].style.display = value;
}
}
}
</script>
<style type="text/css" >
.hasPets { color: green; display: none; }
.hasCats { font-weight: bold; display: none; }
</style>
​<button onclick="f('.hasPets', true)">Show Pets</button>
​<button onclick="f('.hasCats', true)">Show Cats</button>
​<button onclick="f('.hasPets', false)">Hide Pets</button>
​<button onclick="f('.hasCats', false)">Hide Cats</button>
<div class="hasPets">Pets</div>
<div class="hasCats hasPets">Cats</div>
In this example, Show Pets shows both, Hide Cats hides only Cats. You can't show only Cats -- Pets overrides it.
Note: I've kept this short for clarity. In practice you'll have to add a few more lines because not all versions of IE support the .cssRules property, I think they called it .rules.
This function allows for any number of tables to show.
function show_table(){
for(var i = 1; i < 7; i++) // change 7 to the amount of tables
if(document.getElementById('table'+i))
document.getElementById('table'+i).style.display='none';
for (var i = 0; i < arguments.length; i++)
if(document.getElementById('table'+arguments[i]))
document.getElementById('table'+arguments[i]).style.display='block';
}
To show tables with ids of table3 and table5 then:
show_table(3,5);

changing CSS class definition

Suppose I have this class:
.MyClass{background:red;}
This class applies to several divs. I want to change the color of the background to orange by changing the color defined in MyClass.
Now, I know I could do $('.MyDiv').css('background', 'orange');
But my question is really this: how do I change the CSS class definition so that MyClass elements now have background:orange;? I want to be able to change several CSS color properties from one color to another.
Thanks.
Actually altering your stylesheet is pretty challenging. Much more easily, though, you can switch out your stylesheet for a different one, which may be sufficient for your purposes. See How do I switch my CSS stylesheet using jQuery?.
For actually altering the stylesheet content, How to change/remove CSS classes definitions at runtime? will get you started.
It is difficult to find the rule you want because you have to iterate through the document.styleSheets[i].cssRules array. (and compare your class name with the selectorText attribute)
So my solution to this problem is to add a new CSS class, remove the old CSS class from the HTML element and add this class instead of it.
var length = getCssRuleLength();
var newClassName = "css-class-name" + length;
//remove preview css class from html element.
$("#your-html-element").removeClass("css-class-name");
$("#your-html-element").removeClass("css-class-name" + (length-1));
$("#your-html-element").addClass(newClassName);
//insert a css class
insertCssRule("." + newClassName + ' { max-width: 100px; }', length);
function getCssRuleLength() {
var length = 0;
if (document.styleSheets[1].cssRules) {
length = document.styleSheets[1].cssRules.length;
} else if (document.styleSheets[1].rules) { //ie
length = document.styleSheets[1].rules.length;
}
return length;
}
function insertCssRule(rule, index) {
if (document.styleSheets[1].cssRules) {
document.styleSheets[1].insertRule(rule, index);
} else if (document.styleSheets[1].rules) { //ie
document.styleSheets[1].addRule(rule, index);
}
}
Here's my answer in case anyone stumbles upon this. Give your elements a new class name that doesn't already exist, then dynamically add a style segment:
var companyColor = 'orange' //define/fetch the varying color here
var style = '<style>.company-background {background-color: ' + companyColor + '; color: white;}</style>';
$('html > head').append($(style));
//give any element that needs this background color the class "company-background"
You have 2 options
add a new stylesheet that overrides this .MyClass
have a second class with the different property, and change the class Name on these elements
Looking at your question, I think a better approach is to switch MyClass with something else using JavaScript rather than to change the properties of the class dynamically.
But if you are still keen you can switch CSS stylesheets with jQuery http://www.cssnewbie.com/simple-jquery-stylesheet-switcher/
var changeClassProperty = function(sheetName, className, propertyName, newValue, includeDescendents) {
var ending = '$';
setValue = '';
if (includeDescendents === true) {
ending = '';
}
if (typeof(newValue) != 'undefined') {
setValue = newValue;
}
var list = document.styleSheets;
for (var i = 0, len = list.length; i < len; i++) {
var element = list[i];
if (element['href'] && element['href'].match(new RegExp('jquery\.qtip'))) {
var cssRules = element.cssRules;
for (j = 0, len2 = cssRules.length; j < len2; j++) {
var rule = cssRules[j];
if (rule.selectorText.match(new RegExp(className + ending))) {
cssRules[j].style.backgroundColor = setValue;
console.log(cssRules[j].style.backgroundColor);
}
}
}
}
}
changeClassProperty('jquery.qtip', 'tipsy', 'backgroundColor', 'yellow');
You'd be much better off adding and removing classes instead of attempting to change them.
For example
.red {
background: red;
}
.orange {
background: orange;
}
$('#div').click(function(){
$(this).removeClass('red').addClass('orange');
});

Categories

Resources