propiedades - ¿Cómo obtener un atributo de estilo de una clase CSS mediante javascript/jQuery?
propiedad jquery (8)
¿Por qué no agrega la clase .highlighted
, almacena en caché el estilo de color
, que lo elimina y anima al color en caché? Es decir, no anexa elementos y no analiza y crea estilos de bucle.
var $element = $(''.my-class'').addClass(''highlighted'');
var colorToAnimate = $element.css(''color'');
$element.removeClass(''highlighted'');
alert(colorToAnimate);
.my-class {
color: blue;
}
.highlighted {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="my-class">Animated color text</span>
¿Cómo puedo acceder a una propiedad de una clase de CSS por jQuery? Tengo una clase de CSS como:
.highlight {
color: red;
}
Y necesito hacer una animación de color en un objeto:
$(this).animate({
color: [color of highlight class]
}, 750);
Para poder cambiar de red
a blue
(en el CSS) y mi animación funcionará de acuerdo con mi CSS.
Un enfoque sería colocar un elemento invisible con la clase de highlight
y luego obtener el color del elemento para usar en la animación, pero supongo que esta es una muy, muy mala práctica.
¿Alguna sugerencia?
¿Qué tal esto?
$(''<span class="highlight"></span>'').appendTo(''body'');
$(this).animate({
color: $(''.highlight'').css(''color'')
}, 750);
$(''.highlight'').remove();
Está algo sucio pero le dará un elemento (vacío) a la referencia para obtener el valor de CSS que está buscando.
Actualizar Aquí hay una solución decente de CSS parser / abstracter? Cómo convertir una hoja de estilo en un objeto
function findColorProperty(selector) {
rules = document.styleSheets[0].cssRules
for(i in rules) {
//if(rules[i].selectorText==selector)
//return rules[i].cssText; // Original
if(rules[i].selectorText == selector)
return rules[i].style.color; // Get color property specifically
}
return false;
}
Uso
$(this).animate({
color: findColorProperty(''.highlight'')
}, 750);
Aquí hay un violín http://jsfiddle.net/wzXDx/1/ . Tuve que usar styleSheets[1]
para hacer que esto funcione en el violín debido a la naturaleza incrustada del entorno.
Acabo de escribir esta función, obtengo todos los estilos con un selector. Aviso: el selector debe ser el mismo que en el CSS.
/**
* Gets styles by a classname
*
* @notice The className must be 1:1 the same as in the CSS
* @param string className_
*/
function getStyle(className_) {
var styleSheets = global_.document.styleSheets;
var styleSheetsLength = styleSheets.length;
for(var i = 0; i < styleSheetsLength; i++){
var classes = styleSheets[i].rules || styleSheets[i].cssRules;
var classesLength = classes.length;
for (var x = 0; x < classesLength; x++) {
if (classes[x].selectorText == className_) {
var ret;
if(classes[x].cssText){
ret = classes[x].cssText;
} else {
ret = classes[x].style.cssText;
}
if(ret.indexOf(classes[x].selectorText) == -1){
ret = classes[x].selectorText + "{" + ret + "}";
}
return ret;
}
}
}
}
Aquí hay otro método: agregar un div oculto con la clase aplicada. Use jQuery.css para buscar el valor de estilo. Luego elimina el elemento.
http://plnkr.co/edit/Cu4lPbaJWHW42vgsk9ey
function getStyleValue(className, style) {
var elementId = ''test-'' + className,
testElement = document.getElementById(elementId),
val;
if (testElement === null) {
testElement = document.createElement(''div'');
testElement.className = className;
testElement.style.display = ''none'';
document.body.appendChild(testElement);
}
val = $(testElement).css(style);
document.body.removeChild(testElement);
return val;
}
console.log( ''The style value is '' + getStyleValue(''dark-red'', ''color'') );
Como ya está usando jQuery intente usar la función switchClass
-ui switchClass
que le permitiría animar a este nuevo color.
Por ejemplo:
$(''div'').switchClass( "", "highlight", 1000 );
En caso de que no quiera incluir toda la biblioteca de UI, aquí está el código que usan:
switchClass: function( remove, add, speed, easing, callback) {
return $.effects.animateClass.call( this, {
add: add,
remove: remove
}, speed, easing, callback );
}
Y la animateClass fn:
var classAnimationActions = [ "add", "remove", "toggle" ],
shorthandStyles = {
border: 1,
borderBottom: 1,
borderColor: 1,
borderLeft: 1,
borderRight: 1,
borderTop: 1,
borderWidth: 1,
margin: 1,
padding: 1
};
function styleDifference( oldStyle, newStyle ) {
var diff = {},
name, value;
for ( name in newStyle ) {
value = newStyle[ name ];
if ( oldStyle[ name ] !== value ) {
if ( !shorthandStyles[ name ] ) {
if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
diff[ name ] = value;
}
}
}
}
return diff;
}
function getElementStyles( elem ) {
var key, len,
style = elem.ownerDocument.defaultView ?
elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
elem.currentStyle,
styles = {};
if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
len = style.length;
while ( len-- ) {
key = style[ len ];
if ( typeof style[ key ] === "string" ) {
styles[ $.camelCase( key ) ] = style[ key ];
}
}
// support: Opera, IE <9
} else {
for ( key in style ) {
if ( typeof style[ key ] === "string" ) {
styles[ key ] = style[ key ];
}
}
}
return styles;
}
$.effects.animateClass = function( value, duration, easing, callback ) {
var o = $.speed( duration, easing, callback );
return this.queue( function() {
var animated = $( this ),
baseClass = animated.attr( "class" ) || "",
applyClassChange,
allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
// map the animated objects to store the original styles.
allAnimations = allAnimations.map(function() {
var el = $( this );
return {
el: el,
start: getElementStyles( this )
};
});
// apply class change
applyClassChange = function() {
$.each( classAnimationActions, function(i, action) {
if ( value[ action ] ) {
animated[ action + "Class" ]( value[ action ] );
}
});
};
applyClassChange();
// map all animated objects again - calculate new styles and diff
allAnimations = allAnimations.map(function() {
this.end = getElementStyles( this.el[ 0 ] );
this.diff = styleDifference( this.start, this.end );
return this;
});
// apply original class
animated.attr( "class", baseClass );
// map all animated objects again - this time collecting a promise
allAnimations = allAnimations.map(function() {
var styleInfo = this,
dfd = $.Deferred(),
opts = $.extend({}, o, {
queue: false,
complete: function() {
dfd.resolve( styleInfo );
}
});
this.el.animate( this.diff, opts );
return dfd.promise();
});
// once all animations have completed:
$.when.apply( $, allAnimations.get() ).done(function() {
// set the final class
applyClassChange();
// for each animated element,
// clear all css properties that were animated
$.each( arguments, function() {
var el = this.el;
$.each( this.diff, function(key) {
el.css( key, "" );
});
});
// this is guarnteed to be there if you use jQuery.speed()
// it also handles dequeuing the next anim...
o.complete.call( animated[ 0 ] );
});
});
};
Violín de trabajo con todas las funciones necesarias: http://jsfiddle.net/maniator/3C5ZQ/
Desafortunadamente no puedo comentar esta increíble answer , pero encontré un caso que no se atiende (cuando la clase CSS se declara varias veces y la primera declaración no tiene el estilo que está buscando), hice un jsFiddle para atenderlo:
function getStyleRuleValue(style, selector, sheet) {
var sheets = typeof sheet !== ''undefined'' ? [sheet] : document.styleSheets;
for (var i = 0, l = sheets.length; i < l; i++) {
var sheet = sheets[i];
if( !sheet.cssRules ) { continue; }
for (var j = 0, k = sheet.cssRules.length; j < k; j++) {
var rule = sheet.cssRules[j];
if (rule.selectorText && rule.selectorText.indexOf(selector) !== -1 && rule.style[style] !== '''') {
return rule.style[style];
}
}
}
return null;
}
También eliminó la división en el condicional, no es necesario y ahora confirma que el estilo está presente en la regla que se comprueba.
Solo para shigiggles creó un jsFiddle para almacenar en caché los estilos por selector:
var styleCache = {};
function getStyleRuleValue(style, selector, sheet) {
if (typeof styleCache[selector] !== ''undefined'') {
if (typeof styleCache[selector][style] !== ''undefined'') {
return styleCache[selector][style];
}
}
else {
styleCache[selector] = {};
}
var sheets = typeof sheet !== ''undefined'' ? [sheet] : document.styleSheets;
for (var i = 0, l = sheets.length; i < l; i++) {
var sheet = sheets[i];
if( !sheet.cssRules ) { continue; }
for (var j = 0, k = sheet.cssRules.length; j < k; j++) {
var rule = sheet.cssRules[j];
if (rule.selectorText && rule.selectorText.indexOf(selector) !== -1 && rule.style[style] !== '''') {
return styleCache[selector][style] = rule.style[style];
}
}
}
return null;
}
Aunque si usas eso, te sugiero ponerlo en un cierre / clase. Gracias de nuevo a answer por el impresionante original.
Escribí una pequeña función que cruza las hojas de estilo en el documento buscando el selector correspondiente, luego el estilo.
Hay una advertencia, esto solo funcionará para hojas de estilo definidas con una etiqueta de estilo o hojas externas del mismo dominio.
Si se conoce la hoja, puede pasarla y evitar tener que buscar en varias hojas (más rápido y si tiene reglas de colisión es más exacto).
Solo probé en jsFiddle con algunos casos de prueba débiles, avíseme si esto funciona para usted.
function getStyleRuleValue(style, selector, sheet) {
var sheets = typeof sheet !== ''undefined'' ? [sheet] : document.styleSheets;
for (var i = 0, l = sheets.length; i < l; i++) {
var sheet = sheets[i];
if( !sheet.cssRules ) { continue; }
for (var j = 0, k = sheet.cssRules.length; j < k; j++) {
var rule = sheet.cssRules[j];
if (rule.selectorText && rule.selectorText.split('','').indexOf(selector) !== -1) {
return rule.style[style];
}
}
}
return null;
}
uso de ejemplo:
var color = getStyleRuleValue(''color'', ''.foo''); // searches all sheets for the first .foo rule and returns the set color style.
var color = getStyleRuleValue(''color'', ''.foo'', document.styleSheets[2]);
editar:
Descuidé tomar en consideración las reglas agrupadas. Cambié la verificación del selector a esto:
if (rule.selectorText.split('','').indexOf(selector) !== -1) {
ahora comprobará si alguno de los selectores de las reglas agrupadas coincide.
La única solución que me viene a la mente es la siguiente:
//create an element with this class and append it to the DOM
var eleToGetColor = $(''<div class="highlight" style="display: none;">'').appendTo(''body'');
//get the color of the element
var color = eleToGetColor.css(''color'');
//completly remove the element from the DOM
eleToGetColor.remove();
$("div").animate({
//set the new color
color: color,
}, 1000);
.highlight {
color: red;
}
div {
width: 200px;
height: 100px;
color: blue;
font-size: 6em;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
<div>TEST</div>