Adding an External Tool for Compiling LESS files in WebStorm (on Windows)

Interested in converting/compiling LESS files into their CSS counterparts?

Here are the steps (from version 4 of WebStorm from JetBrains).

1. Install Node JS

2. Install the node package (using npm) for less (remember where you install this as you’ll need the path later):

    npm install less

3. In WebStorm, File > Settings, then under the IDE Settings heading, select External Tools.

4. Click on the + icon to add a new tool:

image

5. You’ll see a dialog very much like this:

SNAGHTMLcd7f5f5

6. Fill it out like this (substitute whatever you’d like of course):

SNAGHTMLceae4a7

I chose not to have the console window open every time the compilation occurs.

The only things you’ll need to change is the path to the file lessc. That file is actually JavaScript file (minus the extension). So, replace the first quoted parameter in “Parameters” above with the location that you installed the package for less in.

As it’s a JavaScript file you need to be executed, the “Program” is set to the node executable. Provide the full path (when I didn’t, it sometimes wouldn’t work and would complain that a path didn’t exist).

"###YOUR PATH TO LESSC###\lessc" $FilePath$ "$FileDir$\$FileNameWithoutExtension$.css"

I tried using the Working Directory option and it also worked inconsistently with Node. So, I used the options you see above and it seemed to work more consistently.

7. I also added a shortcut so I could execute it on demand:

SNAGHTMLcdbd3f4

SNAGHTMLcdc51ca

I picked Ctrl+Alt+L, as it was memorable (and available!).

While this is not using a file watcher technique (you could do that if you’d like instead), it works well enough for my workflow.

Backup Reminder for Windows Home Server 2011

This is just a reminder to anyone who uses Windows Home Server’s Backup functionality to verify Backups are working.

I love the “turn it on and forget about it” feature of WHS backup. Computers automatically wake, backup, and sleep. Nice.

However, I noticed last week that at some point WHS2011 had an issue more than a month ago where it no longer was backing up ANY of the Windows PCs in our house (2 laptops, 2 desktops).

No actionable errors had occurred in March that I could find, so I can’t pinpoint a reason. I needed to go to every Windows PC in our house and re-enable backups. Thankfully, it didn’t need to start over from scratch (it picked up where it left off).

image

Needless to say, having your computer backups silently fail is a bit worrisome. As many WHS2011 users likely don’t routinely go to the WHS dashboard – you might want to occasionally and check that every thing is OK.

I don’t use the LAUNCHPAD much as it tends to be the “software who cried wolf” too often. But, even if I had, I couldn’t see any indication in the Dashboard that I would have been alerted to this issue (since alerts are all saved until resolved or ignored).

SNAGHTML7ba7bdb

(The two warnings shown in the screenshot are for: “Important updates should be installed.” and “Free space is low.” AKA, A drive has only 62GB free (10%)).

If you do use the LAUNCHPAD, you can verify the last backup by clicking the “Backup” button. You should see something like this in the dialog that is opened:

image

SVG Setting Text Content Dynamically

Continuing on a theme of animating SVG, I’ve added a label in the center of the animation which contains the current angle of the ever-rotating marker (in fact in a centered horizontally and vertically SVG text node).

(Click image below to try it.)

image

At the bottom of the file from the previous post, I’ve added the following:

    <text id="currentValueAsText" x="300" y="300" 
        style="text-anchor: middle;alignment-baseline:middle" 
        fill="#FFFFFF" font-family="'Arial'" font-size="96" opacity=".6">0</text>

It’s a new text node. It’s set to centered both horizontally and vertically (using the text-anchor and alignment-baseline style properties respectively) at 300,300.

Setting the content is simple as well:

(function () {
    window.onload = loaded;
    function loaded() {
        var colorTemp = document.getElementById("color-temp");
        var reading = document.getElementById('current-reading');
        var currentVal = document.getElementById("currentValueAsText");
        var currentAngle = 0;
        var fill;

        var direction = 1;
        setInterval(function () {
            currentAngle += direction;
            if (currentAngle >= 120 || currentAngle <= -120) {
                direction *= -1;
            } else if (currentAngle === 0) {
                fill = direction === 1 ? "#BE1E2D" : "#10A2DC";
                colorTemp.setAttribute("fill", fill);
            }
            // adjust the opacity
            colorTemp.setAttribute("opacity", Math.abs(currentAngle) / 120.0);
            reading.setAttribute("transform", "rotate(" + currentAngle + ")");
            currentValueAsText.textContent = currentAngle.toString();

        }, 25);
    }
})();

