How do I remove :hover? - javascript

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]);
}
}

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

Calling JS Function on Button Click Blocks CSS :hover

I implement a CSS hover method on all of my buttons. It looks like this:
.button:hover { background-color: #36a39c; }
This method works perfectly fine until I click on one of my buttons. When the button is clicked, a JS function is called using this code:
<div id= "one"><button class="button" id = "b1" value="0" onclick="checker(this.id)"></button></div>
This is the JS Script:
var checker = function(id)
{
var xyz = id;
var value = document.getElementById(xyz).value
if (answerjson[value].is_right_choice==1)
{
for (var i = 1; i <=4; i++) {
document.getElementById("b"+i).style.background='#722F37';
}
document.getElementById(xyz).style.background='green';
setTimeout(function(){ alert("Correct!"); }, 100);
}
else {
for (var i = 1; i <=4; i++) {
document.getElementById("b"+i).style.background='#722F37';
}
document.getElementById(xyz).style.background='red';
setTimeout(function(){ alert("Sorry, Try Again"); }, 100);
}
}
After that script is called, my buttons no longer change color on hover. Any ideas why?
This happens because when you add background color using javascript it is added as inline styling and it overrides the css class selector because inline styling always takes more preference. You need to make a class with that color and add/remove that using javascript. e.g. make a class
.green{
background-color: green;
}
and then add it using javascript like this:
document.getElementById(xyz).className += " green";
You're setting the inline style="" attribute in your JS code.
Properties set in inline styles always override CSS selectors (except with !important), so your CSS no longer does anything.
You should add a CSS class instead of setting an inline style.

Change the CSS value from a file

I have a keyboard.css file and a keyboard.js file, I am trying to change a css rule
.ui-keyboard div { font-size: 1.1em; }
I want to change the font size. is there a way to do this without using
$(".ui-keyboard div").css()?
I want to change the value before the element is rendered, I want to pass the value in the construction of an element
$('.onScreenKeyboard').keyboard({
zoomLevel: 2
});
Edit: to clarify this a bit, the goal is to have a way to change the font-size, without having to go and edit the value on the CSS. I want to create an option in the library that does this:
Inside the constructor I check for options and I change the element,
//set Zoom Level
if(o.zoomLevel){
//Change CSS Here.
}
Maybe you're looking for something like CSSStyleSheet's insertRule and deleteRule.
Here is some code I wrote a while ago to let me modify CSS rules
function CSS(sheet) {
if (sheet.constructor.name === 'CSSStyleSheet') this.sheet = sheet;
else if (sheet.constructor.name === 'HTMLStyleElement') this.sheet = sheet.sheet;
else throw new TypeError(sheet + ' is not a StyleSheet');
}
CSS.prototype = {
constructor : CSS,
add: function (cssText) {
return this.sheet.insertRule(cssText, this.sheet.cssRules.length);
},
del: function (index) {
return this.sheet.deleteRule(index);
},
edit: function (index, cssText) {
var i;
if (index < 0) index = 0;
if (index >= this.sheet.cssRules.length) return this.add( cssText );
i = this.sheet.insertRule(cssText, index);
if (i === index) this.sheet.deleteRule(i + 1);
return i;
}
};
You'd use it by giving the constructor CSS your <style> node, or it's StyleSheet directly, then using .edit with the index of the rule and the new rule you want. e.g.
// get StyleSheet
var mycss = new CSS(document.querySelector('style[src="keyboard.css"]'));
// edit rule 0
mycss.edit(0, '.ui-keyboard div { font-size: 5em; }');
Add the following css to the element, initially you wont display it until you run through your library change the style properties then display it.
.ui-keyboard div {
font-size: 1.1em;
display: none;
}
You can also change the font size without jQuery by doing something like:
[element].style.fontSize = "25px";

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

change backround image of another div when hovering over list item

I have a list in a div and I would like to change the background image of the parent div (#homepage_container) when I hover over a list item.
here's the site:-
http://www.thebalancedbody.ca/
Is this possible? I'm guessing I'll have to use javascript.
Thanks
Jonathan
This is quite simple with pure javascript.
function changeBg(newBg)
{
var imgdiv = document.getElementById("divwithbackground");
imgdiv.style.backgroundImage = "url(" + newBg + ")";
}
Or using sprites:
imgdiv.style.backgroundPosition = "new position";
This can be executed on mouseover for any of your li's. Event registration in javascript can be done many ways, but to do it in script, I recommend QuirksMode's method here.
Something like:
function addEventSimple(obj,evt,fn) {
if (obj.addEventListener)
obj.addEventListener(evt,fn,false);
else if (obj.attachEvent)
obj.attachEvent('on'+evt,fn);
}
And on load:
// get the list items
var ul = document.getElementById("ulId");
var lis = ul.getElementsByTagName("li");
// add event handlers
for (var i = 0; i < lis.length; i++)
{
addEventSimple(lis[i], "mouseover", (function(j) {
return function() {
// get your background image from the li somehow
changeBg(lis[j].id + "_bg.png");
};
})(i)); // use a closure to capture the current value of "i"
}
You have to use JS.
Better to learn something like jQuery.
With it you will have to do something like
var images = ['img1.jpg', 'img2.jpg', ...]
for (var i = 0; i < li_count; ++i) // li_count is the number of li's
$('li:eq(' + i + ')').mouseover(function() {$('#homepage_container').css('background-image', images[i]})
Anyway, if you wish to use such kinds of techniques, you have to learn JS.
See http://www.w3schools.com/js/default.asp and for basics and http://docs.jquery.com/Tutorials for jQuery.
I suggest installing the Jquery Library for this (jquery.com)
Just add this to your header:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js">
<script type="text/javascript">
$(document).ready(function() {
$('li').hover(function(){
$('#homepage_container').css('background-image' : 'whatever.png');
}
});
</script>
If you don't care about IE6, you could do it with CSS:
#homepage_container { background: url(normal.png); }
#homepage_container:hover { background: url(hover.png); }

Categories

Resources