Monday, May 28, 2012

Using Grunt.js with CSS

For most of my apps, I've been using either a Makefile, shell scripts, Python scripts, or some combination of those as my build tool — taking care of tasks like concatenating files, minifying files, and linting my code. A few months ago, Ben Alman introduced Grunt, a build tool written in JS and designed for JS. I quite liked the idea of using JS for task automation, since it's a language I already know (bash scripting makes me want to bash my head against the wall) and it's the language that I write my apps in (at least the front ends). I finally got the opportunity to properly try it out last week, while porting my HTML5 slide editing app over from Closure to Bootstrap.

Grunt is designed primarily for JavaScript projects, like Node.JS or jQuery plugins, so it comes out of the box with tasks for concatenating files, linting JS files (via JSHint), compressing JS files (via UglifyJS), running a Node server, and running JS unit tests — no CSS-related tasks. For this web app, I decided to write the CSS using Less, a CSS pre-processor. While debugging locally, I include the .less file on the page and the less.js pre-processor, but for performance reasons on production, I wanted to just include a minified CSS file. So I needed 2 new tasks: one for processing the .less, and another for minifying the .css. Grunt has a formal way for developers to define and share new tasks via extensions, and luckily I found developers have already made grunt-less and grunt-css extensions.

To use the Grunt extensions, I first had to install them as node modules. I could have installed them simply by running npm install grunt-less inside my project folder, but at the suggestion of Ben, I instead created a package.json file with the modules listed as dependencies. Then I just ran npm install and it grabbed everything necessary. Now, since my code is open-source, I don't have to tell people what they need to install - just have to make sure they run install. Here's what my file looks like:

{
  "name": "SlideEditor",
  "version": "0.0.0",
  "dependencies" : {
    "grunt-less":  ">0.0.0",
    "grunt-css":   ">0.0.0"
  }
}

Once I did that, I just loaded the task definitions in my grunt.js file by sticking these lines in:

  grunt.loadNpmTasks('grunt-less');
  grunt.loadNpmTasks('grunt-css');

And now I could use the tasks! However, before I set them up, I spent a while figuring out the best directory structure for both my JS and CSS. When you're using any sort of build tool, it helps to have a sensible directory structure, like separate folders for the debug files versus the build files. For this app, I decided to put all the original files in a src folder with child folders for css and js, and for the build files, I just put them in css and js folders under the root. In the src/css folder, I have children folders less (for the .less file), app (for the processed less file), and libs (for any CSS files from 3rd party libraries). Here's what that looks like:

  • src
    • css
      • less
      • app
      • libs
    • js
      • app
      • libs
  • js
  • css

Okay, so finally, I put the Grunt extensions to work, setting up the less and cssmin tasks. Here's what all the CSS-related tasks look like in my grunt file:

  var SRC_CSS   = 'src/css/';
  var BUILD_CSS = 'css/';
  
  grunt.initConfig({
    // ...
    less: {
      css: {
        src: [SRC_CSS + 'less/base.less'],
        dest: SRC_CSS + 'app/base.css',
      }
    },
    concat: {
      css: {
        src: [SRC_CSS + 'libs/*.css',
              SRC_CSS + 'app/*.css'],
        dest: BUILD_CSS + 'css/all.css'
      }
    },
    cssmin: {
      css: {
        src: '',
        dest: BUILD_CSS + 'css/all-min.css'
      }
    },
    // ...
  });

You can check out my full grunt.js file here, to see how I use the CSS tasks and JS tasks together. Like any tool, Grunt takes a bit of time to learn, but at least for me, I find it much more approachable than the world of bash scripting. Try it out for your next project!

Tuesday, May 22, 2012

The Best Online Editors for Teaching HTML/CSS/JS

Over the past few months, I've been teaching in-person classes on HTML, CSS, and JavaScript, as part of GirlDevelopIt San Francisco. Along the way, I've experimented with various online consoles and editors, and I thought I'd share my experience with using them for teaching. But first...

