Say I have the following css:
.cls {}
.cls ul {list-style-type:none;}
.cls ul li
{
border-color:#ff0000;
border-style:solid;
float:left;
padding:0px 20px 0px 2px;
border-left-width:1px;
border-bottom-width:0px;
border-top-width:0px;
border-right-width:0px;
}
I assign the class "cls" to a <div> as follows:
<div class="cls">
<ul>
<li id="foo">Foo</li>
<li id="bar">Bar</li>
</ul>
</div>
If I manipulate element properties using jquery, say I change the border-left-color on the "bar" listitem as follows:
$("#bar").css("border-left-color", "#0000ff");
Is there a "jquery way" to RESTORE the properties that the listitem "bar" had inherited when the containing <div> was initially assigned the class "cls"?
Obviously without having to do:
$("#bar").css("border-left-color", "#ffff00"); }.
Something in the form of, $().restoreClass() or equivalent???
Define a new class
.blueBorder {
border-left-color: #0000ff;
}
Then you can toggle the style with
$("#bar").toggleClass('blueBorder'); // with blue border
$("#bar").toggleClass('blueBorder'); // without blue border
$("#bar").toggleClass('blueBorder'); // with blue border
This is the best way to toggle style. Keep in mind that you can apply more than one class to a single HTML element, so that you can combine styles together. For example
$("#bar").toggleClass('blueBorder'); // with blue border
$("#bar").toggleClass('redBackground'); // with blue border and red background
$("#bar").toggleClass('blueBorder'); // with red background
You should keep your presentation (css) separated from the behavior (js), so the following is not recommended:
$("#bar").css("border-left-color", "#0000ff");
Imagine the work you will have, if you write this a thousand times and later your customer decides to change it to yellow.
Demo here
$("#bar").css("border-left-color", "");
When you use .css it adds a style attribute to the element. As long as there was not a style attribute when the page was rendered, calling $().removeAttr('style') should do what you want.
JsFiddle Example
Try: $("#bar").removeAttr('style')
You can get the particular CSS property and store it in a string.
Then you can restore it when you are done with the change.
But you have to be careful with the name of CSS property :
Here it is working:
http://jsfiddle.net/KgEjr/4/
var myOriginal = "" ;
$('#st').click(
function() { storeAndChange(); } );
$('#re').click(
function() { restore(); } );
function storeAndChange()
{
myOriginal = $("#bar").css("border-left-color");
$("#bar").css("border-left-color", "#0000ff");
$("#msg").text("changed");
}
function restore()
{
$("#bar").css("border-left-color", myOriginal);
$("#msg").text("restored");
}
Could you store the style in a data attribute and recover it later? This seems to work with your example.
$(function(){
$(".cls ul li").each(function(){
$(this).data("defaultStyle",$(this).attr("style") || "");
});
$("#foo").css({"border-left-color": "#ff00ff", "font-style": "italic", "background-color": "#efefef"});
$("#bar").css({"border-left-color": "#0000ff", "font-weight": "bold", "background-color": "#cdcdcd"});
$(".cls ul li").click(function(){
$(this).attr("style", $(this).data("defaultStyle"));
});
});
Related
Goal
In my program I want to do both things with jquery/javascript:
Change styling of css classes dynamically
Add/remove classes to elements
Problem
To do the first thing I use $(".className").css() method, but it changes style only for those elements that already have className class, i.e. if I later add className to an element its style won't be new. How can I solve this?
Example
See it also at jsfiddle.
$("p").addClass("redclass");
$(".redclass").css("color", "darkRed");
$("span").addClass("redclass");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>I want to be red! And I am.</p>
<span>I want to be red too but I'm not :'(</span>
Result:
A more shorten format:
$("<style/>", {text: ".redclass {color: darkRed;}"}).appendTo('head');
The snippet:
$("<style/>", {text: ".redclass {color: darkRed;}"}).appendTo('head');
$("p").addClass("redclass");
$("span").addClass("redclass");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>I want to be red! And I am.</p>
<span>I want to be red too but I'm not :'(</span>
While other (working) answers have been supplied, they don't actually answer your question - namely, they don't change the specified css class, but instead override it by adding another rule later in the document.
They achieve this, basically:
Before
.someClass
{
color: red;
}
After
.someClass
{
color: red;
}
.someClass
{
color: white;
}
When in many cases, a better option would see the color attribute of the existing rule altered.
Well, as it turns out - the browser maintains a collection of style-sheets, style-sheet rules and attributes of said rules. We may prefer instead, to find the existing rule and alter it. (We would certainly prefer a method that performed error checking over the one I present!)
The first console msg comes from the 1 instance of a #coords rule.
The next three come from the 3 instances of the .that rule
function byId(id){return document.getElementById(id)}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
byId('goBtn').addEventListener('click', onGoBtnClicked, false);
}
function onGoBtnClicked(evt)
{
alterExistingCSSRuleAttrib('#coords', 'background-color', 'blue');
alterExistingCSSRuleAttrib('.that', 'color', 'red');
}
// useful for HtmlCollection, NodeList, String types (array-like types)
function forEach(array, callback, scope){for (var i=0,n=array.length; i<n; i++)callback.call(scope, array[i], i, array);} // passes back stuff we need
function alterExistingCSSRuleAttrib(selectorText, tgtAttribName, newValue)
{
var styleSheets = document.styleSheets;
forEach(styleSheets, styleSheetFunc);
function styleSheetFunc(CSSStyleSheet)
{
forEach(CSSStyleSheet.cssRules, cssRuleFunc);
}
function cssRuleFunc(rule)
{
if (selectorText.indexOf(rule.selectorText) != -1)
forEach(rule.style, cssRuleAttributeFunc);
function cssRuleAttributeFunc(attribName)
{
if (attribName == tgtAttribName)
{
rule.style[attribName] = newValue;
console.log('attribute replaced');
}
}
}
}
#coords
{
font-size: 0.75em;
width: 10em;
background-color: red;
}
.that
{
color: blue;
}
<style>.that{color: green;font-size: 3em;font-weight: bold;}</style>
<button id='goBtn'>Change css rules</button>
<div id='coords' class='that'>Test div</div>
<style>.that{color: blue;font-size: 2em;font-weight: bold;}</style>
#synthet1c has described the problem. My solution is:
$("head").append('<style></style>');
var element = $("head").children(':last');
element.html('.redclass{color: darkred;}');
What you are having issue with is that when you use the jQuery selector $('.redclass').css('color', 'darkRed') you are getting all the elements that currently have that class and using javascript to loop over the collection and set the style property.
You then set the class on the span after. Which was not included in the collection at the time of setting the color
You should set the class in your css file so it is distributed to all elements that have that class
console.log($('.redclass').length)
$("p").addClass("redclass");
console.log($('.redclass').length)
// $(".redclass").css("color", "darkRed");
$("span").addClass("redclass");
console.log($('.redclass').length)
.redclass {
color: darkRed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>I want to be red! And I am.</p>
<span>I want to be red too but I'm not :'(</span>
I have multiple rows and in each row is a span which is set to transparent:
span {
color: transparent;
}
Now upon the hover of a row, I set the span to be visible by adding the following jQuery:
$('.single-row').hover(function(){
$('span').css("color", "#999");
}, function() {
$('span').css("color", "transparent");
}
);
However, this effects every row at once rather than the specific row being hovered over.. what syntax do use to effect the specific row being hovered over rather than each row without using id's?
You can do it using $(this).find('span') to select a span inside current hovered row
$('.single-row').hover(function(){
$(this).find('span').css("color", "#999");
}, function() {
$(this).find('span').css("color", "transparent");
}
);
Or use a shortcut $('span',this)
$('.single-row').hover(function(){
$('span',this).css("color", "#999");
}, function() {
$('span',this).css("color", "transparent");
}
);
The javascript method in the currently-accepted answer will work fine (provided the bug mentioned in comments is fixed) -- but just for completeness, a pure CSS version of this would be
.single-row span {color: transparent}
.single-row:hover span {color: #999}
I'm trying to make it so that when you hover a list item, the corresponding piece is highlighted, and when you hover the piece, the corresponding list item is highlighted.
So far when you hover on the list item, it does highlight the corresponding map area, but how would I write it so that it hovered reciprocally?
I tried:
$('.one, #one').hover(function(){
$('#one, .one').attr("fill", "#213A46");
$(".info-one").fadeIn();
},
function(){
$('#one, .one').attr("fill", "#009A8B");
$(".info-one").hide();
});
and that did not seem to work. Any suggestions would be helpful. Here's a codepen of what I'm currently working on as well: http://codepen.io/anon/pen/zGzoMY
You can't change the state of an element, so you do have to change your .region-list li:hover { by .region-list li:hover, .region-list li.hover {.
Then you can add it in your JS, i.e. :
$('#four').hover(
function() {
$('#four').attr("fill", "#213A46");
$('.four').addClass('hover');
$(".info-four").fadeIn();
},
function() {
$('#four').attr("fill", "#3F6C80");
$('.four').removeClass('hover');
$(".info-four").hide();
}
This isn't possible. You will need to add a class like .hover to the element.
see: https://forum.jquery.com/topic/jquery-triggering-css-pseudo-selectors-like-hover
The way to trigger the hover on the li by hovering on the map is something like this:
$('#one').hover(function() {
$('.one').trigger('mouseenter');
});
But to add the class you will do something like
$('#one').hover(function() {
$('.one').addClass('hover');
});
Then remember to remove the class on mouseleave.
You need to add the hover handler to the graphic that contains #one. Otherwise, when you mouse over the text inside the polygon, that's treated as leaving the polygon.
$('.one, g:has(#one)').hover(function() {
$('#one').attr("fill", "#213A46");
$('.region-list .one').css({
backgroundColor: '#213a46',
color: '#ffffff'
});
$(".info-one").fadeIn();
},
function() {
$('#one').attr("fill", "#009A8B");
$('.region-list .one').css({
backgroundColor: 'inherit',
color: 'inherit'
});
$(".info-one").hide();
});
Modified Codepen
I've only updated #one, the others are similar. It would be better to implement this using DRY methods where you find the reciprocal elements using data attributes, but I didn't bother with that rewrite.
The below code takes into account different tags and turns the background red if the tag is clicked on. I want to code it so that if it is clicked on again, it changes back from red and 'deletes' the background, or at least set it to null. I have tried an if statement to no avail. I know that I can just make another click event that changes the background to white, but this is for experimental purposes and i was wondering if this CAN be done with if statements. thanks to ya.
<script>
$(document).ready(function() {
$("p, h1").click(function() {
$(this).css("background-color", "red");
if ($(this).css("background-color", "red")) {
$(this).css("background-color", "null");
}
});
});
</script>
First you need to use the getter version of .css() like
if($(this).css("background-color") == "red"){
but it still won't work because, the css getter will return a rgb format value and will return non consistent values across browsers.
So the solution is to use a css based solution using toggleClass()
.red {
background-color: red;
}
then
$(document).ready(function() {
$("p, h1").click(function() {
$(this).toggleClass("red");
});
});
Demo: Fiddle
$('p, h1').click(function() {
var $this = $(this);
var altColor = $this.data('altColor');
$this.css('background-color', altColor ? '' : 'red');
$this.data('altColor', ! altColor);
});
This answers your question, but you should really be using a CSS class for this.
This is easily done using CSS, and is a bit more straight forward. If you create a CSS class for the click, then you can just toggle it on/off each time the item is clicked:
CSS
p, h1 {
background-color: none;
}
p.red, p.h1 {
background-color: red;
}
JavaScript:
$('p, h1').click(function() {
$(this).toggleClass('red');
});
I have more than 3 buttons, each of them has a different style (different border color, different background color on hover).
(I created them with the <li> because they have an action to change the background-position of a picture).
I want them to maintain the same hover state appearance after they've been clicked, but to go back to the normal state when another button is clicked.
How can I do this?
Thank you in advance :)
ps: I'm working in HTML with css, js when needed (like in this case).
Given the complete lack of information about the HTML, and current JavaScript, you're using, the best I can offer is a simple demonstration of how this might be achieved:
function colorify (e) {
// get a reference to the element we're changing/working on:
var demo = document.getElementById('demo'),
/* getting the siblings, the other controls,
of the clicked-element (e.target):
*/
controls = e.target.parentNode.children;
// iterating over those controls
for (var i = 0, len = controls.length; i < len; i++) {
/* if the current control[i] is the clicked-element, we 'add' the 'active'
class, otherwise we 'remove' it (using a ternary operator):
*/
controls[i].classList[controls[i] == e.target ? 'add' : 'remove']('active');
}
/* changing the background-color of the 'demo' element, setting it to the
textContent of the clicked-element:
*/
demo.style.backgroundColor = e.target.textContent;
}
var controls = document.getElementById('controls');
controls.addEventListener('click', colorify);
JS Fiddle demo.
The above is based on the following HTML:
<div id="demo"></div>
<ul id="controls">
<li>Red</li>
<li>Green</li>
<li>Blue</li>
</ul>
And CSS:
#demo {
width: 10em;
height: 10em;
border: 2px solid #000;
}
.active {
color: #f00;
}
This approach requires a browser that implements the classList API, the children property of a DOM node, as well as the addEventListener() method of a Node.
References:
addEventListener.
Element.classList.
ParentNode.children.