Sergio and the sigil

jQuery Character Table

Posted by Sergio on 2008-12-29

The other day I was looking for the HTML code for the ⌘ (in case you can't see it, that's the command key symbol), found in mac keyboards. It was not the first time I was looking for the HTML code for one of those funky characters. I remember having a hard time trying to represent some Math symbols, like sums and integral equations from my college Calculus days.

I thought this would be a nice opportunity to create a small jQuery sample that renders a range (or ranges) of HTML characters along with their codes.

I started with a simple HTML page, leaving all the JavaScript in an external file.

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>HTML Characters</title>
    <meta http-equiv="Content-Type" 
      content="text/html; charset=utf-8">
    <script type="text/javascript" 
      src="jquery-1.2.6.js"></script>
    <script type="text/javascript" 
      src="char-table.js"></script>
  </head>
  <body>
    From (hex): <input id="range_from" type="text"  /> <br/>
    To (hex): <input id="range_to" type="text"  /> <br/>
    <input type="button" value="Load" id="btnLoad" />
    <input type="button" value="Load Example" id="btnLoadEx" />
    <input type="button" value="Load Keyboard Symbols" 
         onclick="CHARTABLE.loadKeyboardSymbols();" />
    <table id="char_table" border="1" />
  </body>
</html>

Here's the JavaScript in the file char-table.js.

$(function(){
  //here we put everything that will run when the page is ready

  $('#btnLoad').click(function(){
    // notice how we get the value of the input fields using val()
    // notice how to parse hex numbers in JS
    var from = parseInt($('#range_from').val(), 16);
    var to = parseInt($('#range_to').val(), 16);
    CHARTABLE.loadRange(from, to);
  });

  $('#btnLoadEx').click(function(){
  //setting the value of each input field
    $('#range_from').val('2190');
    $('#range_to').val('2195');
  //fire the click event of the Load button
    $('#btnLoad').click();
  });

});

// the CHARTABLE object acts as a namespace
var CHARTABLE = {
   loadRanges: function() {
    this.clearTable();
    for(var i=0; i<arguments.length; i++) {
      this.appendRange(
        parseInt(arguments[i][0], 16), 
        parseInt(arguments[i][1], 16)
        );
    }
  },

  loadRange: function(from, to) {
    this.clearTable();
    this.appendRange(from, to);
  },

  clearTable: function(){
    //the html() function is how we replace the innerHTML with jQuery
    $('#char_table').        
      html('<tr><th>Character</th><th>Code</th></tr>');
  },

  appendRange: function(from, to){
    //we can create stand alone DOM elements with $()
    var tbody = $('<tbody/>');
    for(var i=from; i<=to; i++) {
      //notice how we can convert a number to hex
      $('<tr>').
        append('<td>&#x' + i.toString(16) + ';</td>').
        append('<td>&amp;#x' + i.toString(16) + ';</td>').
        appendTo(tbody);
    }
    //adding the tbody to the table at the end
    //  renders faster than adding each row to
    //  the table as we go
    $('#char_table').append(tbody);
  },

  loadKeyboardSymbols: function(){
    this.loadRanges(
      ['21e7', '21e7'],
      ['21a9', '21a9'],
      ['2303', '2305'],
      ['2318', '2318'],
      ['2324', '2327'],
      ['232b', '232b'],
      ['2190', '2198'],
      ['21de', '21df'],
      ['21e4', '21e9']
    );
  }
};

Now enter the range from 2100 to 2400 and stare at a whole bunch of characters that can become useful in some situations.

Note: The characters don't render equally in IE and Firefox, but a large number of them render just fine in both browsers.

One less diacritical mark to annoy me

Posted by Sergio on 2008-12-26