Use the textContent property of the SVG text node to set the text.

Done. Smile

Spinning SVG Animation

Interested in learning a few capabilities of SVG animation this evening from JavaScript in a web page, I put together a simple demonstration.

Click on the image to launch the demo.

image

Animating SVG in a modern browser (including IE9) is generally easy enough. This example was slightly more interesting in that I wanted the thicker line to rotate based on the center point of the image, rather than the location of the line itself.

Not what I wanted:

image

Desired rotation:

image

The white bar would rotate around the center point (marked by the red arrow above).

I’ve included all of the code at the bottom of the post. (There’s quite a lot of path information).

The JavaScript just used an interval to move the line around the point:

(function () {
    window.onload = loaded;
    function loaded() {
        var colorTemp = document.getElementById("color-temp");
        var reading = document.getElementById('current-reading');
        var currentAngle = 0;
        var fill;

        var direction = 1;
        setInterval(function () {
            currentAngle += direction;
            if (currentAngle >= 120 || currentAngle <= -120) {
                direction *= -1;
            } else if (currentAngle === 0) {
                fill = direction === 1 ? "#BE1E2D" : "#10A2DC";
                colorTemp.setAttribute("fill", fill);
            }
            // adjust the opacity
            colorTemp.setAttribute("opacity", Math.abs(currentAngle) / 120.0);

            reading.setAttribute("transform", "rotate(" + currentAngle + ")");

        }, 25);
    }
})();

The angle is fixed between 120 and –120 degrees. When the angle reaches zero, the fill color is toggled.

As the angle adjusts, the line is updated as well as the opacity of the fill.

The overall size of the SVG drawing is 600×600. Knowing that (and wanting the exact center), I translated a group to an offset of 300x, 300y containing the line:

<g id="temp-transform" transform="translate(300,300)">
        <line id="current-reading" fill="none" stroke="#FFFFFF"
              stroke-width="5" stroke-linecap="round"
              stroke-miterlimit="10" x1="0" y1="-180" x2="0" y2="-120"/>
</g>

This effectively made the rotation now work from the center, once the line coordinates were adjusted to reflect the new translation.

This works because the contents of the outer group caused the new starting point (origin) to be 300x, 300y rather than the default 0x, 0y. You can see the line is from y –120 to y –180. That’s because I wanted the line to start in the top middle (as the x is set to 0 for the line).

I used Adobe Illustrator CS 5.5 to create the SVG image. Illustrator typically does not always handle fonts well when exporting as SVG. The final text node was this:

<text transform="matrix(1 0 0 1 254.1387 83.3198)" fill="#D1D3D4" font-family="'Arial'"
font-weight="bold" font-size="29.4616">thermo</text>

To make it work across browsers, I needed to modify the text node below slightly. Note the font name and missing bold attribute. It’s not a hard switch, but it’s annoying if you need to make changes to your SVG multiple times.

<text transform="matrix(1 0 0 1 254.1387 83.3198)" fill="#D1D3D4" 
font-family="'Arial-BoldMT'" font-size="29.4616">thermo</text>

If you have any questions, please leave a comment!

<!DOCTYPE HTML>
<html>
<head>
    <title>Svg Spinner Demo</title>
    <style>
        #demo1 svg {
            width: 300px;
            height: 300px;
        }

    </style>
</head>
<body>