Why is an online editor useful?

  • Speed: It's often faster to make changes in an online console and see the result than it is to use a standard code editor, save the file, reload the page, etc.
  • Sharability: An online console often gives you a link to your code, which you could easily share with students -- or they could share that link with you (like if they worked on something outside the class and had a question). Look, ma, no upload!
  • Compatibility: An online console works anywhere that you have a browser (and works pretty much the same everywhere), whereas most code editors are specific to the OS and each works slightly differently. By using an online console, all students can have the same experience. Plus, if a student doesn't have a laptop with them (like they only have a ChromeBook, iPad, or iPhone), then they can always use the online console.

That being said, there is a danger to using online consoles — they often work a bit differently than the real thing (saving a file on the desktop + viewing in the browser), which can lead to debugging peculiarities (like line numbers not actually pointing to the right line of code or an inspected source showing an iframe) that can confuse students even further. For teaching and learning, the best consoles are the ones that are as close to the real thing as possible.

JavaScript Consoles

For the JavaScript class, we started off with a few weeks of just JS: variables, functions, conditionals, etc. To make sure the students focused on JS and not how it interacts with the DOM, I wanted them to use JS in a pure JS console. There are many JS consoles out there, but the only one I truly liked is repl.it. It's a console for a variety of languages, and is the one used by Codecademy labs. Here's what I liked about it:

  • It evaluates the JS on the client, so it's fast. (A few consoles send it to a server first, ick).
  • It has a multi-line console on the left-hand side, so you can write lots of code and then run it. Many JS consoles are only single line input, or multi-line if you press shift-enter — but I really wanted multi-line to be the default.
  • It uses the open-source Ace editor for the multi-line console, and that editor includes line numbers and error markers next to problematic lines.
  • It's linkable and printable.
  • It's an open-source project, and the contributors were very responsive to the issues I filed.
  • It works on ChromeBook and to a reasonable extent, iPad and iPhone (yes, one of our students coded on an iPhone!).

HTML/CSS/JS Editors

Once we got to the DOM part of the JS class, I looked for an online editor that supported HTML/CSS as well. In this case, though, I encouraged most students to use their desktop code editors, as they're generally better and they are what they would be using outside of class anyway — so I mostly looked for online tools that I could use for in-class demonstrations and as backup options for students that couldn't use desktop editors.

I ended up using Cloud9 IDE most of the time. Cloud9 a startup for doing web development in the cloud, and their editor is the open-source Ace editor (same as repl.it). The experience of using it is similar to the experience of using a desktop editor - you start a project, create a new file, save the file, view the file in a new window, save and reload, repeat. My only real qualms with it are that it takes time to get started and the project-based interface is a bit much for someone just playing around - and it suffered occasional server issues.

I also occasionally used JSBin v3, an open-source editor from Remy Sharp, based on the CodeMirror editor. I like how lightweight the interface is, but I didn't like how the tool changed my HTML (inserting comments, script tags, etc), and I found the save-view-reload interface a bit confusing. That said, Remy is receptive to feedback and says that I could set up custom templates for teaching. I would definitely look more into it for next class.

Many people would recommend JSFiddle, but I don't actually think that's optimized for learning and teaching the basics of HTML/CSS/JS. It's better for putting together quick demos and test cases, particularly when using libraries.

Wednesday, May 2, 2012

Triggering Numeric Keyboards with HTML5

In the PhoneGap-powered mobile apps for EatDifferent, there's a part where you can enter measurements like weight and body fat — numbers like "12" or "150.5". I realized that I had to switch between the normal keyboard and numeric keyboard (the one with symbols and numbers) whenever I entered measurements, and I wanted to see if I could trigger the numeric keyboard by default for those input fields. HTML5 inputs support a few interesting new attributes, like type="number" and pattern="regex", and I figured I could use some combination of them to get what I wanted. So I started experimenting...

Using type="text" with pattern

The iOS developer docs actually include a section on how to trigger different keyboards and they recommend using type="text" with the specific pattern of either "[0-9]*" or "\d*" to trigger the numeric keypad, like so:

<input type="text" pattern="[0-9]*">

