2012-03-01 13 views
11

Nos gustaría convertir un estilo CSS introducido como cadena en un objeto JS.Javascript/convertir cadena de estilo CSS en el objeto JS

Por ejemplo,

var input = " border:solid 1px; color:red "; 

esperada objeto JS:

{ 
    border:"solid 1px", 
    color:"red" 
} 

Por supuesto, el número de entradas de estilo es ilimitado, así como los nombres de estilo (borde, color, tipo de letra, z-index , etc ...) Gracias.

+0

Las pruebas muestran que solo las respuestas de jAndy y mjac funcionan correctamente. Los otros se olvidaron de los espacios en blanco. – kirilloid

+0

https://jsperf.com/style-tag-to-object comparación de algunas de las respuestas publicadas – CodeToad

Respuesta

3

Se podría utilizar la función de división Javascript: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/split

Primera división de la cadena con ; como separador, y luego para cada fracción de resultado con :, la colocación de los elementos de un objeto a medida que avanza.

p. Ej.

var result = {}, 
    attributes = input.split(';'); 

for (var i = 0; i < attributes.length; i++) { 
    var entry = attributes[i].split(':'); 
    result[entry.splice(0,1)[0]] = entry.join(':'); 
} 
+4

No funcionará si hay un '':'' en el valor de CSS. P.ej. 'background-image: url ('http://example.com/image.png')'. Se solucionó dividiendo solo en el primer '':'', p. 'entry = attributes [i] .split (/:(.+)/)'. –

+0

Corto y simple, pero no maneja bien los espacios. El uso de css común tiene un espacio después de los dos puntos, por ejemplo '' background: red'' ... pero esto produce '{background: 'red'}' (observe el espacio innecesario antes de _red_) –

0

algo como esto debe obtener bastante cerca:

var input = " border:solid 1px; color:red "; 
var output = '{' + input.replace(/([\w-.]+)\s*:([^;]+);?/g, '\n $1:"$2",') + '\n}'; 

... giros

" border:solid 1px; color:red " 

en

{ 
    border:"solid 1px", 
    color:"red ", 
} 
2

En una forma funcional:

var styleInput = " border:solid 1px; color:red "; 

var result = styleInput.split(';').reduce(function (ruleMap, ruleString) { 
    var rulePair = ruleString.split(':'); 
    ruleMap[rulePair[0].trim()] = rulePair[1].trim(); 

    return ruleMap; 
}, {}); 

Recorte las cuerdas antes de usarlas como teclas de objeto.

+1

No es necesario recortar el espacio en blanco ... Se supone ... http://cl.ly/392n3b0j2U2I2f232G2S – jondavidjohn

+1

Trim no está disponible en todos los navegadores – kirilloid

+1

@jondavidjohn No todos los navegadores son iguales. '({" trimmed ": 1}). trimmed' ->' undefined' – kirilloid

2

Todas las respuestas parecen necesitar mucha división, ¿por qué no hacer una coincidencia y obtener todos los pares de una vez?

function cssSplit(str){ 
    var O= {}, 
    S= str.match(/([^ :;]+)/g) || []; 
    while(S.length){ 
     O[S.shift()]= S.shift() || ''; 
    } 
    return O; 
} 
+0

¿Qué pasa con la división? Sí, podrías argumentar que lleva (un poco) más tiempo, pero dudo que estemos hablando de miles de propiedades CSS aquí. Incluso entonces, apuesto a que su coincidencia es una intensidad computacional similar a 'S = str.split (/ [:;] + /);'. –

+1

Esta solución tomará más tiempo, porque el cambio es lento. Sin embargo, el código tiene menos tamaño. – kirilloid

+0

No use espacios en Regexp, use '\ s' en su lugar:' [^ \ s:;] ' –

0

Esta es mi función para convertir cadena de CSS para objetar:

function cssConverter(style) { 
    var result = {}, 
     attributes = style.split(';'), 
     firstIndexOfColon, 
     i, 
     key, 
     value; 

    for(i=0; i<attributes.length; i++) { 
     firstIndexOfColon = attributes[i].indexOf(":"); 
     key = attributes[i].substring(0, firstIndexOfColon); 
     value = attributes[i].substring(firstIndexOfColon + 1); 

     key = key.replace(/ /g, ""); 
     if(key.length < 1){ 
      continue; 
     } 

     if(value[0] === " "){ 
      value = value.substring(1); 
     } 

     if(value[value.length - 1] === " "){ 
      value = value.substring(0, value.length - 1); 
     } 

     result[key] = value; 
    } 

    return result; 
}; 
6

muy simple:

var regex = /([\w-]*)\s*:\s*([^;]*)/g; 
var match, properties={}; 
while(match=regex.exec(cssText)) properties[match[1]] = match[2].trim(); 

https://regex101.com/r/nZ4eX5/1

+0

Solo una nota: no debería importar mucho, pero tenga en cuenta que' match [2] 'no ser recortado en el lado derecho. :-) – nunocastromartins

+0

Editado, gracias. – shuji

0

Esta es mi opinión

function cssToObj(css) { 
 
    var obj = {}, s = css.toLowerCase().replace(/-(.)/g, function (m, g) { 
 
     return g.toUpperCase(); 
 
    }).replace(/;\s?$/g,"").split(/:|;/g); 
 
    for (var i = 0; i < s.length; i += 2) 
 
     obj[s[i].replace(/\s/g,"")] = s[i+1].replace(/^\s+|\s+$/g,""); 
 
    return obj; 
 
} 
 

 

 
console.log(cssToObj("z-index: 4; opacity:1; transition-duration: 0.3s;"));

1

sólo por diversión y para completar ...

No he comprobado la compatibilidad entre navegadores (sólo probado en Chrome), y tiene algunas peculiaridades:

var input = "font-weight:bold; color: blue; margin: 0 15px"; 

var e = document.createElement("div"); 
e.setAttribute("style", input); 

var output = {}; 

for (var i = 0; i < e.style.length; i++) { 
    var name = e.style[i]; 
    var value = e.style.getPropertyValue(name); 
    output[name] = value; 
} 

El La peculiaridad es que, aunque pasamos en una sola declaración margin, obtenemos un objeto como

{ 
    color: "blue", 
    font-weight: "bold", 
    margin-bottom: "0px", 
    margin-left: "15px", 
    margin-right: "15px", 
    margin-top: "0px", 
} 

Esto podría ser bueno o malo según lo que está buscando.