2009-09-11 7 views
49

¿Es posible realizar cambios en un conjunto de reglas dinámicamente CSS (es decir, un poco de JS que cambiaría un CSS conjunto de reglas cuando el usuario hace clic en un widget)Cambio de un CSS conjunto de reglas de Javascript

Este CSS particular, el conjunto de reglas se aplica a muchos elementos (a través de un selector de clases) en la página y quiero modificarlo cuando el usuario hace clic en el widget, de modo que cambien todos los elementos que tienen la clase.

+2

En cuanto a algunas de las respuestas, parece que hay cierta confusión acerca de lo que significa su pregunta. Esto no es ayudado por el hecho de que "una clase de CSS" no existe, pero dos cosas diferentes comúnmente se describen mal de esa manera. Una es "Una clase HTML", pero creo que se refiere a la otra: un conjunto de reglas CSS (en este caso, con un selector de clases). – Quentin

+0

Quise decir un conjunto de reglas CSS para un selector de clase –

Respuesta

31

Puede, pero es bastante engorroso. La mejor referencia sobre cómo hacerlo es el siguiente artículo: Totally Pwn CSS with Javascript (web archive link).

Me las arreglé para que funcione con Firefox y IE - No pude en Chrome, aunque parece que es compatible con los métodos DOM.ricosrealm informa que también funciona en Chrome.

+0