Being a Portuguese-speaking person living in the US, one of the things you have to get used to is the keyboard physical layout and key mappings. You know, Latin-originated languages tend to have thôse wéìrd chãraçtërs, which are really just diacritical marks applied to regular characters to differentiate words (sometimes it changes the pronunciation, sometimes i doesn't.)

To accommodate the extra characters, many countries define their own standard for physical keyboard layout. In Brazil the standards body is called ABNT and they came up with the layout that you can see below. It's a mild variation from the one used in the US and works well if you type in Portuguese most of the time.

Even when I was living in Brazil, when I started using computers at home and at work, it was easier to find a keyboard with a US layout than one with the ABNT layout (this situation has changed now.) I chose to stick to a keyboard with the US physical layout and, when in Windows — which was most of the time anyway — apply the US-International key mappings.

What happens when you use the US-International it that some keys become dead keys and when you strike them no characters are echoed. The OS waits for the next key(s) to decide what to print. For example, if I type [ " ][ a ][ b ][ c ] without the US-International mapping, I get (unsurprisingly) "abc. With US-International on I get äbc. I'd have to type [ " ][space][ a ][ b ][ c ] to get the intended text. Other dead keys are [ ' ],[ ` ],[ ^ ],[ ~ ].

Of all these dead keys, the ones that hit me the hardest are [ " ] and [ ' ] because I use them all the time when writing source code.

Where am I going with all this?

As of January 1st 2009 all Portuguese-speaking countries will start complying with an agreement that will cause some orthographic changes in the language. One of the new rules is that the umlaut (those two dots above some letters) is being dropped from the language.

I'm so happy with this decision that I simply could not wait until the US-International key mapping gets updated in some Windows update super Tuesday. I decided to take matters on my own hands and yank that nasty thing off my system.

How to create/edit keyboard layouts (mappings)

Microsoft published a cool little tool called Keyboard Layout Creator that allows you to create or edit the keyboard layouts.

It doesn't get much simpler than that. I installed and run this program. Then I loaded the existing US-International layout and saved it as US-International-No-Umlaut. Mousing over the ["] key would reveal that it indeed is marked as dead and show all the available combinations.

From there I just needed to right-click that key and un-check the option that was setting it as a dead key.

The next step is to compile the new layout into a DLL and create the setup package for it. That is done by the menu option Project > Build DLL and Setup Project.

After running the produced setup program, I could just go into the regional settings of my system and select the new layout (mapping) as my default setting.

If you are another Portuguese-speaking programmer and don't feel like going through the same steps, you can just download the setup files I created.

Now I just need to get rid of that muscle memory that I acquired after all these years.

Language Envy - episode 0

Posted by Sergio on 2008-12-24

Although C# is the language that I can call myself proficient enough to make a living these days, there are other languages that I have to use for specific tasks (like JavaScript, SQL, XSLT.) I also like using other general purpose languages for pure exploration or pet projects. I'd include Ruby, ObjectiveC and PHP in this group.

When using other languages it often happens that I encounter features that I wish C# had or that the C#-equivalent was as easy (it works both ways — I miss some C# feature on the other side as well.)

In this series of undetermined length I will be posting some of the items from my wish list as I remember them.

The case statement

To start things off, let's check out C#'s case statement, straight from the language specification.

switch-statement:
    switch   (   expression   )   switch-block
switch-block:
    {   switch-sectionsopt   }
switch-sections:
    switch-section
    switch-sections   switch-section
switch-section:
    switch-labels   statement-list
switch-labels:
    switch-label
    switch-labels   switch-label
switch-label:
    case   constant-expression   : // <-- line 14
    default   :

I know that doesn't look like C# code. What I'd like to point is in line 14. The expression in each case label has to be a constant. I'm sure that helps making the switch statement compile to a very efficient MSIL code, but let's consider what we are missing because of that.

Here's a sample of what you can do in a Ruby case expression.

SIDE NOTE: The hawk-eyed reader will catch the terminology difference here. Many language constructs that are mere statements in C# are expressions in Ruby. But that's not the feature I'll write about today. Maybe in a future installment.
Months = %w(JAN FEB MAR APR MAY\
        JUN JUL AGO SEP OCT NOV DEC)

def get_month(value)
  case value
    when Date # class name (instance of?)
      return Months[value.month - 1]

    when /\d{4}-(\d{2})-\d{2}/ # Regular expression (matches ?)
      return Months[$1.to_i  - 1]

    when 1..12  # Range of values (contained ?)
      return Months[value - 1]

  end
end

puts get_month(Date.today)
puts get_month("2008-10-20")
puts get_month(8)

As you can hopefully see in the above example, the expressions in each when statement do not need to be constants (class names like Date are constants, by the way)

Ruby defines the === (triple equal) comparison operator that can be overriden in each class and is used in the case expression to test each when condition. This is usually read as "when value matches with this expression here...".

Not surprisingly, the built-in classes in Ruby do override the triple equal operator to add a more meaningful implementation for it. Range matches the values that are within the range. RegExp matches values that agree with the regular expression, Class objects match values that are instances of that class, etc.

I use this feature all the time and it's so convenient that I'd be thrilled to see it in C# one day.

So, what is my suggestion?

I wouldn't be a real programmer if I didn't try to sell my own suggestion, would I? Since IComparable is taken and means something different, I was thinking of maybe something like this.

public interface ICanMatch

Presentation Remote

Posted by Sergio on 2008-12-20

In the last few months I have been using my MacBook to give presentation, both at work and not. I've been meaning to buy one of those presenter remotes. I even got to borrow one and tried it once and I must say it worked pretty well.

Then I remembered that the MacBook came with that useless remote that I had forgotten in a junk drawer somewhere. Well, that remote happens to work well with more than just Front Row. I heard it works with Keynote for presentations. I don't use that application and I'm not planning to buy it since Powerpoint 2007 works very well for me on my PC and I'm too cheap to buy Keynote.

I typically save my PowerPoint presentations to PDF and show them on the mac using Preview (a simple PDF viewer). The remote does not work with Preview out of the box but I found this little freeware called iRed Lite that can make the apple remote control just about any application, as long as the application is controllable with AppleScript, which most apps are.

The only problem was that iRed Lite came with support for Preview but it did not work well for the full screen mode, which I needed. Time to get my hands dirty with AppleScript.

The idea here was to bind the commands associated with the left and right arrows of the remote to the keys PageUp and PageDown, respectively.

The iRed Lite utility allows you to edit each command by assigning a keystroke or an AppleScript snippet. Initially I tried the keystroke alternative but I could not figure out how to send a PageDown or PageUp to the application because on the keyboard they are Fn+UP and Fn+DOWN and Fn was not available in the utility. The AppleScript ended up being rather minimal, as seen in the screenshot.

For the Next Page command I entered:

tell application "System Events" to key code 121

For the Previous Page command I entered:

tell application "System Events" to key code 116

You can find all these key codes in the file /System/Library/Frameworks/Carbon.framework/Frameworks/ HIToolbox.framework/Headers/Events.h provided you installed the developer tools from the OS X installation DVD, i.e. you have Xcode installed.

Wow. All this trouble to save $50? I guess I just liked the fact that I found a use for that remote. Now I just need to hack a laser diode inside the remote to use as a pointer too.

Thank you LCNUG

Posted by Sergio on 2008-12-19

Thanks to the brave souls that ignored the incredibly exaggerated Winter storm warnings and insane weather forecast for last night. These folks came to the LCNUG meeting and were home before the first snow flake hit the ground. Also, thanks LCNUG for inviting me to talk, I hope you enjoyed at least a little bit.

The material I had to show in my presentation would no doubt fill an entire day (because it came from a full-day class I previously led) but we are not that crazy so we decided that:

  • Doesn't matter how much of the material we cover, what we cover we will cover well.
  • It would be best to talk about less things but get more value out of that than talk about a whole lot of things and feel like you just wasted two hours of your life.
  • Go only as far as our stamina (and storm anxiety) allowed us to.
  • Ask, ask, ask. Don't go back home with any lingering question.
  • Well, keep that under the 2-hour mark, will you?

I never thought we would have enough time to see the entire material or even see some jQuery stuff. But I'm confident that what we have seen there will allow anyone that is starting to take JavaScript seriously to jump on jQuery (or YUI or Prototype.js, etc) and be able to effectively read the docs, the samples, and even the source code.

I'm trying to get clearance with my company to share the presentation material. Either by a download link here or directly emailing the attendees. Sit tight.