LESS: Mixin with optional parameter - less

I have a LESS mixin with this code:
.generated_width (#margins:40px)
{
-webkit-width:calc(~"100% - " #margins );
-moz-width:calc(~"100% - " #margins );
width:calc(~"100% - " #margins );
}
But sometimes I need to OPTIONALLY specify a % width different, for example "50%". Obviously, I could create another specific, but different, mixin with "50%" replacing "100%", but I prefer to pass this value as a parameter.
Is there a way to edit my mixin in order to OPTIONALLY accept a parameter that overrides default value of "100%" ? In other words, sometime the call could be:
.generated_width (40px)
Others
.generated_width (50%,40px)

So you have
.generated_width (#margins: 40px, #per: 100%)
{
-webkit-width:calc(~"#{per} - " #margins );
-moz-width:calc(~"#{per} - " #margins );
width:calc(~"#{per} - " #margins );
}
When called
.generated_width (40px)
.generated_width (40px, 40%)
I think depending on your LESS version you can also do
.generated_width (#per:40%)
This way you can specify as many optional parameters as you want. This is much more flexible but a little bit more code to type. So if you only have 1 optional param then just leave it at the last spot

Related

Ambiguous expression could be either a parameterless closure expression or an isolated open code block;

I'm having the following code block which will create an object with is concatenated string of all objects within "basixCertificateNumbers" array.
def object= jsonSlurper.parseText '''
{
"basixCertificateNumbers": [
{
"basixCertificateNumber": "012-012"
},
{
"basixCertificateNumber": "045-123"
}
]
}
'''
def concatdObj = jsonSlurper.parseText '''
{
"basixNumber" : ""
}
'''
def content = object.each{ entry->
if(entry.value.getClass().name === "java.util.ArrayList"){
for (basixIndex = 0 ; basixIndex < entry.value.size(); basixIndex++){
entry.value[basixIndex].each{ nestedEntry->{
concatdObj.basixNumber = concatdObj.basixNumber + nestedEntry.value + " "
}}
}
concatdObj.basixNumber = concatdObj.basixNumber.substring(0, concatdObj.basixNumber.length() - 1);
}}
I'm currently receiving the following errors:
Ambiguous expression could be either a parameterless closure expression or an isolated open code block;
solution: Add an explicit closure parameter list, e.g. {it -> ...}, or force it to be treated as an open block by giving it a label, e.g. L:{...} # line 41, column 56.
asixIndex].each{ nestedEntry->{
^
Even though the solution suggested is to put the label on it, I'm not sure where would be the optimal way to put it.
The current solution would be remove the "{" after nestedEntry, which will be something like this:
entry.value[basixIndex].each{ nestedEntry->
concatdObj.basixNumber = concatdObj.basixNumber + nestedEntry.value + " "
}
However, I believe this is not an optimal way of doing things, so if anyone would have a better idea. It would be a great help!
My desire output would be:
{
"basixNumber" : "012-012 045-123"
}
You can just do
def content = [
basixNumber: object.basixCertificateNumbers.basixCertificateNumber.join(' ')
]
String jsonOutput = new JsonOutput().toJson(content)
You don't need concatdObj

How do you model a path parameter in the middle with http4k

I am using http4k-contracts and I am trying to model a route with a path parameter in the middle of the path, i.e.
This is the path: /player/{id}/match
This is my code (does not compile): "/player/" / Path.string().of("id") / "match" meta { ..
Whats the right way to do it?
If this doesn't compile, it probably means that the function on the end of that statement doesn't have enough parameters. You need something like this - notice the "dead" parameter in the middle of the lambda where the string "foo" would be injected:
"/prefix" / Path.of("first") / "foo" / Path.of("second")
bindContract GET to { first, _, second -> {
Response(OK).body("$first $second") }
}
Trailing parameters work in exactly the same way, so by extrapolation you'd need this:
val route = "/prefix" / Path.of("first") / "foo" meta { description = "I am great"} bindContract GET to { first, _ -> { Response(OK).body(first) } }
For adding the meta tags, you can easily get tripped up by the infix whitespace, so try playing with the line breaks if it doesn't compile.

LESS CSS grid mixin

I have this piece of LESS code:
.generate-spans(#columns; #prefix; #current: 1) when (#current =< #columns) {
.span-#{prefix}-#{current} {
width: (#current/#columns*100%);
}
.generate-spans(#columns, #prefix, (#current + 1));
}
.generate-spans(12, "large");
It is suppose to generate something like this:
.span-large-1 {
width: 8.333333333333332%%;
}
.span-large-2
width: 16.666666666666664%;
}
.....
But it just returns error: Operation on an invalid type in ....
How do i make the code work as intended?
Your code works in Less 1.7.0. Try it here: http://lesstester.com/
The only typo is the name in quotes, which you should remove:
.generate-spans(12, large);
And that fix might also make it work in the version of Less that you are using.
If for some reason you have to use quotes, you can also try:
.generate-spans(12, ~"large");
Which will remove the quotes from the resulting CSS.

In VTD-XML how to add new attribute into tag with existing attributes?

I'm using VTD-XML to update XML files. In this I am trying to get a flexible way of maintaining attributes on an element. So if my original element is:
<MyElement name="myName" existattr="orig" />
I'd like to be able to update it to this:
<MyElement name="myName" existattr="new" newattr="newValue" />
I'm using a Map to manage the attribute/value pairs in my code and when I update the XML I'm doing something like the following:
private XMLModifier xm = new XMLModifier();
xm.bind(vn);
for (String key : attr.keySet()) {
int i = vn.getAttrVal(key);
if (i!=-1) {
xm.updateToken(i, attr.get(key));
} else {
xm.insertAttribute(key+"='"+attr.get(key)+"'");
}
}
vn = xm.outputAndReparse();
This works for updating existing attributes, however when the attribute doesn't already exist, it hits the insert (insertAttribute) and I get "ModifyException"
com.ximpleware.ModifyException: There can be only one insert per offset
at com.ximpleware.XMLModifier.insertBytesAt(XMLModifier.java:341)
at com.ximpleware.XMLModifier.insertAttribute(XMLModifier.java:1833)
My guess is that as I'm not manipulating the offset directly this might be expected. However I can see no function to insert an an attribute at a position in the element (at end).
My suspicion is that I will need to do it at the "offset" level using something like xm.insertBytesAt(int offset, byte[] content) - as this is an area I have needed to get into yet is there a way to calculate the offset at which I can insert (just before the end of the tag)?
Of course I may be mis-using VTD in some way here - if there is a better way of achieving this then happy to be directed.
Thanks
That's an interesting limitation of the API I hadn't encountered yet. It would be great if vtd-xml-author could elaborate on technical details and why this limitation exists.
As a solution to your problem, a simple approach would be to accumulate your key-value pairs to be inserted as a String, and then to insert them in a single call after your for loop has terminated.
I've tested that this works as per your code:
private XMLModifier xm_ = new XMLModifier();
xm.bind(vn);
String insertedAttributes = "";
for (String key : attr.keySet()) {
int i = vn.getAttrVal(key);
if (i!=-1) {
xm.updateToken(i, attr.get(key));
} else {
// Store the key-values to be inserted as attributes
insertedAttributes += " " + key + "='" + attr.get(key) + "'";
}
}
if (!insertedAttributes.equals("")) {
// Insert attributes only once
xm.insertAttribute(insertedAttributes);
}
This will also work if you need to update the attributes of multiple elements, simply nest the above code in while(autoPilot.evalXPath() != -1) and be sure to set insertedAttributes = ""; at the end of each while loop.
Hope this helps.

CI active record, escapes & order_by datetime column

I've noticed that when ordering by a datetime column in CI with active record, it's treating the column as a string, or int.
Example:
$this->db->limit(12);
$this->db->where('subscribed',1);
$this->db->join('profiles','profiles.user_id=users.id');
$this->db->where('active',1);
$this->db->select('users.thumbUpload,users.vanity_url');
$this->db->select('users.created_on as time');
$this->db->order_by('time');
$query = $this->db->get('users');
This is where users.created_on is a datetime field. Firstly, is it because active record is rendering time escaped, or is it something else? And if it is, can I prevent the escaping on order_by somehow?
Also, stackoverflow, please stop autocorrecting 'datetime' to 'date time'. It's annoying.
Cheers!
When you set second argument as false, function wont check and escape string. Try this
$this->db->select('users.created_on as time', FALSE);
Or for you query use
$this->db->order_by('users.created_on', 'DESC'); //or ASC
And for complex queries
$this->db->query("query");
According to the signature of the method in core files of CI (currently 2.2), it does not have any option to allow to choose whether or not to escape.
// The original prototype of the order_by()
public function order_by($orderby, $direction = '') {
// Definition
}
As you see there is not argument as $escape = true in the argument list. One way to do so is to hack this core file (I normally do not suggest it, since if you upgrade CI to a newer version later, then these changes will be lost, but if you do not intend to do so, it is OK to use it).
To do so, first change the prototype as:
public function order_by($orderby, $direction = '', $escape = true) {
// Definition
}
And then check the conditions in the following parts of definition:
// Line 842
if($escape){
$part = $this->_protect_identifiers(trim($part));
}else {
$part = trim($part);
}
// Line 856
if($escape){
$orderby = $this->_protect_identifiers($orderby);
}
When you call it, to prevent the escaping:
$this->db->order_by($ORDERBY_CLAUSE, null, false);