IE9 get hover color javascript [duplicate] - javascript

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'));

Related

Adding/changing properties in all the tags of a type (odd results)

I am looking for a way to add/change some properties in all tags of a certain type after the page is loaded.
I found two ways. But for some reason that I don't understand, the results are different.
Method 1 - adding a style tag as the last child of <html>.
var style = document.createElement( "style" );
style.innerHTML = `
div {
background-color: black;
color: white;
}
`;
document.documentElement.appendChild( style );
Result of style tag as last HTML child method
Method 2 - Getting all the tags of that type and painfully having it change them one.
var elems = document.body.getElementsByTagName("div");
for( let i = 0; i < elems.length; i++ ){
elems[i].style.backgroundColor = "black";
elems[i].style.color = "white";
}
Result of loop/in-line method
So I was wondering why the results between the two methods are different, and I'm also happy to learn about other methods of changing all tags of a type of course.
the first method it creates a <style> tag and sets its attributes like you would write the css in the <style> tag or enter it via <link>
the 2nd method uses the style attribute of each tag which is also W3C standard but scoped to just that tag and has syntactic limitations (cannot use selectors like :hover , :focus...)
the 2nd method is faster than 1 and has higher precedence and no error about scoped it is preferred in javascript
Here, Method 1 adding a new style tag to the document and applying CSS styles using the innerHTML. All tags on the page that match with the selector div will have the styles using this technique. However, depending on how much styling is required, this technique may result in a slower page load.
Then,another method which is selecting the background and color properties of each div element on the page by looping through all of them. This approach is quicker because it doesn't need to wait for new styles to load.
So, another method you can use just by changing a bit in your second method is:
var elems = document.querySelectorAll("div");
for( let i = 0; i < elems.length; i++ ){
elems[i].style.backgroundColor = "black";
elems[i].style.color = "white";
}
Nevertheless, you can also use Jquery for shortcut execution :
$("div").css({
"background-color": "black",
"color": "white"
});
The difference was priority. The same inline results of method 2 (loop/inline), were achieved with method 1 (<style> as last child) by adding the !important rule due to the increased priority. Like so:
div {
background-color: black !important;
color: white !important;
}
Simple example demoing how to easily and fully revert all changes, and be left back with the original HTML:
<!DOCTYPE html>
<html>
<head>
<style>
p {
background-color: red;
}
</style>
</head>
<body>
<p>Text sample.</p>
<p style="background-color: grey">Text sample.</p>
<button onclick="test1()">Remove temporary changes</button>
</body>
<script>
function test1() {
document.getElementById("tempChanges").remove();
}
</script>
<style id="tempChanges">
p {
background-color: green !important;
}
</style>
</html>

JS - how to get content of internal style element (<style>...</style)

by internal style I mean
<style>
#div
{color:red;}
</style>
document.getElementsByTagName('style').innerHTML is not working... document.styleSheets either.
document.getElementsByTagName returns Array of Elements
so you need to access it with index
document.getElementsByTagName('style')[0].innerHTML
document.styleSheets is much useful if you want to get specific selector or modify something from style sheet
Example
var styleSheet = document.styleSheets[1];
// assuming second one is embedded style,
// since document.styleSheets also shows linked style sheets (like <link heref=".. >)
for (var i = 0; i < styleSheet.rules.length; i++) {
// if you are looking for selector '.main'
if (styleSheet.rules[i].selectorText === '.main') {
// get background color
var oldBg = styleSheet.rules[i].style.backgroundColor;
// set background color
styleSheet.rules[i].style.backgroundColor = '#ddd';
}
}
document.styleSheets is an array , for each of the style definition in your page .
Iterate for each of the style elements and find the rules defined.
document.styleSheets[0].rules
This is again an array. so iterate . The rule text for each of the rules can be extracted as follows
document.styleSheets[indexofstyleelement].rules[indexofrule].cssText
document.styleSheets[0].rules[0].cssText gives rule text for first of the rules defined inside first style element
<!DOCTYPE html>
<html>
<head>
<style>
#div {
color: red;
}
</style>
</head>
<body>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
<script>
function myFunction() {
var x = document.getElementsByTagName("STYLE")[1];
document.getElementById("demo").innerHTML = x.innerHTML;
}
</script>
</body>
</html>
https://jsfiddle.net/mediaguru/xt9mkncx/
using jquery use this
var x = $('style').html();
using javascript
var x=document.getElementById("home");
var y = x.firstChild.innerHTML;
Ahh I'm so stupid..
for (var i = 0; i < styles_length; i++)
{// I had:
// styles.innerHTML;
// not correct:
styles[i].innerHTML;
}
All answers by #Jag, #ABHIJITH GM, #mediaguru, #hardik are correct.
Thank you guys! And sorry for this newbie question... all day codding, my eyes are hurting, coffee time.

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.

using buttons for changing font size for the whole website using javascript

i am trying to implement accessibility tools and i have managed to change the font size of a paragraph once the button has been clicked but i tried altering the code so that it will work on all the paragraph and it does not work
<script>
function myFunction()
{
var p =document.getElementsByTagName('p'); // Find the element
p.style.fontSize="1.5em"; // Change the style
}
</script>
<button type="button" style="background: #ccc url(images/small.jpg); padding: 0.3em 1em" onclick="myFunction()"></button>
this is how it worked before for just one paragraph but i am trying to more than one:
<script>
function myFunction()
{
x=document.getElementById("demo") // Find the element
x.style.fontSize="3.0em"; // Change the style
}
</script>
getElementsByTagName returns a NodeList, which is like an array, so you have to loop through them and apply the style to each element:
function myFunction() {
var arr = document.getElementsByTagName('p');
for (var i = 0; i < arr.length; i++) {
arr[i].style.fontSize = "1.5em";
}
}
Your issue in the first code block is that getElementsByTagName returns an nodeList of elements (which you can pretend is an array). So you would need to do this:
var p =document.getElementsByTagName('p'); // Find the element
for(var i=0; i<p.length; i++) {
p[i].style.fontSize="1.5em"; // Change the style
}
However, a better approach would be to define some css classes to do this job for you.
<style>
body { /*normal size*/
font-size: 1em;
}
body.largeFont {
font-size: 1.5em;
}
</style>
<script>
function largeFont() {
document.body.className="largeFont";
}
</script>

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