How to change the font size in Chrome Developer Tools

When presenting on JavaScript or jQuery I’ll typically spend a lot of time in the Chrome Developer Tools window at the console. The problem is that, depending on the projection facilities and the resolution the fonts can be too small to read.

The Chrome devtools themselves are built out of HTML and CSS so I started digging for how I could edit the stylesheet. You can view the default devtool stylesheet by navigating to chrome-devtools://devtools/devTools.css. You can’t easily edit this though (it’s probably buried as a resource within Chrome), but you can override its styles using the standard custom user stylesheet Custom.css!

Custom.css lives at:

  • Windows: C:\Users\<user>\AppData\Local\Google\Chrome\User Data\Default\User StyleSheets
  • Mac OS X: ~/Library/Application Support/Google/Chrome/Default/User Stylesheets/

The style(s) to add and override in Custom.css are:

body.platform-mac .monospace, body.platform-mac .source-code {
    font-family: Monaco, monospace;
}

/* Keep .platform-mac to make the rule more specific than the general one above. */
body.platform-mac.platform-mac-snowleopard .monospace,
body.platform-mac.platform-mac-snowleopard .source-code {
    font-size: 11px !important;
    font-family: Menlo, monospace;
}

body.platform-windows .monospace, body.platform-windows .source-code {
    font-size: 12px !important;
    font-family: Consolas, Lucida Console, monospace;
}

body.platform-linux .monospace, body.platform-linux .source-code {
    font-size: 11px !important;
    font-family: dejavu sans mono, monospace;
}

A nice touch is that the styles update automatically as you save Custom.css so you can tweak it on the fly to get the right font-size for your audience.

Chrome DevTools with a larger font-size

Hope that helps!

LESS + CoffeeScript for ASP.NET = LessCoffee

As documented in recent posts, I’ve been tinkering getting the LESS and CoffeeScript compilers running on Windows Script Host. I’ve now got round to wrapping these up as ASP.NET HTTP Handlers so you can easily use them in ASP.NET-based websites. You simply reference the *.less and *.coffee files and they get served up as CSS and JavaScript directly. For example:

<link href="content/style.less" rel="stylesheet">
<script src="content/site.coffee"></script>

No need to install add-ins into Visual Studio or add build steps to your project. The main downside is that it won’t run on non-Windows platforms under Mono (although I’m tempted adapt it to use Mozilla’s SpiderMonkey JavaScript Shell).

If you’re running Visual Studio 2010 then simply use the LessCoffee NuGet package.

PM> Install-Package LessCoffee

If you’re using Visual Studio 2008 you’ll need follow these manual steps:

  • Copy LessCoffee.dll to your web application’s /bin directory
  • Add the following entries to your web.config file:
    <system.web>
        <httpHandlers>
            <add path="*.coffee" type="DotSmart.CoffeeScriptHandler, LessCoffee" verb="*" validate="false"/>
            <add path="*.less" type="DotSmart.LessCssHandler, LessCoffee" verb="*" validate="false"/>
        </httpHandlers>
    </system.web>

    <!-- IIS 7 -->
    <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
        <handlers>
            <add path="*.coffee" type="DotSmart.CoffeeScriptHandler, LessCoffee" verb="*" name="DotSmart.CoffeeScriptHandler"/>
            <add path="*.less" type="DotSmart.LessCssHandler, LessCoffee" verb="*" name="DotSmart.LessCssHandler"/>
        </handlers>
    </system.webServer>

If you’re using Windows 2003/IIS 6 then you will need to map the file extensions *.less and *.coffee to aspnet_isapi.dll.

The source is on GitHub, obv: https://github.com/duncansmart/LessCoffee

The simplest way to compile CoffeeScript on Windows

tl;dr: You can compile CoffeeScript on Windows with zero third-party dependencies.

A while back I did a post on running the LESS.js compiler on Windows using the venerable and ubiquitous Window Script Host (WSH: providing JavaScript console scripting since Windows 98… when John Resig was still in 8th grade). At the time I tried something similar to generate JavaScript from the wonderful CoffeeScript language, but I couldn’t get it working due to what I assumed were shortcomings in WSH’s JScript engine. There are plenty of other options out there for compiling CoffeeScript, but incur various third-party dependencies as detailed in this StackOverflow question.