<div id="demo1">
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="600px" height="600px" viewBox="0 0 600 600" enable-background="new 0 0 600 600" xml:space="preserve">
<g>
    <radialGradient id="SVGID_1_" cx="298.9106" cy="196.146" r="399.267" gradientUnits="userSpaceOnUse">
        <stop  offset="0" style="stop-color:#D9D9D9"/>
        <stop  offset="1" style="stop-color:#C2C2C2"/>
    </radialGradient>
    <path fill="url(#SVGID_1_)" d="M300.646,595.41c-78.957,0-153.188-30.747-209.02-86.579C35.795,453,5.048,378.77,5.048,299.812
        c0-78.957,30.748-153.188,86.579-209.02S221.689,4.214,300.646,4.214c78.958,0,153.188,30.748,209.019,86.579
        c55.832,55.831,86.579,130.063,86.579,209.02c0,78.958-30.747,153.188-86.579,209.019
        C453.834,564.663,379.604,595.41,300.646,595.41z"/>
    <path fill="#808285" d="M300.646,6.214c39.637,0,78.086,7.762,114.281,23.071c34.961,14.787,66.359,35.957,93.324,62.922
        s48.135,58.364,62.923,93.325c15.309,36.193,23.07,74.643,23.07,114.28s-7.762,78.086-23.07,114.281
        c-14.788,34.961-35.958,66.359-62.923,93.324s-58.363,48.135-93.324,62.923c-36.194,15.309-74.644,23.07-114.281,23.07
        s-78.087-7.762-114.28-23.07c-34.961-14.788-66.36-35.958-93.325-62.923s-48.135-58.363-62.922-93.324
        C14.81,377.898,7.048,339.449,7.048,299.812s7.762-78.087,23.071-114.28c14.787-34.961,35.957-66.36,62.922-93.325
        s58.364-48.135,93.325-62.922C222.559,13.976,261.009,6.214,300.646,6.214 M300.646,2.214
        C136.287,2.214,3.048,135.453,3.048,299.812S136.287,597.41,300.646,597.41s297.598-133.239,297.598-297.598
        S465.005,2.214,300.646,2.214L300.646,2.214z"/>
</g>
<g>
    <radialGradient id="SVGID_2_" cx="299.0464" cy="204.2632" r="368.0053" gradientUnits="userSpaceOnUse">
        <stop  offset="0" style="stop-color:#141414"/>
        <stop  offset="1" style="stop-color:#080808"/>
    </radialGradient>
    <path fill="url(#SVGID_2_)" d="M300.646,572.266c-72.775,0-141.194-28.34-192.654-79.8c-51.459-51.46-79.8-119.879-79.8-192.654
        s28.34-141.194,79.8-192.654s119.879-79.8,192.654-79.8s141.194,28.34,192.654,79.8c51.46,51.46,79.8,119.879,79.8,192.654
        s-28.34,141.194-79.8,192.654S373.421,572.266,300.646,572.266z"/>
    <path d="M300.646,29.358c36.512,0,71.931,7.15,105.271,21.252c32.205,13.622,61.129,33.123,85.968,57.962
        c24.84,24.839,44.341,53.763,57.963,85.968c14.102,33.34,21.252,68.759,21.252,105.271c0,36.512-7.15,71.931-21.252,105.271
        c-13.622,32.205-33.123,61.129-57.963,85.968c-24.839,24.84-53.763,44.341-85.968,57.963
        c-33.34,14.102-68.759,21.252-105.271,21.252c-36.513,0-71.931-7.15-105.271-21.252c-32.205-13.622-61.129-33.123-85.968-57.963
        c-24.839-24.839-44.34-53.763-57.962-85.968c-14.102-33.34-21.252-68.759-21.252-105.271c0-36.513,7.15-71.931,21.252-105.271
        c13.622-32.205,33.123-61.129,57.962-85.968s53.763-44.34,85.968-57.962C228.715,36.509,264.133,29.358,300.646,29.358
         M300.646,25.358c-151.577,0-274.454,122.877-274.454,274.454c0,151.576,122.877,274.454,274.454,274.454
        c151.576,0,274.454-122.878,274.454-274.454C575.1,148.235,452.222,25.358,300.646,25.358L300.646,25.358z"/>
