Programmatically editing Less (css) code with JQuery-like selector syntax?

此生再无相见时 提交于 2019-11-27 20:53:01

it is definitely possible, but i had to modify the less sourcecode a bit (which i think is fine, considering it's really not meant to be done :) )

i suppose everyone wants to see a demo first, click here: http://jsfiddle.net/kritzikratzi/BRJXU/1/ (script-window contains only the modified less.js-source, everything of interest is in the html window)

kk, i'll first explain my patch, usage is at the end.

patch consists of three parts

add a utility function

less.Overrides = {}; 
less.Override = function( variableName, value ){
    if( !value ){
        delete less.Overrides[variableName]; 
    }
    else{
        less.Overrides[variableName] = value; 
    }
    less.refreshStyles(); 
}; 

save the property into an object and tell less to update it's styles.

modify the parse function

   function parse(str, callback ){
        ... 

        var overrides = "\n\n"; 
        for( var key in less.Overrides ){
            overrides += key + ": " + less.Overrides[key] + ";\n"; 
        }

        str += overrides; 

all we do here is serialize the overridden properties and add them to the end of every file that is parsed.

modify the loadStyles function

    if (styles[i].type.match(typePattern) || styles[i].hasAttribute( "lessText" )) {
        var lessText; 
        if( styles[i].hasAttribute( "lessText" ) ){
            lessText = styles[i].getAttribute( "lessText" );
        }
        else{
            lessText = styles[i].innerHTML || ''; 
            styles[i].setAttribute( "lessText", lessText );
        }
    ....

by default less will replace the type parameter from <style type='text/less'> to type='text/css' and forgot about the less-source. to prevent this the original less-source is stored and loaded.

usage and conclusion

<style type="text/less">
    @color: green; 

    #header{ color: @color; }
</style>
<div id="header">i'm the header!</div>
<a href="#" onclick="less.Override('@color', 'red');">make it red</a> 

this works just fine on my computer and i have to admit it looks very neat. i haven't tested external less files, if they don't work it should be easy to fix.

i still think it's not the best idea to use this in a production environment (for reasons mentioned by others already).

While I agree with @Baz1inga that in general this would be easier to do by adding and removing classes, I also know there are certain cases where LESS-style variables work much better (e.g. if the color is sometimes foreground, sometimes background, or is lightened in certain places). This is definitely do-able; in fact, here's some tested code that will do it (minus the jQuery-style syntax; any particular reason for needing that?):

function update_css(newcss) {
    var id = "styleholder";
    if ((css = document.getElementById(id)) === null) {
        css = document.createElement('style');
        css.type = 'text/css';
        css.id = id;
        document.getElementsByTagName('head')[0].appendChild(css);
    }
    if (css.styleSheet) { // IE
        try {
            css.styleSheet.cssText = newcss;
        } catch (e) {
            throw new(Error)("Couldn't reassign styleSheet.cssText.");
        }
    } else {
        (function (node) {
            if (css.childNodes.length > 0) {
                if (css.firstChild.nodeValue !== node.nodeValue) {
                    css.replaceChild(node, css.firstChild);
                }
            } else {
                css.appendChild(node);
            }
        })(document.createTextNode(newcss));
    }
}

lessvars = {mycolor: "red"};

maincode = "div { color: @mycolor; }"; // this would be a long string, loaded via AJAX from a LESS file on the server

function compile_less(variables) {
    var variable_less = "";
    for (var variable in variables) {
        variable_less += "@" + variable + ": " + variables[variable] + ";";
    }
    new(less.Parser)({
        optimization: less.optimization
    }).parse(variable_less + maincode, function (e, root) {
        update_css(root.toCSS());
    });
}

compile_less(lessvars);

function set_less_var(name, value) {
    lessvars[name] = value;
    compile_less(lessvars);
}

The "update_css" function above is derived from the "createCSS" function in less.js; the rest I wrote. You can now, at any time, do something like this, to change the color and havethe effects appear immediately in the site content:

set_less_var("mycolor", "green");

(Note that, of course, your "maincode" should probably be loaded from .less files in the background -- I just assigned them here to variables for simplicity.)

Just for fun (as I don't recommend it) -- and to show you that I think my code does what you want -- here's a function that allows you to use the above code to do $("@mycolor").value("black");:

function $(varname) {
    return {
        value: function(val) {
            set_less_var(varname.slice(1), val);
        }
    }
}

first of all javascript can't write to a file. The best you'll be able to do is get Javascript to read and edit the XML then post that data to a server-side script to write to file.

well in general people use a different class to address this issue and replace the existing class with the new class rather than go edit the css file itself, which sounds pretty weird to me..

I stumbled upon this blogpost may be this is what you are looking for.. he shows different ways to get news stylesheets based on your requirement.

If you can do c# and want to do this server-side, the port dotless supports plugins where you implement a visitor pattern to programmatically alter the less ast before it is spit out...

it might, just might be a good idéer but if your css / html is right this shouldn't be necessary at all, you just have to css in the right way you could stack your classes if you have alot of "a" tags. If you have very big websites your customers can be quite picky about some little changes like font then its good to customize your outcome and then it is very easy to just css your way out of it, than to make more variables to make your outcome

If you wanna change 1 color your just use your find tool and use find and replace.

please just use some css & comon knowlegde to get your result the more scripts manipulating your website the more load time.

Best regards

SP

If you use the less compiler locally in your browser, there is now a feature to modify less variables:

less.modifyVars({
 '@buttonFace': '#5B83AD',
 '@buttonText': '#D9EEF2'
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!