Boulder/Denver New-Tech Meetup Feb 2009

The Bounder/Denver New-Tech Meetup for february was excellent, glad I was able to attend.  New this month was a live twitter feed for the all things #bdnt.  Evidently the 350-ish people there (only a few of whom were actually tweeting) managed to push #bdnt into the top 5 trending tags (which reminds me, this twitter tag trend of the superbowl is very cool).  The beer thread was especially entertaining.

This is the 4th BDNT meetup I’ve attended, and mostly they seem to be about startup companies at various stages giving a 5-min spiel about what they’re doing, business model, next steps, etc — so lots of ‘new’, but doesn’t seem to be so much ‘tech’ in the mix.  I’d like to see people just showing off cool technology they’re messing around with.

In that vein, I talked to Robert Reich (BDNT founder) afterward to get his take on the philosophy of the group and such.  It sounds like that kind of pure-tech presentation is welcome, but it does have to pass his bar of interesting for the group.  I did throw out the possibility of talking about what I’m doing with microblogging inside intel, and it could work.  There’s quite a bit to do before I would have enough to show there, but it would be interesting (for me, anyway).  Not that I love to speak publicly, but it would be a great chance to make some connections.

Uncategorized

Comments (1)

Permalink

twitter for the enterprise?

Interesting last two days inside Intel, at least for me.  There was a bit of a stir about employees using yammer — concern about potential for sharing sensitive data on an externally-hosted service.

I haven’t been using twitter for very long, but I had wondered about the availability of a twitter-like service for internal use.  Intel is a big company, lots of opportunity for sharing and following what else is happening.  Somehow I missed the memo about the group on yammer.

Anyhow, through the course of it all, I was exposed to yammer (along with everyone else in the company…) When I joined the group, the discussion was all about possible alternatives that could be hosted internally and thus be approved for some of the conversations people would like to have.

laconi.ca was proposed as a possible platform, so I looked into it.  I happened to have a web server allocated to me that could host a deployment for evaulation.  Setup was reasonably easy — if you ignore the hours spent trying to build php5 for the machine.  Probably didn’t help that I was falling asleep at the keyboard…

The laconi.ca app seems pretty full-featured, but there’s actually a fair amount that doesn’t apply to this type of deployment — we won’t be using OpenID logins, SMS is probably not useful, won’t be supporting cross-posting to twitter, etc.  All of those things have to be hacked out of the code, unfortunately, as it is not very modular / configurable codebase.

One thing I’d really like to change for this purpose is to increased the limit for messages from 140 to 250 characters or so.  Since it most likely won’t end up supporting SMS, there’s not much point in restricting to 140 characters.  Encouraging brevity is a good thing, but 140 is a bit too short.  But once again, there’s no simple way to configure that.  The 140 limit is built into the database scheme, into the middleware, and also hard-coded in the client javascript code.  A bit disappointed by that…

I worked with one of the active yammerers to do some initial testing, then announced it to the rest of the yammer group.  That all happened on Friday afternoon, so there hasn’t been a lot of response yet, but it seems mostly positive so far.  Yammer definitely has some nice functionality that will be missed (e.g. threaded conversations and groups), but this has the huge advantage of being entirely contained within the copany network.

At the same time I was doing this, I found out that the corporate IT group is working on a full-blown “professional social network” solution for everyone, which will include an integrated micro-blogging function.  That will roll out starting in about two more months…. Being part of a large effort, I don’t expect much from that micro-blogging feature.  Frankly I expect it to suck.  Doing it right is hard enough in relative isolation (twitter/yammer/laconi.ca are not trivial), so doing it as a small part of a larger system will result in a ho-hum, watered-down service that will struggle to engage many users.

Hopefully the laconi.ca-based service will get some traction in the meantime.  If there’s enough momentum, it can’t be ignored.  That’s how previous grass-roots efforts with blogging, wikis, etc have evolved within Intel.  The yammer situation has demonstrated a pretty clear demand for this capability.  Not sure how my involvement in the whole thing will play out, but I hope it remains interesting.

Uncategorized

Comments (1)

Permalink

Overnight success takes years