</g>
<g>
    <radialGradient id="SVGID_3_" cx="299.5176" cy="232.4409" r="259.4771" gradientUnits="userSpaceOnUse">
        <stop  offset="0" style="stop-color:#212121"/>
        <stop  offset="1" style="stop-color:#0D0D0D"/>
    </radialGradient>
    <path fill="url(#SVGID_3_)" d="M300.646,491.916c-105.927,0-192.104-86.178-192.104-192.104
        c0-105.927,86.178-192.104,192.104-192.104c105.926,0,192.104,86.178,192.104,192.104
        C492.75,405.738,406.572,491.916,300.646,491.916z"/>
    <path d="M300.646,109.708c25.666,0,50.561,5.026,73.996,14.938c22.638,9.575,42.968,23.283,60.429,40.743
        c17.46,17.46,31.167,37.791,40.742,60.428c9.912,23.435,14.938,48.331,14.938,73.996s-5.025,50.561-14.938,73.996
        c-9.575,22.638-23.282,42.968-40.742,60.429c-17.461,17.46-37.791,31.167-60.429,40.742c-23.435,9.912-48.33,14.938-73.996,14.938
        s-50.562-5.025-73.996-14.938c-22.637-9.575-42.968-23.282-60.428-40.742c-17.46-17.461-31.168-37.791-40.743-60.429
        c-9.912-23.435-14.938-48.33-14.938-73.996s5.026-50.562,14.938-73.996c9.575-22.637,23.283-42.968,40.743-60.428
        s37.791-31.168,60.428-40.743C250.084,114.733,274.98,109.708,300.646,109.708 M300.646,105.708
        c-107.201,0-194.104,86.903-194.104,194.104c0,107.201,86.903,194.104,194.104,194.104c107.201,0,194.104-86.903,194.104-194.104
        C494.75,192.611,407.847,105.708,300.646,105.708L300.646,105.708z"/>
</g>
<g opacity="0.8">
    <path id="color-temp" fill="#BE1E2D" opacity="0" d="M300.646,489.309c-104.489,0-189.497-85.008-189.497-189.497c0-104.489,85.008-189.497,189.497-189.497
        c104.489,0,189.497,85.008,189.497,189.497C490.143,404.301,405.135,489.309,300.646,489.309z"/>
    <path d="M300.646,110.815c25.515,0,50.266,4.997,73.566,14.852c22.505,9.519,42.718,23.146,60.075,40.504
        s30.984,37.57,40.504,60.075c9.854,23.3,14.852,48.051,14.852,73.566s-4.997,50.266-14.852,73.566
        c-9.52,22.505-23.146,42.718-40.504,60.075s-37.57,30.984-60.075,40.504c-23.3,9.854-48.051,14.852-73.566,14.852
        s-50.266-4.997-73.566-14.852c-22.505-9.52-42.718-23.146-60.075-40.504s-30.985-37.57-40.504-60.075
        c-9.855-23.3-14.852-48.051-14.852-73.566s4.997-50.266,14.852-73.566c9.519-22.505,23.146-42.718,40.504-60.075
        s37.57-30.985,60.075-40.504C250.38,115.812,275.131,110.815,300.646,110.815 M300.646,109.815
        c-104.933,0-189.997,85.064-189.997,189.997c0,104.932,85.064,189.997,189.997,189.997c104.932,0,189.997-85.064,189.997-189.997
        C490.643,194.879,405.578,109.815,300.646,109.815L300.646,109.815z"/>
</g>
<g id="temperature-markings">
        <line fill="none" stroke="#C7C8CA" stroke-width="5" stroke-miterlimit="10"
              x1="300.646" y1="123.751" x2="300.646" y2="161.603"/>
        <line fill="none" stroke="#C7C8CA" stroke-width="5" stroke-miterlimit="10"
              x1="422.102" y1="371.971" x2="454.881" y2="390.896"/>
        <line fill="none" stroke="#C7C8CA" stroke-width="5" stroke-miterlimit="10"
              x1="146.41" y1="390.896" x2="179.191" y2="371.97"/>
</g>
<g id="temp-transform" transform="translate(300,300)">
        <line id="current-reading" fill="none" stroke="#FFFFFF"
              stroke-width="5" stroke-linecap="round"
              stroke-miterlimit="10" x1="0" y1="-180" x2="0" y2="-120"/>
