How can I generate dynamic LESS stylesheets? - less

I want to import a variables less file that is DB generated into to be used by my other less files. This will provide some high level variables for my app. What is the best way to import these? I've tried something like #import "http://server.com/foo.less" without success.
The file would look like:
#fontColor: #EEE;
#fontSize: 10px;
Generated from
#fontColor: {{fontColor}}
#fontSize: {{fontSize}}

With Asp.net your server could dynamic generate the less file. But I think it is also possible with other techniques.
HomeController
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
public ActionResult StyleMeFromCshtml()
{
Response.ContentType = "text/css";
return View(new StyleModel());
}
Index.cshtml
<!DOCTYPE html>
<html>
<head>
<title>test less</title>
<link rel="stylesheet/less" type="text/css" href="/Home/StyleMeFromCshtml" />
<script src="~/Scripts/less-1.4.2.js"></script>
</head>
<body>
<div class="styleMeLess">
I'm styled
</div>
</body>
</html>
StyleModel.cs
public class StyleModel
{
public string BackgroundColor
{
get
{
// or get the value from the DB
var random = new Random();
var toArgb = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256));
return toArgb.Name.Remove(6, 2);
}
}
}
The StyleMeFromCshtml.cshtml is less camouflaged in cshtml
#model lessTest.Models.StyleModel
#{
Layout = null;
}
.styleMeLess{
background-color: ##Model.BackgroundColor
}
With every call of the index a random color is generated on the Server. But the color value could also come from the DB. The trick is that in the response the contentType is set "text/css".
Or you return the less string directly:
public ActionResult StyleMe()
{
var random = new Random();
var toArgb = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256));
string style = String.Format(".styleMeLess{{ background-color: #{0} }}", toArgb.Name.Remove(6,2));
return Content(style, "text/css");
}

You need to do this using the url() "function"
#import url("http://localhost/foo.less");
This will import your less file at compile time, which slows down the process depending on how fast your request is being answered.
After that, all variables in this file will be available to your current scope.
Very likely, this applies to mixins as well, but I did not test that.

Assuming you have access to server.com to get the file (and I assume you do), and that your path is correct (and I assume it is), it would appear to me that one error that needs corrected is that the file should look like (note the addition of the colons):
#fontColor: #EEE;
#fontSize: 10px;
I don't know if that means you need to change your generating code to:
#fontColor: {{fontColor}}
#fontSize: {{fontSize}}
I'm not familiar enough with what the double brackets means {{...}}, but I assume that is how the database is pulling information from it to put into the .less file that it is being generated. If so, then adding the colons there should resolve what LESS is expecting a variable to be defined like, and may solve your issue.

Related

automation of dimple.js charts with a configuration file

I wanted to be able to change the type of charts made with dimple.js using variables.
I am able to do it using local variables, set up manually, thanks to this post: change chart type in dimple.js to automate chart production
However, when I am trying to go a step further and place all my variables in a configuration file, it does no longer work anymore. I'm pretty sure I'm missing something with the "objects", but can't figure what.
Sorry, it might be an obvious thing I'm missing, but I'm a data analyst, not a developer and quite a rookie concerning d3.js and dimple.js.
My code: (see below) http://plnkr.co/McEDMkovXaQpsn5z9mmV
I have put 2 html pages : "Manual" is where it works with local variables declared manually.
"Dynamic" is the same code except I've put the variables in a configuration file and I read the configuration file using D3.csv function (a line par chart). It does not work.
Thank you for your help!
Code : http://plnkr.co/McEDMkovXaQpsn5z9mmV
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="http://dimplejs.org/dist/dimple.v2.1.0.min.js"></script>
<script type="text/javascript" src="script.js"</script>
</head>
<body>
<div id="chartContainer">
<script type="text/javascript">
var chartType1 = "bar";
var chartDimple1 = dimple.plot[chartType1];
var chartSerie1 = "Channel";
var chartGroup1 = ["Month", "Channel"];
var chartMeasure1 = "Unit Sales";
var filterField1 = "Owner";
var filterValues1 = ["Aperture", "LexCorp"];
var svg1 = dimple.newSvg("#chartContainer", 590, 400);
d3.csv("data.csv", function (data1) { //d3.tsv("data/example_data.tsv", function (data) {
var data1 = dimple.filterData(data1, filterField1, filterValues1) // dataFiltered = dimple.filterData(data, "Owner", ["Aperture", "LexCorp"])
var myChart1 = new dimple.chart(svg1, data1);
myChart1.setBounds(60, 30, 510, 305)
var x1 = myChart1.addCategoryAxis("x", chartGroup1); // var x = myChart.addCategoryAxis("x", ["Channel" , "Month"]);
x1.addOrderRule("Date");
var y1 = myChart1.addMeasureAxis("y", chartMeasure1);
myChart1.addSeries(chartSerie1, chartDimple1); // myChart.addSeries("Channel", dimple.plot.bar);
myChart1.addLegend(60, 10, 510, 20, "right");
myChart1.draw();
});
</script>
</div>
<div id="chart2"></div>
<div id="chart3"></div>
<script type="text/javascript">
pageLayout(configFile);
</script>
</body>
</html>
I'm having a tough time getting the example working, lots of files doing lots of things. I think the basic problem is that when you import the dsv config file, your group still comes back as a string like "["Month", "Channel"]". When you pass this to chart.addCategoryAxis it's going to look at it like a string rather than an array. You should be able to do
chart.addCategoryAxis(JSON.parse(d.chartGroup));
and have it correctly set it as an array. This only works if you know it's going to be an array, if it may only be one string you would need to check beforehand to know if you need to parse it or not.
Also some of the code I don't think works on that site because it's still looking for the static dsv/csv files in a data/ directory that isn't there, but I think the string/array issue is probably the one holding you up.