Great advice in a post on Coding Horror, from Jeff Atwood and others.  This title made me laugh: Teach Yourself Programming in Ten Years.  I started playing around with BASIC on the Apple II’s at school in 4th grade, then on my parents’ Kaypro II.  So I’ve been been at it a long time.  There’s a whole lot left to learn.

I also (sort of) studied violin for ~15 years.  I can manage to play a few things well, but it’s mostly frustrating, because I can’t just pick it up and play.  And I know what it would take: consistent, dedicated practice — not just playing, but practice, doing specific exercises to develop specific skills and expand my repertoire.

The same definitely applies to software and business development.  I’ve had extensive experience with some technologies in some application domains, but there’s so much I don’t know.  I’ve definitely reached a stage in my professional career where I’m starting to feel like things should be happening, and it is hard to be patient and keep slogging away.  Keep learning something new — that’s the easy part, actually.  Focused, intentional practice is not so much fun.  But I’m in it for the long haul, maybe one day I also will be able to wake up an overnight success.

Uncategorized

Comments (0)

Permalink

Implementing a ‘ruler’ with Raphael and jQuery

Investigating a click-and-drag ruler to measure dimensions on-screen.

I used jQuery for event handling and such, and Raphael for drawing the lines. Since it’s just two straight lines, I probably could have done it just as easily with html elements (e.g. setting two borders on a positioned div…) That would probably end up being more robust concerning cross-browser compatibility. Oh well. See the demo here.

There’s nothing innovative here, just something I need to implement for a project. It turns out to be a bit involved to handle all parts of the interaction. The basic idea is:

  • on mousedown: register the starting point, and create the lines and labels (Ruler.start())
  • on mousemove: update the end point and redraw the lines and labels (Ruler.move())
  • on mouseup: hide the lines and labels (Ruler.finish())
var Ruler = function (elem) {
  elem = $(elem);
  this.elem = elem[0];
  this.raph = new Raphael(elem[0],elem.width(),elem.height());

  var b = this;
  elem.mousedown(function(e) { b.start(e); });
  elem.mouseup(function(e) { b.finish(e); });
  elem.mousemove(function(e) { b.move(e); });
};

The full implementation came to about 125 lines, tested in Firefox 3, and IE 7. I’ll cover some of the tricky issues here.

Bias

The ruler feels more natural if it follows the direction the mouse is moved—if I drag the mouse left or right, then it draws the horizontal segment first, followed by the vertical; if I drag the mouse up or down initially, it draws vertical then horizontal.

The code waits for at least a 10-pixel movement from the starting point to determine the user intent, and then fixes that as the bias for the ruler. This affects the ordering of the line segments, as well as the placement of the text labels.

  bias: function(left,top) {
    var dx = Math.abs(this.dx);
    var dy = Math.abs(this.dy)
    if ( (dx+dy) > 10 )
      this.dir = (dx > dy) ? 'h':'v';
  },

The lines

The two line segments are drawn as a single Raphael path element. Instead of re-creating the path for each movement, it updates the points in the path instead. Raphael makes this easy:

  draw_lines: function(left,top) {
    var p = this.path.path;
    if ( this.dir == 'h' )
      p[1].arg = [left, this.start_at.top];
    else
      p[1].arg = [this.start_at.left, top];
    p[2].arg = [left, top];
    this.path.redraw();
  },

The text labels

The labels showing the horizontal and vertical distance are drawn with two dynamically-created divs, positioned absolutely. I want these to be treated as passive annotations on the page, but since they are actual DOM elements, they are treated just like any other text on the page—the get selected when the mouse goes over them while the mouse button is down (i.e. while dragging the ruler).