But on a whim the other day I revisited it and thankfully now it does work on plain old WSH without any coaxing (not sure what changed, or what I was doing wrong last time). I took the full browser-based coffee-script.js and wrapped it with a simple *.wsf and batch file to handle command-line options.

Download

It’s on github, natch: https://github.com/duncansmart/coffeescript-windows

Usage

To use it, invoke coffee.cmd like so:

coffee input.coffee output.js

You can also pipe to and from it if you are so inclined via stdin/out. Errors are written to stderr.

In the test directory there’s a version of the standard CoffeeScript tests which can be kicked off using test.cmd. Note that the test just attempts to compile the standard set of  *.coffee test files but doesn’t execute them.

Hope it helps; comments appreciated!

DDDSW Hecklegate

I went to the free DDDSW developer conference on Saturday in Bristol which was excellent. Kudos to all the organisers and speakers and sponsors who made it happen.

One of the sessions I attended though stood out because the speaker, although apparently experienced, had a pretty tough time, especially with some of the comments submitted to an audience feedback web app being used by attendees at the conference. But actually I found myself agreeing with many of the sentiments of these comments (as did the person I sat next to) and felt the session didn’t go well, although it actually contained some great content. Here’s my take on it.

Starting a session by saying how tired you are and how you haven’t slept for days is effectively saying: “sorry, this might be a bit shit”. You may feel justified in saying this because you are delivering the session for no fee and indeed may have incurred substantial expense in traveling to the conference. Nobody cares. It rubs your audience up the wrong way because they also may have incurred considerable expense in getting there too. In fact it’s their free time you’re saying you may be about to waste. They may start to feel their time would have been better spent in another session. Also, consider that your slot at the conference may have been at the expense of someone else, maybe a newbie who would have loved their first opportunity in the spotlight.

Doing too many “hands up if you…” audience questions can get tedious quickly. Indeed, don’t continually ask people to put their hands up if you’re going to say they’re wrong. It might be OK once, but more than that and people are going to feel uncomfortable and antagonised.

If someone walks out, ignore it. Making a point of it makes you look petty. Just maybe they actually had valid reasons for leaving, or indeed, maybe they weren’t enjoying the session. Just let it go.

Finally, there’s a distinction between being “passionate and opinionated” and coming across as a blowhard.

First steps with IronJS 0.2

With the release of IronJS 0.2, the code below is the result of a 30-minute play I had this morning, which shows how easy it is to embed a fully .NET JavaScript runtime in your application by simply referencing IronJS.dll.

It’s changed quite a from prior versions and I think you’ll see it has become much easier to host since  Dan Newcombe’s experiments last year.

//reference IronJS.dll
using System;
using System.IO;

class IronJsDoodles
{
    static void Simple()
    {
        var context = new IronJS.Hosting.CSharp.Context();
        object result = context.Execute("1 + 2;");

        Console.WriteLine("{0} ({1})", result, result.GetType());
        // "3 (System.Double)"
    }

    static void InteractingWithGlobal()
    {
        var context = new IronJS.Hosting.CSharp.Context();

        context.SetGlobal("a", 1d);
        context.SetGlobal("b", 2d);
        context.Execute("foo = a + b;");

        double foo = context.GetGlobalAs<double>("foo");

        Console.WriteLine(foo);
        // "3"
    }

    static void AddingHostFunctions()
    {
        var context = new IronJS.Hosting.CSharp.Context();

        // Effectively the same as context.CreatePrintFunction() :-)
        var print = IronJS.Native.Utils.createHostFunction<Action<string>>(context.Environment,
            delegate(string str)
            {
                Console.WriteLine(str);
            });
        context.SetGlobal("print", print);

        context.Execute("print('Hello IronJS!')");
    }
}

Hope it helps you get started.

SOLVED: MSDeploy error “(400) Bad Request”

While working from home I was trying to use MSDeploy (aka Web Deploy, or the Publish Web command in Visual Studio 2010) to update an internal site. Whilst this would work perfectly when I was physically in the office, when working from home via the VPN it would fail with the following error:

