User defined functions with LessCSS? - less

I have just recently gotten into LessCSS and I am running into what I feel is major limitation and I was wondering if there was a way to do this?? I want to say I read somewhere that Sass allows for user defined functions but will LessCSS do the same?
What I'm wanting to do:
#fs: 16;
// either return the value
.s(#t,#s,#u) {
// return #t/#s*#u;
}
#elem {
margin-top: .s(30,#fs,1em);
width: .s(900,#fs,1em);
.child {
width: .s(100,900,100%);
}
}
// or have a property argument
.s(#t,#s,#u,#p) {
#{p}: #t/#s*#u;
}
#elem {
.s(30,#fs,1em,margin-top);
.s(900,#fs,1em,width);
.child {
.s(100,900,100%,width);
}
}
The only way I can figure it out, but it is very limited because I have to have multiple mixins:
.s(#t,#s,#u,#p) when (#p = margin-top) { margin-top: #t/#s*#u; }
// margin[-top|-right|-bottom|-left]
// padding[-top|-right|-bottom|-left]
.s(#t,#s,#u,#p) when (#p = width) { width: #t/#s*#u; }
.s(#t,#s,#u,#p) when (#p = height) { height: #t/#s*#u; }
I know I can always modify the less.js file to add a spacing function like the built-in round() or ceil() function. But, that kills the option of compiling the .less files for production using LessPHP, Crunch, SimpLess.

As far as I know, there's no property argument: you must write it down.
That is, a function will return a calculated value or instruction(s) (property/ies and calculated values).
There aren't thousands of properties in CSS, it's not a CMS with hundreds of classes and functions, so your list won't be as long as you can imagine. You should use other CSS preprocessors or a backend language to generate your CSS if you want to do such complicated things. Or better keep it simple.
That said, lessphp allows for user functions:
lessphp has a simple extension interface where you can implement user functions that will be exposed in LESS code during the compile. They can be a little tricky though because you need to work with the lessphp type system.

Notice that you also can easily add custom functions to the default Less compiler, which enable you to use the client side less.js compiler for testing and the command line lessc compiler for production.
For Less 1.x
Download and unzip the source from github at: https://github.com/less/less.js/releases/latest
Run npm install
Open the lib/functions.js file
Add your custom function (returncenter() in this example) inside the tree.functions object, for instance as follows:
tree.functions = {
returncenter: function() {
return new(tree.Anonymous)('center');
},
//original function below
}
Run grunt dist
After the preceding step you can include dist/less-1.x.x/js in your HTML or compile your Less code with the dist/lessc compiler.
For Less 2.x
Download and unzip the source from github at: https://github.com/less/less.js/archive/master.zip
Run npm install
Create a file caleld lib/less/functions/custom.js and write down the following content into it:
var Anonymous = require("../tree/anonymous"),
functionRegistry = require("./function-registry");
functionRegistry.addMultiple({
returncenter: function() {
return new(Anonymous)('center');
}
});
Open the lib/less/function/index.js file and append require("./custom"); to the list of register functions, just before return functions;
Run grunt dist
Now you can use the following Less code:
selector {
property: returncenter();
}
The preceding Less code will compile into the following CSS code:
selector {
property: center;
}

Related

Mocha and jsdom - How to set a window variable

I know you're not supposed to do this, but I'm trying to write some tests with legacy code still using requirejs that have a few window variables floating around.
Basically I'm trying to write a mocha test and include some predefined global variables that a different file would use later. I'm trying to do the following, but it seems the global variable "container" isn't populated when accessing it later.
global.document = require('jsdom').jsdom('<html></html>');
global.window = document.defaultView;
global.$ = require('jquery')(window);
// this should be available everywhere as far as I can tell...
global.container= {};
global.window.container= global.container;
// legacy scripts still using requirejs, so we need to load the require config here
var requirejs = require('testing-setup').requirejs;
// chai is nice
require('chai').should();
describe('model tests', function () {
var model;
// before we begin the tests, we need to require in all the necessary modules
before(function (done) {
window.container= {
dateFormat: false
};
requirejs(['Model', 'common', 'date'], function (Model) {
// load some dummy data out of a file
model= new Model(require('./test-data.js').item);
done();
});
});
// run some more tests down here, I'll spare you those
});
The script being loaded called "common" above has a reference to the global "container" object that lives on the window. Apparently what I have is not correct. Is there no way to set up a shared global variable in jsdom? I know it's not the standard way of doing things, so please spare the lectures. Refactoring all that legacy code right now is not really a feasible option.
Ah, it turns out this is the correct way of doing it. It appears the jsdom/nodejs differentiate the difference between window and global. If you want something to be available everywhere in every file in that session, it needs to be on the global namespace. The window is explicitly window.

How to override dojo's domReady

I want to override dijit._CssStateMixin's domReady() method.
Is there any way to override that instead of changing the listener mechanism in Dojo.
I tried overriding _cssMouseEvent() method in simple javascript, but it still does invoke dijit's _cssMouseEvent() from domReady().
I have tried following approach:
dojoConfig = {
map: {
'dijit/_CssStateMixin': {
'dojo/domReady': 'app/noop'
}
}
};
I have added 'app' folder and then 'noop.js' inside that.
noop.js has nothing in it:
define([], function () {
return function () {};
});
Even after this I can see that dijit.js's _CssStateMaxin domReady() getting called from listener.apply (code snippet pasted below)
var addStopImmediate = function(listener){
return function(event){
if(!event.immediatelyStopped){// check to make sure it hasn't been stopped immediately
event.stopImmediatePropagation = stopImmediatePropagation;
return listener.apply(this, arguments);
}
};
}
If your ultimate goal is to prevent the domReady callback in dijit/_CssStateMixin from running, your simplest bet is likely to re-map dojo/domReady to a different module that doesn't call the callback at all, when loaded via dijit/_CssStateMixin.
NOTE: Stripping out these handlers might have adverse visual effects on Dijit widgets which inherit _CssStateMixin, since it may hinder the application of Dijit CSS classes related to hover and focus. But if your concern is that _CssStateMixin is hampering performance, it may at least be worth a try to confirm or deny your suspicion.
First we have to create a simple module that returns a function that does nothing, which we will later substitute for dojo/domReady when loaded by dijit/_CssStateMixin, so that it can still call domReady but it won't execute the callback it passes.
For simplicity's sake I'll assume you already have a custom package that you can easily add a module to; for this example I'll assume it's called app. Let's create app/noop:
define([], function () {
return function () {};
});
Now let's configure the loader to map app/noop in place of dojo/domReady specifically when loaded by dijit/_CssStateMixin:
var dojoConfig = {
...,
map: {
'dijit/_CssStateMixin': {
'dojo/domReady': 'app/noop'
}
},
...
};
Now the offending domReady callback should no longer be run.
If you're curious about map, you can read more about it in this SitePen FAQ.

how to generate css (like .E.F) using less.js compiler

I would like to generate CSS using less compiler..
Originally I have a less file and I need to prepend every rule with some class (not a nested selector)
.E{ .F{ color:blue; } }
is going to generate
.E .F{color:blue;}
In my case I don't want it to be nested but should get generated in the following way
.E.F{color:blue;}
.E {
&.F { color:blue; }
}

In SourceMod, how do I check if a plugin exists?

In SourceMod, how do I check if a plugin exists? I tried the GetFeatureStatus method, but it doesn't work. Any ideas?
If a plugin has registered itself as a Library, you can check if it exists using the LibraryExists command on the name it registered. Traditionally, this name is in all lowercase, but some plugins/extensions use mixed-case, such as SteamTools (which uses "SteamTools").
Having said that, it's generally better to cache whether a library exists instead of constantly calling this command... but then a library can be unloaded or loaded on your without your knowledge. There are functions to catch that.
So, the best way is generally to do something like this (using the NativeVotes plugin as an example).
#undef REQUIRE_PLUGIN
#include <nativevotes>
//global variable
new bool:g_bNativeVotes = false;
public OnAllPluginsLoaded()
{
g_bNativeVotes = LibraryExists("nativevotes");
}
public OnLibraryAdded(const String:name[])
{
if (StrEqual(name, "nativevotes"))
{
g_bNativeVotes = true;
}
}
public OnLibraryRemoved(const String:name[])
{
if (StrEqual(name, "nativevotes"))
{
g_bNativeVotes = false;
}
}
If a plugin isn't registered as a library, you can use GetFeatureStatus to check for a particular native. The catch is in realizing that this function doesn't return a bool, but rather a FeatureStatus_ value.
For instance, here's how I'd check for a (in development) feature for the same plugin as mentioned above:
if (GetFeatureStatus(FeatureType_Native, "NativeVotes_IsVoteCommandRegistered") == FeatureStatus_Available)
{
// Do something with vote commands.
}

How may I pass a variable to :extend when using Less?

I would like to use a variable within a Less mixin that when passed to :extend has the same result as if I had instead used :extend with a class name string.
In the example below I have commented out a line that produces the CSS output I want by using :extend with a string.
But how can I do this with the #class-name variable instead?
.class-to-be-extended {display: block;}
.my-mixin (#class-name) {
#class-string: ~".#{class-name}";
.my-extra-class {
// &:extend(.class-to-be-extended); // works
&:extend(#{class-string}); // doesn't work, but no errors
}
}
.my-mixin(class-to-be-extended);
The CSS output I would like is:
.class-to-be-extended,
.my-extra-class {
display: block;
}
At the time of writing this I'm using the latest version I can find which is Less 1.4.2
This is not possible with Less version 1.4.2. (Thanks to Jon Schlinkert for letting me know via Twitter).
A feature request has been submitted to https://github.com/less/less.js/issues