</g>
    <text transform="matrix(1 0 0 1 254.1387 83.3198)" fill="#D1D3D4" font-family="'Arial'"
          font-weight="bold" font-size="29.4616">thermo</text>
</svg>


</div>


<script type="text/javascript">

    (function () {

        window.onload = loaded;

        function loaded() {
            var colorTemp = document.getElementById("color-temp");
            var reading = document.getElementById('current-reading');
            var currentAngle = 0;
            var fill;

            var direction = 1;
            setInterval(function () {
                currentAngle += direction;
                if (currentAngle >= 120 || currentAngle <= -120) {
                    direction *= -1;
                } else if (currentAngle === 0) {
                    fill = direction === 1 ? "#BE1E2D" : "#10A2DC";
                    colorTemp.setAttribute("fill", fill);
                }
                // adjust the opacity
                colorTemp.setAttribute("opacity", Math.abs(currentAngle) / 120.0);

                reading.setAttribute("transform", "rotate(" + currentAngle + ")");

            }, 25);
        }
    })();


</script>
</body>
</html>

Nest Thermostat, Software Update 2.0

Nest recently released a new update to the software of the thermostat device (as well as their corresponding web and mobile applications).

Some of the details may be found on their blog.

A few of the new features include an historical view of the heating/cooling usage:

image

On Friday, April 6th for example, you can see when the heat turned on and what the set points were for the day for my First Floor thermostat. The data isn’t as interesting during our Midwest Spring as the furnace doesn’t run nearly as much.

Here’s from another day:

image

I doubt I’ll use this feature much. It only has 10 days of information available apparently right now, so I just can’t see this being very useful. I’m skeptical that this will affect my choices as it comes to how we use our HVAC system. I could see potentially how aggregate data of many users (in a similar geographical area) could become more compelling and potentially a source of data that Nest might be able to sell.

The settings for a thermostat have been tweaked visually. The same basic data is available as before:

image

The learning tab has been cleaned up as well:

image

For some reason, our thermostat that we’ve had for four months is apparently still in training (Time to Temp). That seems like an issue that maybe I’ll look into. Although I don’t really care much about the “time to temp” feature normally as I don’t manually adjust the affected thermostat much.

The “Away” tab changed:

image

Not a big improvement for usability. Probably more touch friendly (and it’s logically correct as it heats when less than 58 degrees for example), but it feels wrong. Thermostats aren’t normally left to right oriented (temp goes up and down), so this breaks a typical UX model.

On the Equipment tab, they’ve tweaked the UI as well:

image

I clicked on the Safety Temp word (? it’s not a button, nor a link, so I don’t know what to call it) and the above UI displayed. The same temperature range UX is displayed, but here I like it even less. I suppose we don’t have a maximum temperature in the house during cooling season, but this is clunky. (And given that it’s safety related, I wish it were more clear). I can hear some of you say, “but it’s clear to me.” I do understand it, but I’m confident there is a better way of displaying and adjusting these temperatures that would be more obvious.

(And Nest Labs, go ahead and spell out “TEMP” please? Thanks!)

The technical info tab is the same basically.

There’s now a lock feature (which I have no need for, and am not going to experiment with right now):

image

One of the big new TM’ed features is called Airwave™. Apparently, when it’s hot and the humidity is low (not typical for Wisconsin, as our summers are usually hot and humid), the thermostat apparently will try to do more cooling by turning off the air conditioning system early and using the fan more. (I always thought our air conditioner already did that as the compressor turns off before the fans). If it helps lower our electricity bill, awesome. I’ll report back if I can tell that it is working and helping (without historical data though, it will be difficult for us, especially as we added solar panels to our house last fall).

The scheduling tab looks basically unchanged. The support tab has more content, so you don’t have to go to their web site to read the information. That’s a nice improvement.


OK, this was very strange. As I was writing this post (and in the middle of using the application), I saw the following:

image

image

image

Now, the thermostats are all disconnected in some odd way:

image

A few minutes later, things improved (but not perfect):

image 

Twenty minutes later, the BASEMENT thermostat is still disconnected. I reset the thermostat and it’s back now.