Unfortunately, when you start typing in that field on iOS, it will actually bring up the keypad that only has numbers, not the keypad which also includes symbols like the period, necessary for decimals. And on Android, you just get the normal keypad.

So then I tried setting that pattern to what I actually wanted to accept - numbers and periods:

<input type="text" pattern="\-?\d+(\.\d{0,})?">

On both iOS and Android, that just resulted in the regular old keypad showing up. No good!




Using type="number"

After deciding that Android doesn't pay attention to pattern at all and that iOS probably hard-coded the special case for the strict numeric patterns, I tried using input type="number" instead, with a step value of "0.01":

<input type="number" step="0.01">

Success! On both iOS and Android, a keypad with both numbers and a period shows up.



Now, I re-use my mobile web HTML for the website as well, so I needed to make sure that this solution would work well in desktop browsers. In older browsers, new HTML5 input types will just fallback to text, so we don't have to worry about them, but some newer browsers have special treatment for them, and that's what I needed to check. As I discovered, Chrome actually renders a spinner control inside the input for changing the number value by the specified step value. Maybe it's just because I'm not used to it, but I don't like that interface much, and it doesn't feel appropriate for my use case.

Fortunately, with a bit of Webkit-specific CSS, we can hide the spinner (kudos to StackOverflow for this):

input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}


Future-proof?

So, it's pretty cool that we can start being more semantic in HTML5 about what our inputs accept - and that browsers react to provide better input interfaces. But, it feels like it's still quite ill defined how browsers should react, and whether they will all react the same way, and whether their reactions will actually be appropriate for the variety of use cases out there.

Now that I've made this change to a more specific input type, I'll need to be on the lookout for browser changes to make sure it's always the best solution. It's not a change I'd make willy-nilly.

If you've done any experimenting with the new HTML5 input types and keyboard interfaces, I'd love to hear your thoughts in the comments.

Tuesday, May 1, 2012

Learning to Code in SF

San Francisco is filled with developers — but it's also filled with people that want to learn how to be developers. Thankfully, there are many ways for would-be developers to learn from the current developers here, and since I'm getting asked this question more and more these days, I thought I'd share a list of the ways I know. Let me know if I missed anything!

For Everyone


For Women

There are many groups that offer classes solely for women, to provide a more comfortable environment than the usual male-dominated ones (sorry, dudes, but sometimes it sucks to be the only girl in the room).

  • GirlDevelopIt: This is a global organization that offers low-cost web development classes for women, and we're just getting it started here in SF. So far, I've taught an HTML & CSS class for it and am looking forward to the JavaScript class in May.
  • WomenWhoCode: This group was started to bring together women who already code, but just this week, they started holding a weekly frontend web development meetup for women that want to learn more about the various aspects of web development.
  • PyLadies: Dedicated to getting more women in the Python community, the SF chapter of PyLadies is just getting started, and they're kicking off with study groups and hackathons.
  • RailsBridge: Started several years ago with the goal of getting more women in the Ruby community, they organize weekend workshops on Ruby and Rails. Sign up for their mailing list to find out when the next one is happening in SF.
  • HackstarAcademy: An intensive 10-week programming class for women, $6000 but scholarships are available.

For Trans People

There's a growing number of folks that identify as trans in SF, and now there are even coding classes targeted at them - well, one, at least.

  • TranscodeSF: A year of twice-weekly programming classes.

For Kids

Children are our future! And they're also really fun to teach, and can be amazing quick learners. Watch your ego melt away when a kid learns from you and then zooms past. :)

  • CoderDojo: A global organization that puts on free coding workshops for kids, the SF chapter is now hosted at the Twitter office.
  • BlackGirlsCode: Specifically aimed at teaching young women in color how to code, they put on weekend workshops on programming and web development.
  • CodeEd: Specifically targeting girls from underserved communities, it teaches web development skills.
  • WizBots: Using LEGO robotics to encourage kids in math and science.
  • Eureka: A program for teenage girls to get into math and science.

As you can see, there are a lot of opportunities for learning to code in SF - and I didn't even list the many local community colleges with low-cost classes. If you're a developer and want to teach, many of those groups are looking for volunteers. Good luck!