Get the loaded LESS file and compile it on demand

I'm trying to compile a small LESS portion of code and mixing it with a bigger one already compiled in the page.
I thought there was some way to reuse the compiled less or maybe load it again, mix it with the newer code and then compile it mixed in the page.
I thought to load it in some way like the example below:
var runtime_less = '#bg:red; .selector { background-color:#bg; }';
var library_less = '#var:bla bla bla...';
var library_parser = new(less.Parser)({
paths: ['.', './lib'], // Specify search paths for #import directives
filename: 'css/full_library.less' // Specify a filename, for better error messages
});
frontsize_parser.parse('', function (e, tree) {
library_less = tree;
});
var runtime_parser = new(less.Parser)({});
runtime_parser.parse(library_less, function (e, tree) {
// this should be inside some load event
$("#container-style").text(library_less.toCSS() + ' ' + tree.toCSS());
});
Does exist some way to get the current page loaded LESS file and treat it in some way?
Or does exist some way to load LESS files and then mix the LESS data with a string with additional LESS code?
with t.less containing:
#color: lightgreen;
You can use the following code:
<link type="text/css" href="t.less" rel="stylesheet/less">
<script>
less = {
env: "development"
};
</script>
<script src="/less.js/dist/less.js"></script>
<script>
var tmp = less.parse;
less.parse = function(input,option,callback) {
tmp(input + ' h1 {color:#color;}',option,callback);
}
less.refreshStyles();
</script>

How to show the compiled css from a .less file in the browser?

What is the best way to show the resulting css from files compiled with less.js in the client.
In other words, how can i fill a div with the resulting css?
I need to display the result on the page, any way to do this?
THanks!
update
As already pointed out in the comments by #ertrzyiks you should replace less.parse with less.render for Less v 2.x:
var lessCode = '';
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if(xmlhttp.status == 200 && xmlhttp.readyState == 4){
var options = {}
lessCode = xmlhttp.responseText;
less.render(lessCode, options, function (error, output) {
if(!error) {
document.getElementById('lesscode').innerHTML = output.css;
}
else document.getElementById('lesscode').innerHTML = '<span style="color:red">' + error + '</span>';
});
}
};
xmlhttp.open("GET","important.less",true);
xmlhttp.send();
see also: How to detect and print changing variables LESS
But since Less v2:
In the browser, less.pageLoadFinished will be a promise, resolved when
less has finished its initial processing. less.refresh and
less.modifyVars also return promises.
When you compile filename.less the compiled CSS code has been inject in a style tag with id less:filename, so to get the compilled CSS code you can also use:
less.pageLoadFinished.then(
function() {
console.log(document.getElementById('less:filename').innerHTML);
}
);
Notice that the last example also applies the compiled CSS code on the page.
--end update
I expected that running something such as the following was possible:
<link rel="stylesheet/less" type="text/css" href="important.less">
<script src="less-1.7.3.js" type="text/javascript"></script>
<script>
css = less.tree.toCSS();
console.log(css);
</script>
unfortunately this does not work, but you can use the following code to get what you want:
<script src="less-1.7.3.js" type="text/javascript"></script>
<script>
var lessCode = '';
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if(xmlhttp.status == 200 && xmlhttp.readyState == 4){
lessCode = xmlhttp.responseText;
new(less.Parser)().parse(lessCode, function (e, tree) {
document.getElementById('lesscode').innerHTML = tree.toCSS().replace(/\n/g,"<br>");
});
}
};
xmlhttp.open("GET","important.less",true);
xmlhttp.send();
</script>
With in the body section of your HTML:
<div id="lesscode"></div>
See also: Combining two .less files in one and How to open a local disk file with Javascript?
I just use Chrome's Inspect Element.
Right click on the element CSS you are looking for, Right click and choose Inspect element. On the right you will find the compiled CSS in Styles. Hope it helps
You have two options to do this, Internet Explorer or Firefox.
Let's start with Firefox. If you install the web developer toolbar, you get a menu option that's labelled CSS. Clicking on this gives you a few options and if you choose View CSS, you are taken to a new tab that shows you all of the styles for the page, grouped by their location and you should see a section with the CSS that has been generated by LESS and dynamically applied to the elements.
IE also has a Web Developer option and if you use the toolbar to inspect an element, you can then use the short cut 'Ctrl + T' which will bring up the page source with the computed styles.
The Firefox solution is better, as you can see exactly which styles have been provided by LESS whereas IE just lumps it all together.
There is a third option, and that is to compile the CSS server side!

