Banner

Ultima revisión 16/11/2014

Actualizar y crear hojas de estilo a través de JSON y jQuery

Una de las cosas a las que he tenido recurrir ultimamente es a utilizar plantillas personalizadas por usuario para distintos sites. Cómo muchos sabréis una de las maneras más simples es utilizar hojas de estilo dinámicas a través de PHP pero, si no podemos utilizar PHP, si por ejemplo estamos en JAVA, una de las soluciones disponibles es precisamente esta.

Para realizar esta solución, lo que vamos a crear son 2 funciones de JavaScript. Una que realizará las modificaciones solicitadas en las hojas de estilo y otra que cargará un JSON y lo utilizará como array de valores para configurar dichas hojas de estilo.

Función para la actualización de las hojas de estilo

Bien, como decía lo primero que necesitamos es crear una función que sea capaz de modificar o crear estilos dentro de una hoja de estilo. Para ello, vamos a utilizar el método de JavaScript insertRule y que, como su propio nombre indica, lo que hace es insertar reglas nuevas en las hojas de estilos.

Este método utiliza 2 parámetros:

  • regla: Es el parámetro descrito tal y como vendría definido en la hoja de estilos.
  • índice: Es un identificador numérico que indica el índice en la lista de la regla de la hoja de estilo de la regla antes que para insertar la regla especificada.

¿Y cómo funciona esto ?. La función que vamos a crear, buscará entre todas las hojas de estilo de la página, la que coincide con el nombre pasado por parámetro. Seguidamente localizará la regla a crear o modificar y, finalmente le asignará el valor solicitado.

El código quedaría así:

/**
 * Function to create / update the stylesheets definitions.
 * @author Pablo E. Fernández Casado
 * @param Sheet Name of stylesheet (styles.css, ie.css, ...)
 * @param selector Selector Name (.textFloat, #banner, ...)
 * @param property Property Name (background, color, padding, ...)
 * @param value Value of property name to assign.
 * @param priority Important or empty (Equivalent to !important)
 */
function changeStyleSheet(sheet, selector, property, value, priority){
    var sheetId = 0;
    $(document.styleSheets).each(function(id){
        try {
            if(document.styleSheets[id].href.indexOf(sheet) != -1){
                sheetId = id;
            }
        } catch (e) {}
    });

    var s = document.styleSheets[sheetId];
    var rules = s.cssRules || s.rules;
    for(var i = rules.length - 1, found = false; i >= 0 && !found; i--){
        var r = rules[i];
        if(r.selectorText == selector){
            priority = typeof priority != 'undefined' ? priority : '';
            try { r.style.setProperty(property, value, priority); } catch (e) { r.style[property] = value+(priority!=""?" !"+priority:""); }
            found = true;
        }
    }
    if(!found){
        s.insertRule(selector + '{' + property + ':' + value + ';}', rules.length);
    }
}

Lo único que hay que tener en cuenta con este código es que debe haber, por lo menos, una hoja de estilo definida en el <head> de la página y que, si no encuentra la hoja de estilos solicitada, introducirá los las reglas en la primera hoja de estilos que encuentre.

Creación del JSON como plantilla

Todos sabemos cómo es un JSON, si no podéis ir a Wikipedia y allí os lo explicará muy bien. Dicho esto, os mostraré esl JSON propuesto para el problema que nos ocupa.

{
    "styles.css":{
        ".headerStyleSheet, .footerStyleSheet":{
        "background":   	"#003366",
        "color":        	"#ffffff",
        "border":       	"2px solid #6688aa",
        "padding":      	"5px",
        "text-align":   	"center",
        "text-transform":	"uppercase"
    },
    ".articleStyleSheet":{
        "background":   "#e8e8e8",
        "color":        "#333333",
        "border":       "2px solid #cccccc",
        "margin":       "5px 0",
        "padding":      "5px"
    }
}

Como se puede observar en el JSON vamos a deminir unas pocas clases y aplicarlas a unos DIV con esos nombres..

Función de parseado de JSON y asignación de estilos

Esta función requiere 2 JSON, uno que es la personalización del usuario y otro que es el "por defecto". Con ello nos evitamos que si el del usuario tiene mal formateado de parseado o no existe, se cargue siempre el de por defecto pero, se puede hacer únicamente con uno.

Una vez recuperada la información del JSON solicitado, se recorrerá el mismo y se harán los cambios en las hojas de estilo pertinentes.

/**
 * Funtion to create stylesheets from json file.
 * @author Pablo E. Fernández Casado
 * @param template_name Template name to be loaded.
 */
function loadTemplate(template_name){
    var customValues = null;
    var unixStamp = new Date().getTime();

    $.ajax({
        url: "json/stylesheet_"+template_name+".json?t=unixStamp",
        dataType: "json",
        async:false,
        success: function (data) {
            customValues = data
        },
        error: function (data, status, errorThrown) {
            $.ajax({
                url: "json/stylesheet_default.json?t=unixStamp",
                dataType: "json",
                async:false,
                success: function (data) {
                    customValues = data
                },
                error: function (data, status, errorThrown) {
                    alert("La Plantilla no ha podido ser cargada.\n\nEstado: "+data.status + " " + data.statusText+"\nError:"+errorThrown);
                }
            });
        }
    });

    // Begin to custom
    $.each(customValues, function(styleSheet_name, styleSheet_value) {
        $.each(styleSheet_value, function(selector_name, selector_value) {
            $.each(selector_value, function(property_name, property_value) {
                changeStyleSheet(styleSheet_name, selector_name , property_name, property_value, property_value.indexOf('important')?'important':'');
            });
        });
    });
}

Demo

Header

Este es el
contenido del ejemplo...

Footer