Remote agent (URL http://myserver.example.com/MSDEPLOYAGENTSERVICE) could not be contacted.  Make sure the remote agent service is installed and started on the target computer.
An unsupported response was received. The response header 'MSDeploy.Response' was '' but 'v1' was expected.
The remote server returned an error: (400) Bad Request.

To see what was going on I started Fiddler and tried the publish again. (One crucial thing I had to do for Fiddler to capture traffic when connected via the VPN was to fully qualify the machine name, so instead of http://myserver, use http://myserver.your-corp.net as the service URL, otherwise it didn’t capture the traffic.)

This is what the exchange looked like:

POST http://myserver.example.com/MSDEPLOYAGENTSERVICE HTTP/1.1
MSDeploy.VersionMin: 7.1.600.0
MSDeploy.VersionMax: 7.1.1042.1
MSDeploy.RequestUICulture: en-US
MSDeploy.RequestCulture: en-GB
Version: 8.0.0.0
MSDeploy.Method: Sync
MSDeploy.RequestId: fde03509-b23e-4759-9353-e8dbf19a2293
Content-Type: application/msdeploy
MSDeploy.ProviderOptions: H4sIAAAAAAAEAO29B2AcSZYlJi9tynt...
MSDeploy.BaseOptions: H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvV...
MSDeploy.SyncOptions: H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvV...
Host: myserver.example.com
Transfer-Encoding: chunked
Expect: 100-continue
...

And in response:

HTTP/1.1 400 Bad Request (The HTTP request includes a non-supported header. Contact your ISA Server administrator.)
Via: 1.1 IBISA2
Connection: Keep-Alive
Proxy-Connection: Keep-Alive
Pragma: no-cache
Cache-Control: no-cache
Content-Type: text/html
...

There in the clear was the crucial error information that MSDeploy was failing to relay: those whacky MSDeploy HTTP Headers were being blocked by our ISA Server. (Note to the developers of MSDeploy: showing this information in debug or verbose modes would be very useful!)

After specifying an access rule on the ISA server to not filter proxied requests to the server in question based on HTTP headers, it all started working again.

Generating better default DisplayNames from Models in ASP.NET MVC using ModelMetadataProvider

Using the scaffolding in MVC makes it easy to knock up CRUD applications without too much difficulty. Typically you end up with something like this – note the PascalCase field names taken straight from the model generated by Html.LabelFor:

camelcase before

So now the obvious thing is to add DisplayName attributes metadata to your model, for example:

[DisplayName("Assigned To")]
public int AssignedToId { get; set; }

[DisplayName("Customer Name")]
public string CustomerName { get; set; }

Meh, donkey work. In most cases it just needs better default labels in the absence of explicit DisplayName annotations. Nine times out of ten field names such as AssignedToId and CustomerName would be simply expanded to Assigned To and Customer Name. (Of course, they don’t do this out of the box because these simple rules wouldn’t hold true for all languages.)

In MVC you can hook into the metadata discovery/generation process by implementing a ModelMetadataProvider, the default one of which is the DataAnnotationsModelMetadataProvider. So all I did was inherit from the latter and override the GetMetadataForProperty method and if no DisplayName has been specified on the model, create one based on the model’s camel-cased property name.

class MyFabulousModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
   // Uppercase followed by lowercase but not on existing word boundary (eg. the start)
   Regex _camelCaseRegex = new Regex(@"\B\p{Lu}\p{Ll}", RegexOptions.Compiled);

   // Creates a nice DisplayName from the model’s property name if one hasn't been specified
   protected override ModelMetadata GetMetadataForProperty(
      Func<object> modelAccessor,
      Type containerType,
      PropertyDescriptor propertyDescriptor)
   {
      ModelMetadata metadata = base.GetMetadataForProperty(modelAccessor, containerType, propertyDescriptor);

      if (metadata.DisplayName == null)
         metadata.DisplayName = displayNameFromCamelCase(metadata.GetDisplayName());

      return metadata;
   }

   string displayNameFromCamelCase(string name)
   {
      name = _camelCaseRegex.Replace(name, " $0");
      if (name.EndsWith(" Id"))
          name = name.Substring(0, name.Length - 3);
      return name;
   }
}

Hook the provider up in Application_Start by assigning an instance of it to ModelMetadataProviders.Current.

It’s pretty effective I think:

camelcase after

Anything that isn’t quite right can be overridden simply my explicitly adding DisplayNames to the model.

Follow

Get every new post delivered to your Inbox.

Join 36 other followers