¡Eso es genial! No tenía idea de que pudieras hacer eso. Parece bastante avanzado, sin embargo. Y realmente no puedo ver un buen uso si tienes un buen marco como Prototype o jQuery, que hará la mayor parte de ese trabajo por ti ... Pero aún así es bueno saberlo. Marcado como referencia futura (: +1 – peirix

+0

Este es un buen uso: http://stylebuilder.telerik.com/: P Y sí, es avanzado: usar jQuery es probablemente mucho más adecuado para la situación;) –

+1

Aquí hay algunas referencias de MDC : https://developer.mozilla.org/en/DOM/document.styleSheets https://developer.mozilla.org/En/DOM/Stylesheet –

0

Mientras setAttribute es agradable, hay una manera estándar de hacer esto a través de la mayoría de los navegadores:

htmlElement.className = 'someClass'; 

que hacerlo de muchos elementos, necesitará una solución de navegadores:

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

Es posible que desee reemplazar la línea:

if (elements[ i ].className.match(className)) 

Con algunos Regular Expression, pero tendrás que escapar de los personajes especiales en ese caso.

+1

En cuanto a la última parte de su respuesta, creo que se debe usar algo que no sea la coincidencia, para dar cuenta de nombres de clases múltiples, en cualquier orden. Por ejemplo, "foo bar" .match ("foo bar") devolverá "foo bar", pero "foo bar" .match ("bar foo") devolverá nulo. Quizás dividir por espacios y verificar todos los nombres de clase en un bucle for funcionaría (sin embargo, se debe ignorar el espacio en blanco inicial/final, y se debe tener cuidado de no obtener una cadena vacía en el conjunto de un espacio extra en algún lugar). Referencia: [Semántica W3] (http://www.w3.org/TR/html5/dom.html#dom-document-getelementsbyclassname) – Chase

2

Dependiendo de lo que esté tratando de lograr, una mejor solución podría ser cambiar/agregar una clase a un elemento contenedor (¡body do do!), Y definir las clases en consecuencia.

.yourclass { color: black } 
#wrapper.foo .yourclass { color: red } 
#waraper.bar .yourclass { color: blue } 

a continuación, puedes utilizar

document.getElementById('wrapper').className='foo'; 

(o la envoltura de su marco js designado para el mismo) para cambiar todo con clase yourclass dentro de lo que su elemento es wrapper.

((entre paréntesis) ¿hay alguna manera de detener el formateador SO de asumir la materia a partir de una # es un comentario?)

+1

En respuesta a su paréntesis: sí, hay una forma de especificar explícitamente los lenguajes de código (http : //meta.stackexchange.com/questions/63800/interface-options-for-specifying-language-prettify) – Brilliand

4

Las API de hojas de estilo de edición con JS son, por desgracia, no es consistente en todos los navegadores. El YUI Stylesheet Utility intenta suavizar estas diferencias para que pueda usarlo. También puede consultar the source code para descubrir cómo funciona si no desea usar YUI.

+0

¿Sigue siendo válido? – fiatjaf

+0

Dice 'obsoleto' y 'no utilizar esto para nuevos proyectos' allí mismo en el sitio, por lo que mi mejor opción sería no. – stinodes

4

He probado el código a través del enlace de @ comentario alex-gyoshev, pero dosn't trabajar

  1. se produce un error en las reglas CSS con las fuentes de Google en Chrome
  2. falla en Firefox controles de seguridad

Así que lo cambié un poco, pero eliminé la funcionalidad delete porque no era necesario para mí. Controlado en IE 11, FireFox 32, Chrome 37 y 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! 
} 
+0

las reglas de CSS son insensibles a mayúsculas y minúsculas? – sarkiroka

+1

https://www.google.ru/search?q=CSS+case+sensitive -> http://www.w3.org/TR/CSS2/syndata.html#characters "Toda la sintaxis de CSS es mayúscula insensible dentro del rango ASCII (es decir, [az] y [AZ] son ​​equivalentes), excepto para las partes que no están bajo el control de CSS ". – ornic

5

Esta es una versión moderna basada en Totally Pwn CSS con Javascript. Es ES6, espero que no te importe.

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

Esta función devuelve un CSSStyleRule que se puede utilizar de esta manera:

var header = getCSSRule('#header'); 
header.style.backgroundColor = 'red'; 

también document.styleSheets lista de referencias de los objetos CSSStylesSheets. Otra manera de acces un sytleSheet específico en la página está asignando un Identificación al elemento estilo o enlace en el código html, y conseguir que en JavaScript utilizando document.getElementById ('mi estilo'). hoja. Estos son algunos métodos útiles:

principales navegadores e IE9 +: insertRule(), deleteRule(), removeProperty().

Major Browsers, Firefox? y IE9 +: setProperty().

<stye id="my-style" ... 
.... 
var myStyle = document.getElementById('my-style').sheet 
myStyle.insertRule('#header { background: red; }', 0); 

También es posible crear dinámicamente un nuevo elemento de estilo para almacenar estilos creados dinámicos, creo que debe ser la forma de evitar conflictos.

+0

¡Esto funciona genial! Solo agregaría comprobar si existe 'styleSheet.cssRules' antes de llamar a find en él. – sandinmyjoints

1

dar a su estilo etiqueta un identificador, como <style id="ssID"> si someonelse está haciendo sus estilos para usted decir que persona para dar la etiqueta de estilo un id - esa manera se puede acceder a él directamente sin andar a las corridas preguntando lo que su índice se

// 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]; 

} 

ahora usted tiene una tabla hash para todo en la hoja de estilo - nota de que algunos valores serán indefinido, pero no para cualquiera de las cosas que se preocupan por

Si usted tiene, por ejemplo, una clase llamada #menuItem y que desea cambiar su color a negro, hacer esto

cssHash['#menuItem'].style.color = #000; 

esa línea va a establecer el color del estilo de la regla cuyo índice fue mirado hacia arriba en la tabla hash (cssHash) con el nombre '#menuItem'

más importante aún, es probable que tenga varias diferentes clases que desea cambiar todo a la vez algo así como cuando ha cambiado las mayores en la universidad

digamos que tiene cuatro clases diferentes y que desea establecer la totalidad de sus colores de fondo en el mismo valor, que algún usuario seleccionado desde una entrada

la etiqueta del selector de color es <input id="bColor" type="color"> y las reglas de clase que desea cambiar se llaman #menuItem.homeAddr lapso y #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 
+0

Acaba de pasar, pero la mayoría de las personas aquí publican la explicación sobre su código, en lugar de como comentarios mezclados con el código. Es posible que desee considerar hacer eso en el futuro. –

+0

Esta es una idea bastante útil, pero tenga en cuenta que ss0.sheet.rules puede tener potencialmente un elemento con clave "length" e incluso podría tener "item" dependiendo del navegador, etc. – Asu

Cuestiones relacionadas