So, when the ruler drag is started and it is short, the mouse is over the text labels, and the browser selects the text as it is supposed to. Not a nice effect. I found this solution for making the text non-selectable in a cross-browser manner, but with limited success.

  draw_labels: function(left,top) {
    var hl, ht, vl, vt;
    if ( this.dir == 'h' ) {
      // horz label
      hl = (this.start_at.left + left)/2;
      ht = this.start_at.top;
      // vert label
      vl = left + 2;
      vt = (this.start_at.top + top)/2;
    } else {
      // horz label
      hl = (this.start_at.left + left)/2;
      ht = top;
      // vert label
      vl = this.start_at.left + 2;
      vt = (this.start_at.top + top)/2;
    }
    $(this.hlabel).text(this.dx).
      css({left: (this.offset.left + hl)+"px",
           top: (this.offset.top + ht)+"px"});
    $(this.vlabel).text(this.dy).
      css({left: (this.offset.left + vl)+"px",
           top: (this.offset.top + vt)+"px"});
  },

mouseup outside of the div

If the mouse leaves the #paper div, and then the user releases the mouse, the Ruler.finish() method never gets called. This has a very simple solution: in Ruler.start(), don’t do anything if the ruler is already in progress (the previous mousedown), so the user just has to click again inside the div to finish it.

Am I making this too hard? Feel free to point me to easier/cleaner/better solutions…

Uncategorized

Comments (1)

Permalink

Pedigree navigation mockup

Now that I have a gedcom parser to work with, I loaded up a mockup pedigree view I’ve been working on with some real data

pedigree mockup

Next steps:

  • navigation to children, siblings
  • draw connecting lines
  • popup for details on a person

At some point I’ll abandon this code to start working on the ‘real’ implementation, but it’s a good vehicle for prototyping for now. All done in Javascript (~560 lines), with a bit of help from the dojo toolkit.

Uncategorized

Comments (0)

Permalink

Ruby GEDCOM::Parser module

Getting ready to do some work on yology, I needed a good way to get at some sample date. Numerous GEDCOM files are readily available, but I only need a subset of the data for the mockups I’m planning.

I took a look at the existing ruby GEDCOM::Parser, but wasn’t satisfied. So I forked it and hacked away. See the full writeup for details.

Uncategorized

Comments (1)

Permalink

Tk-GraphViz 1.01

I just upload Tk-GraphViz 1.01 to CPAN. Alternately, download it here

This is a very minor update with some additional polygonal node shapes. This module could use some serious updating to get in sync with the latest graphviz—the first version went on CPAN back in 2003.

Uncategorized

Comments (0)

Permalink

Follow me on twitter

http://twitter.com/jslade

I plan to use that twitter profile for tech-related stuff

Uncategorized

Comments (0)

Permalink

git socks proxy with ssh2

Rufus Cable at ThreeBytesFull posted a helpful writeup on using a SOCKS proxy for git access from behind a corporate firewall.

In my corporate environment, we don’t use OpenSSH, but rather Reflection for Secure IT, which is ssh2. The only change I had to make from his instructions was in the socks-ssh wrapper script—using the SocksServer config option instead of ProxyCommand:


#!/bin/sh
# Filename: ~/bin/socks-ssh
# This script opens an SSH connection through a SOCKS server
ssh -o 'SocksServer http://myproxy.mycompany.com/' $@

Uncategorized

Comments (0)

Permalink

Layout test — experimenting with Raphael

I’ve been looking for a light-weight, cross-platform Javascript library for doing 2D vector graphics. I specifically wanted vector graphics with a full DOM for handling events and such, vs raster graphics (e.g. canvas). I think I found what I’m looking for in Raphael.js.

As a proof of concept, I wrote a little demo app presented here. It uses jQuery + Raphael for the interface, which is just a simple chip floorplan viewer. The boundaries of the various sections of the chip are drawn as rectilinear polygons (layout.js):

LT.prototype._drawBlock = function(g,block) {
  if ( block.path ) return;

  var linewidth = 1;
  if ( this.scale < 1.0 ) linewidth /= this.scale;
   var p = g.path({stroke:'white', 'stroke-width':linewidth+"px"});
   block.path = p;

  var boundary = block.boundary.split(':');
  for ( var i=0, n=boundary.length; i<n; i++ ) {
    var pt = boundary[i].split(',');
    if ( i == 0 ) p.moveTo(pt[0],pt[1]);
    else p.lineTo(pt[0],pt[1]);
  }
  p.andClose();

  var m = block.m;
  if ( m ) p.matrix(m[0],m[1],m[2],m[3],m[4],m[5]);

  p[0].onmouseover = function() { p.attr({fill:'red'}); };
  p[0].onmouseout = function() { p.attr({fill:''}); };

};