Disqus Plugin Explanation of Dynamic Tags

So I am using the Disqus Plugin v2.65. I am trying to edit the dsq-global-toolbar at the top of the Disqus comments.
The following tags are in disqus-comment-system/comments.php
<div id="disqus_thread">
<?php if (!get_option('disqus_disable_ssr')): ?>
<?php
// if (is_file(TEMPLATEPATH . '/comments.php')) {
// include(TEMPLATEPATH . '/comments.php');
// }
?>
<div id="dsq-content">
<ul id="dsq-comments">
however on my site there are mulitple tags (the disqus-global-toolbar div) that seem to be dynamically appended between the dsq-content div and the dsq-comments ul. Where is this coming from and where can I edit this? Any help would be greatly appreciated.
I think it is coming somewhere around line 3140 in disqus.js
You can use this code to wait for the document to finish loading completely then do your changes (client side):
$(document).ready(function() {
window.disqus_no_style = true;
$.getScript('http://sitename.disqus.com/embed.js', function() {
var loader = setInterval(function() {
if($('#disqus_thread').html().length) {
clearInterval(loader);
disqusReady();
}
}, 1000);
});
function disqusReady() {
//whatever you can imagine
}
});
window.diqus_no_style can be deleted as well as the $.getsript wrapper.
Is that what you are looking for?
Something like this (use livequery instead of live):
function disqusReady() {
$('#dsq-global-toolbar').livequery(function() {
//$(this) will refer to object
});
}
Not sure what plug-in you're talking about, but if it's WordPress, I've done the same thing. Modify wp-content/plug-ins/disqus-comment-system/comments.php by adding an event handler for 'afterRender' (fires when the content ready in the DOM, but still hidden), eg. around line 70:
config.callbacks.afterRender.push(myFunctionToModifyDisqusOutput);

How to show next/previous links in Google Custom Search Engine paging links

The Google Custom Search integration only includes numbered page links and I cannot find a way to include Next/Previous links like on a normal Google search. CSE used to include these links with their previous iframe integration method.
I stepped through the javascript and found the undocumented properties I was looking for.
<div id="cse" style="width: 100%;">Loading</div>
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
google.load('search', '1', {language : 'en'});
google.setOnLoadCallback(function() {
var customSearchControl = new google.search.CustomSearchControl('GOOGLEIDGOESHERE');
customSearchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET);
customSearchControl.setSearchCompleteCallback(null,
function() { searchCompleteCallback(customSearchControl) });
customSearchControl.draw('cse');
}, true);
function searchCompleteCallback(customSearchControl) {
var currentPageIndex = customSearchControl.e[0].g.cursor.currentPageIndex;
if (currentPageIndex < customSearchControl.e[0].g.cursor.pages.length - 1) {
$('#cse .gsc-cursor').append('<div class="gsc-cursor-page">Next</div>').click(function() {
customSearchControl.e[0].g.gotoPage(currentPageIndex + 1);
});
}
if (currentPageIndex > 0) {
$($('#cse .gsc-cursor').prepend('<div class="gsc-cursor-page">Previous</div>').children()[0]).click(function() {
customSearchControl.e[0].g.gotoPage(currentPageIndex - 1);
});
}
window.scrollTo(0, 0);
}
</script>
<link rel="stylesheet" href="http://www.google.com/cse/style/look/default.css" type="text/css" />
I've been using this to find the current page:
ctrl.setSearchCompleteCallback(null, function(gControl, gResults)
{
currentpage = 1+gResults.cursor.currentPageIndex;
// or, here is an alternate way
currentpage = $('.gsc-cursor-current-page').text();
});
And now it's customSearchControl.k[0].g.cursor ... (as of this weekend, it seems)
Next time it stops working just go to script debugging in IE, add customSearchControl as a watch, open the properties (+), under the Type column look for Object, (Array) and make sure there is a (+) there as well (i.e. contains elements), open[0], and look for Type Object, again with child elements. Open that and once you see "cursor" in the list, you've got it.