可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
It's possible to use libraries in less.js to dynamically regenerate css from less files within the browser. If there was an easy way to modify less code, this would be an extremely powerful method of dynamically updating a site's css.
Imagine you had a colour that was used 100 times throughout a large site. If you wanted to change that color dynamically just using javascript, you would need to update every bit of css that had that colour (perhaps 50 lines of code).
With what I'm imagining all you would need to write is something like this:
$('@mainColour').value('#F04');
I'm thinking of having a go at this myself, but it sounds like a huge project and I wonder if someone has already started something like this?
edit: to clarify, ideally what I want to be able to do is take a string of Less code, programatically edit it (perhaps using a jquery-like selector syntax) and then spit it out as modified Less. Ideally the code is in Javascript (but not necessarily client side) The example I give above is one possible application but maybe not a good one (where there might be better more common ways of achieving it).
回答1:
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).
回答2:
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);
}
}
}
回答3:
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.
回答4:
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...
回答5:
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
回答6:
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'
});