All the block boundaries are given in chip coordinates, so the whole view has to be scaled to fit in the canvas. All the polygons are drawn as a group, and then the group is translated and scaled to fit (layout.js):

LT.prototype.draw = function() {
  this.g = this.paper.group();

  // Calculate dimensions
  this.bbox.w = this.bbox.x2 - this.bbox.x1;
  this.bbox.h = this.bbox.y2 - this.bbox.y1;
  this.elem_w = this.jq.width();
  this.elem_h = this.jq.height();

  this.scale_w = this.bbox.w / this.elem_w;
  this.scale_h = this.bbox.h / this.elem_h;
  this.scale = this.scale_w > this.scale_h ? this.scale_w : this.scale_h;
  this.scale = (1 / this.scale) * 0.90;

  // Draw block outlines
  for ( var i=0, n=this.blocks.length; i<n; i++ ) {
    var block = this.blocks[i];
    this._drawBlock(this.g,block);
  }

  // normalize all drawing to 0,0
  this.g.translate(-this.bbox.x1,-this.bbox.y1);

  // Scale to fit
  this.g.scale ( this.scale, this.scale );

  // center all drawing in the paper
  this.g.translate((this.elem_w - this.bbox.w)*.5,
           (this.elem_h - this.bbox.h)*.5);
};

The polygons are given onmouseover / onmouseout handlers to fill them red when hovered, but that is the extent of the interactivity in this example.

The data for the block boundaries is pulled from mysql on the server side. It is all driven by a CGI script written in ruby. I chose this as a simpler alternative to Rails or Merb or Camping—showing the full stack of operations (database queries, template formatting, etc) without much of the hidden ‘magic’ of those frameworks (index.cgi):

class LayoutTest
  def main
    init
    parse_opts
    connect_to_gallery
    read_blocks_info
    read_layout_info
    output_layout
  rescue => e
    fatals_to_browser e
  end

  protected

  def init
    @cgi = CGI.new('html3')
    print @cgi.header
  end

  def parse_opts
    @block = @cgi['block']
    @block = 'pcore' if @block.empty?
    @parent = @cgi['parent']
  end

  def read_layout_info
    @instance = {}
    @layout = {}

    instances = query("select * from layout_instance " +
                      "where `cell` = '#{@block}'")
    instances.each do |inst|
      @instance[inst['instance']] = inst
    end

    chillins = @children.map{|c| "'#{c}'"}.join(',')
    layouts = query("select * from layout_info " +
                    "where `cell` in ('#{@block}',#{chillins})")
    layouts.each do |lo|
      @layout[lo['cell']] = lo
    end

  end

  def query sql
    rows = []
    sth = @dbi.execute(sql)
    sth.fetch_hash do |row|
      rows << row.dup
    end
    sth.finish
    rows
  end
end

The HTML output is generated using ERB. It loads the necessary javascript libraries (jQuery, Raphael, and my own layout code), then generates the necessary calls to LT.block() to define each block to be shown. The raw block boundary data has to be transformed (translated + rotated / mirrored) to account for placement relative to the containing block—that’s all handled in layout.js). The template (index.html.erb):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <title>layout test: <%= @block %></title>
    <link rel="stylesheet" href="layout.css" type="text/css" charset="utf-8" media="screen,projection"></link>
  </head>
  <body>
    <h1>layout test: <%= @block %></h1>
<% if @parent %>
<a href="?block=<%= @parent %>"><%= @parent %></a>
<% end %>
<span id="info"></span>
<div id="layout">
</div>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="raphael.js"></script>
<script type="text/javascript" src="layout.js"></script>
<script type="text/javascript">
var layout = new LT("layout");
<%= layout_block %>
<% @children.each do |child| %>
<%= layout_child child %>
<% end %>
layout.draw();
</script>
  </body>
</html>

The full code is available here. Not very useful without a database to feed the data, but should serve as a reasonable example:

Uncategorized

Comments (2)

Permalink