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

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>

Related

how to update style properties in <style> tag using javascript [duplicate]

Is it possible to make changes to a CSS rule-set dynamically (i.e. some JS which would change a CSS rule-set when the user clicks a widget)
This particular CSS rule-set is applied to lots of elements (via a class selector) on the page and I want to modify it when the user clicks the widget, so that all the elements having the class change.
You can, but it's rather cumbersome. The best reference on how to do it is the following article: Totally Pwn CSS with Javascript (web archive link).
I managed to get it to work with Firefox and IE - I couldn't in Chrome, though it appears that it supports the DOM methods.ricosrealm reports that it works in Chrome, too.
This is a modern version based on Totally Pwn CSS with Javascript. It's ES6 I hope don't mind.
function getCSSRule(ruleName) {
ruleName = ruleName.toLowerCase();
var result = null;
var find = Array.prototype.find;
find.call(document.styleSheets, styleSheet => {
result = find.call(styleSheet.cssRules, cssRule => {
return cssRule instanceof CSSStyleRule
&& cssRule.selectorText.toLowerCase() == ruleName;
});
return result != null;
});
return result;
}
This function returns a CSSStyleRule that you can use like this:
var header = getCSSRule('#header');
header.style.backgroundColor = 'red';
Also document.styleSheets list references of the CSSStylesSheets Objects. Other way to acces a specific sytleSheet in the page is by assigning an id to the style or link element in the html code, and get it in javascript using document.getElementById('my-style').sheet. This are some useful methods:
Major Browsers and IE9+ : insertRule(), deleteRule(), removeProperty().
Major Browsers, Firefox? and IE9+ : setProperty().
<stye id="my-style" ...
....
var myStyle = document.getElementById('my-style').sheet
myStyle.insertRule('#header { background: red; }', 0);
It is also possible to dynamically create a new style element to store dynamic created styles, I think should be way to avoid conflicts.
You can edit CLASS in document styleshets as follows
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
function edit() {
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
}
.box {
margin: 10px;
padding: 10px;
background: yellow;
}
<button onclick="edit()" >Click me</button>
<div class="box" >My box 1</div>
<div class="box" >My box 2</div>
<div class="box" >My box 3</div>
I tried the code via link from #alex-gyoshev comment, but it dosn't work
it fails on the CSS rules with Google fonts in Chrome
it fails on FireFox security checks
So I changed it slightly, but deleted delete functionality since it wasn't needed for me. Checked in IE 11, FireFox 32, Chrome 37 and Opera 26.
function getCSSRule(ruleName) { // Return requested style object
ruleName = ruleName.toLowerCase(); // Convert test string to lower case.
var styleSheet;
var i, ii;
var cssRule = false; // Initialize cssRule.
var cssRules;
if (document.styleSheets) { // If browser can play with stylesheets
for (i = 0; i < document.styleSheets.length; i++) { // For each stylesheet
styleSheet = document.styleSheets[i];
if (!styleSheet.href) {
if (styleSheet.cssRules) { // Browser uses cssRules?
cssRules = styleSheet.cssRules; // Yes --Mozilla Style
} else { // Browser usses rules?
cssRules = styleSheet.rules; // Yes IE style.
} // End IE check.
if (cssRules) {
for (ii = 0; ii < cssRules.length; ii++) {
cssRule = cssRules[ii];
if (cssRule) { // If we found a rule...
// console.log(cssRule);
if (cssRule.selectorText) {
console.log(cssRule.selectorText);
if (cssRule.selectorText.toLowerCase() == ruleName) { // match ruleName?
return cssRule; // return the style object.
}
}
}
}
}
}
}
}
return false; // we found NOTHING!
}
Depending on what you're trying to achieve, a better solution might be to change/add a class to a containing element (body would do!), and define classes accordingly.
.yourclass { color: black }
#wrapper.foo .yourclass { color: red }
#wrapper.bar .yourclass { color: blue }
then you can just use
document.getElementById('wrapper').className='foo';
(or your chosen js framework's wrapper for the same) to change everything with class yourclass inside whatever your wrapper element is.
The APIs for editing stylesheets with JS are, sadly, not consistent across browsers. The YUI Stylesheet Utility attempts to smooth over these differences so you could just use that. You could also look at the source code to figure out how it works if you don't want to use YUI itself.
give your style tag an id, like <style id="ssID">
if someonelse is making your styles for you
tell THAT person to give the style tag an id -
that way you can access it directly without
scrambling around wondering what its index is
// create a hash table
var cssHash = {};
// loop through and populate the hash table
for (let i in (r = ss0.sheet.rules)) {
// selectorText is the name of the rule - set the value equal to the rule
cssHash[r[i].selectorText] = r[i];
}
now you have a hash table for everything in the style sheet -
note that some values will be undefined, but not for
any of the things you care about
if you have, for instance, a class called #menuItem
and you want to change its color to black, do this
cssHash['#menuItem'].style.color = #000;
that line will set the color of the style of the rule
whose index was looked up in the hash table (cssHash)
by the name '#menuItem'
more importantly, you probably have several different
classes that you want to change all at once
kind of like when you switched majors in college
let's say you have four different classes
and you want to set all of their background colors
to the same value, that some user selected from an input
the color selector tag is <input id="bColor" type="color">
and the class rules you want to change are called
#menuItem .homeAddr span and #vacuum:hover
// create a listener for that color selector
bColor.addEventListener('input', function (e) {
// loop through a split list of the four class names
'#menuItem .homeAddr span #vacuum:hover'.split(' ').forEach(function (obj) {
// use the hash table to look up the index of each name
// and set the background color equal to the color input's value
cssHash[obj].style.backgroundColor = bColor.value;
});
}, false); // false added here for the sake of non-brevity
While setAttribute is nice, there is a standard way of doing this across most browsers:
htmlElement.className = 'someClass';
To do it over many elements, you will need a cross browser solution:
function getElementsByClassName( className, context, tagName ) {
context = context || document;
if ( typeof context.getElementsByClassName === 'function' )
return context.getElementsByClassName( className );
if ( typeof context.getElementsByTagName !== 'function' )
return [];
var elements = typeof tagName === 'string' ? context.getElementsByTagName( tagName ) :
context.getElementsByTagName('*'),
ret = [];
for ( var i = 0, il = elements.length; i < il; i++ )
if ( elements[ i ].className.match( className ) )
ret.push( elements[ i ] );
return ret;
}
var elements = getElementsByClassName('someClass');
for ( var i = 0, il = elements.length; i < il; i++ )
elements[ i ].className = 'newClass';
You may want to replace the line:
if ( elements[ i ].className.match( className ) )
With some Regular Expression, but you will have to escape special characters in that case.
To check all stylesheets for the rule and set it:
Your rule:
.aaa: {
background-color: green
}
[...document.styleSheets].flatMap(s=>[...s.cssRules])
.find(i=>i.selectorText=='.aaa').style.backgroundColor = 'red';
Note that the css styles, when accessed through javascript, do not have dashes in them. In the example above, background-color becomes backgroundColor

CSS style to inline style via 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.

Change backgroundcolour of input after onblur automatically across page

I would like an input field to have the background colour changed after onblur. Automatically for all fields on every page. So I am hoping for a script in the header that will automatically affect all input fields.
Can this be done?
Thanks!
window.onload = function(){
Array.prototype.slice.call(document.getElementsByTagName('input')).forEach(function(element){
element.addEventListener('blur',function(){
//anything here. Notice that both this and element refer to each input element.
})
});
}
document.querySelectorAll or any function returning a NodeList object can be used.
since you start up in an "onblur" state, you should listen to the focus/click event, not the blur event
add css
input{ /*Blurred state*/
background-color: red;
}
.onFocus input{ /*clicked state*/
background-color: green;
}
add some javascript
$(input).
click(function(e){
body.className="onFocus";
}).
blur(function(){
body.className="";
});
It can certainly be done. Because you've demonstrated no attempt, I'm choosing to assume you're willing to support the latest/up-to-date browsers (rather than all legacy browsers):
function colorOnBlur(){
this.style.backgroundColor = '#f00';
}
var inputs = document.querySelectorAll('input');
for (var i = 0, len = inputs.length; i < len; i++){
inputs[i].addEventListener('blur', colorOnBlur);
}
JS Fiddle demo.
Or you can add a new class-name to the elements (rather than changing the style object yourself:
function colorOnBlur(){
this.classList.add('blurred');
}
var inputs = document.querySelectorAll('input');
for (var i = 0, len = inputs.length; i < len; i++){
inputs[i].addEventListener('blur', colorOnBlur);
}
Coupled with the CSS:
input.blurred {
background-color: #f00;
}
JS Fiddle demo.
Obviously, adjust the relevant colours to your own tastes/requirements.
References:
addEventListener().
classList.
document.querySelectorAll().

Hide H1 Element using JavaScript

I want to hide the <h1> element using plain javascript, not jQuery, without adding id="whatever" or class="whatever" to the tag. Is this possible?
Why can't I just add id="whatever" to the tag?
I'm using a UIButton in xCode that when clicked, it injects javascript into a UIWebView. Inside that UIWebView is a H1 element that is on a website that I do not have access to to add <h1 id="whatever">. I hope it makes sense.
document.getElementsByTagName('h1')[0].style.display = 'none';
You can use getElementsByTagName method:
var h = context.getElementsByTagName('h1');
for (var i = h.length; i--; ) {
h[i].style.display = 'none';
}
Where context is document or more specific parent node you want to search your headers within.
However there is better solution. You could add specific class to some parent node and hide child headers with CSS:
.without-headers h1 {display: none;}
Use getElementsByTagName to hide the first h1 on your page:
document.getElementsByTagName("h1")[0].style.display = "none";
// ^ index 0, so that's the first `h` that's found.
Or to hide them all:
var headers = document.getElementsByTagName("h1");
for (var i = 0, l = headers.length; i < l; i++; ) {
headers[i].style.display = "none";
}
Or even better yet, if you can modify the CSS:
h1{
display:none;
}
For the JavaScript solutions, please keep in mind that they will only work when the DOM has been loaded.
Add a domready event listener, like this:
window.addEvent('domready', function() {
// modify your DOM here.
});
you can use getElementsByTagName
document.getElementsByTagName("h1")
But it will access all h1 elements, so to be more specific access it by index like this
document.getElementsByTagName("h1")[0].style.display = "none";
just small change in dfsq's code
var h = document.getElementsByTagName('h1');
for (var i =0; i<h.length; i++) {
document.getElementsByTagName('h1').item(i).style.display = 'none';
}

How do I remove :hover?

I have a small problem with a script.
I want to have a default action on :hover for clients with Javascript disabled, but for those with Javascript enabled I want another action (actually... same action, but I want to add a small transition effect).
So... How can I do this? I am using jQuery.
Apply two classes to the relvant element. one contains the hover behaviour, and one contains all the other styling.
You can then use the jquery
$(element).removeClass('hover');
method to remove the class with the hover behaviour and then apply whatever you want using
$(element).bind('mouseover', function () { doSomething(); });
$(element).bind('mouseout', function () { doSomething(); });
How about putting the :hover fall-back in a stylesheet that is only loaded if javascript is disabled?
<noscript>
<link href="noscript.css" rel="stylesheet" type="text/css" />
</noscript>
Here is a solution without hack classes:
CSS:
a {color: blue;}
a:hover {color: red;}
jQuery (uses jQueryUI to animate color):
$('a').hover(
function() {
$(this)
.css('color','blue')
.animate({'color': 'red'}, 400);
},
function() {
$(this)
.animate({'color': 'blue'}, 400);
}
);
demo
I think the best approach would be to leave the :hover behavior as a fall-back for non-javascript users and then use JQuery to create mouseover and mouseout event handlers to create a different effect for javascript-enabled users.
JQuery Javascript Library - Events/mouseover
It's a very old question but I feel the urge to tell that modernizr provides a very good way to implement these kind of fallbacks.
Just include modernizr in the head and you can do these:
.no-js a:hover {
set background color and stuff like that
for cases when no javascript is present
}
On the other hand if you want to do this the other way and only set css when js is present
.js a:hover {
set background color to default
and the text decoration
}
It is more or less the same solution as adding a hover tag to the markup, but a little more robust.
I HAVE FOUND YOUR SOLUTION
basically you start out by redefining what you did with the css hover.
(naturally you would do this by dynamically pulling the information from the style)
then do whatever you want to in jquery with mouseover/mouseout events
this allows you to keep the :hover event in your css because jquery is binding your original styles to the element. In essence disabling the :hover event.
if your css is:
a.class {
background-color: #000000;
background-position: 0 0;
}
a.class:hover {
background-color: #ffffff;
background-position: 100% -50px;
}
your jquery would be somthing like:
jQuery("a.class").each(function () {
var oldBackgroundColor = jQuery(this).css("backgroundColor");
var oldBackgroundPosition = jQuery(this).css("backgroundPosition");
jQuery(".class").css({
'backgroundColor':oldBackgroundColor,
'backgroundPosition':oldBackgroundPosition
});
})
.bind("mouseover", function() {
doSomething();
})
.bind("mouseout", function() {
doSomething();
})
You can redraw element after click
function redraw(element) {
if (!element) { return; }
let n = document.createTextNode(' ');
let disp = element.style.display; // don't worry about previous display style
element.appendChild(n);
element.style.display = 'none';
setTimeout(function(){
element.style.display = disp;
n.parentNode.removeChild(n);
}, 100); // you can play with this timeout to make it as short as possible
}
You can globally enable behavior across the entire document by using a single css rule, and then disable that rule in one statement in javascript, while installing the new event handler.
Add a class to your html body tag:
<html>
<body class="use-hover">
...
Default behavior in your css, let's say to bold links on hover:
body.use-hover a:hover
font-weight: bold
And in your js, when run will remove the default behavior and do something else:
$(function() {
$('body').removeClass('use-hover');
$('a').live('mouseover', function() {
// Do something when hovered
}).live('mouseout', function() {
// Do something after hover is lost
});
});
You could strip all :hover style rules from document.styleSheets.
Just go through all CSS styles with JavaScript and remove all rules, which contain ":hover" in their selector. I use this method when I need to remove :hover styles from bootstrap 2.
_.each(document.styleSheets, function (sheet) {
var rulesToLoose = [];
_.each(sheet.cssRules, function (rule, index) {
if (rule.selectorText && rule.selectorText.indexOf(':hover') > 0) {
rulesToLoose.push(index);
}
});
_.each(rulesToLoose.reverse(), function (index) {
if (sheet.deleteRule) {
sheet.deleteRule(index);
} else if (sheet.removeRule) {
sheet.removeRule(index);
}
});
});
I did use underscore for iterating arrays, but one could write those with pure js loop as well:
for (var i = 0; i < document.styleSheets.length; i++) {}
Vanilla JS version of Mikael Lepistö's answer
for (var i = 0; i < document.styleSheets.length; i++) {
var sheet = document.styleSheets[i];
var rulesToLose = [];
for (var j = 0; j < sheet.cssRules.length; j++) {
var rule = sheet.cssRules[j];
if (rule && rule.selectorText && rule.selectorText.indexOf(':hover') >= 0) {
rulesToLose.push(j);
}
}
// Iterate backwards to prevent pointing to the wrong index while sheet rules get deleted
for (var k = rulesToLose.length - 1; k >= 0; k--) {
sheet.deleteRule(rulesToLose[k]);
}
}

Categories

Resources