Prevent Javascript onClick Event From Bubbling Up

I recently was working with some code that had an onClick event handler on the <TR> of each row of a table. In one of the columns, a <TD>, there were icons that also had onClick’s on them. Something like:

1
2
3
4
5
6
7
8
9
10
<table>
  <tr onClick='foo()'>
    <td onClick='bar()'>
      <!-- some icons -->
    </td>
    <td></td>
    <td></td>
    ...
  </tr>
</table>

Now if the icons in the first <TD> were clicked, I wanted bar() to fire, but not foo(). Normal behavior is to execute them both.

Turned out there is a simple solution for this with jQuery. Only tested in Firefox, but presumably this works across the board because jQuery is awesome that way.

Add a class to the <TD> called no-event-bubble-up:

1
  <td onClick='bar()' class='no-event-bubble-up'>

And add the following JS to your page:

1
2
3
4
5
6
7
8
9
<script type='text/javascript'>
  $(document).ready(function() {
    $(".no-event-bubble-up").each(function() {
      $(this).click(function(e) {
        e.stopPropagation();
      });
    });
  });
</script>

That’s all that is needed and it worked for me.

Let me know if you find this useful.

Get Rxvt-unicode With 256 Color Support on Ubuntu

rxvt-unicode (commonly called urxvt) already has 88 color support, and for most things, this is fine. But I recently just found the CSApprox plugin for vim, which lets you use Gvim themes in console vim. CSApprox actually does a pretty good job interpolating for 88 colors too, but it is best at 256.

So here’s my build log of compiling rxvt-unicode with the 256 color patch on Ubuntu Hardy, and debianizing (packaging) it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# I keep all custom deb's here, use any directory you want
cd ~/debian-src

# Make a place for rxvt-unicode
mkdir rxvt-unicode
cd rxvt-unicode/

# Get the source
apt-get source rxvt-unicode
cd rxvt-unicode-8.4/

# Apply 256 color patch, it's included with the source
patch -p1 < doc/urxvt-8.2-256color.patch

# Make sure you have all depdencies to build it
sudo apt-get build-dep rxvt-unicode

# Build it
dpkg-buildpackage -us -uc -rfakeroot

This will actually build three separate packages:

  • rxvt-unicode
  • rxvt-unicode-lite
  • rxvt-unicode-ml

All I care about is rxvt-unicode, but you might want -lite or -ml. If someone more adept in Debian package building than I am can tell me how to just compile one of these versions, that’d be great. :)

Moving along:

1
2
3
4
5
6
# Install it!
cd ~/debian-src/rxvt-unicode
sudo dpkg -i rxvt-unicode_8.4-1_amd64.deb

# As always, your arch may be different.  Replace amd64 with whatever is
# appropriate for you.

Now we need to make terminfo aware that rxvt-unicode supports 256 colors. The default terminfo entry you’ll have for rxvt-unicode will say 88, and that won’t be right for your new version.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cd ~
infocmp -L rxvt-unicode > rxvt-unicode.terminfo

vi rxvt-unicode.terminfo
# Change the following from:
#
#    lines_of_memory#0, max_colors#88, max_pairs#256,
#
# to:
#
#    lines_of_memory#0, max_colors#256, max_pairs#32767

# Make .terminfo dir if you don't already have it
install -d .terminfo

# Rebuild terminfo for rxvt-unicode
tic -o .terminfo/ rxvt-unicode.terminfo

# Cleanup
rm rxvt-unicode.terminfo

That should do it.

To test it out, use this 256colors2.pl script (it’s the same one included in the xterm distribution). Download it, set it executable, open a fresh urxvt terminal, and run:

1
$ ./256colors2.pl

The output should look like:

Any program that supports 256 colors that had to fallback to 88 or even 8 colors can now be used in all its glory.

Does this make your consoling experience better? Let me know, post a comment.

Hardy Xen domU Doesn’t Show Login Prompt [Fix]

I have a Xen machine running Ubuntu Hardy (8.04.1). I created a guest that was also Hardy, with xen-tools. But after booting it up, the login prompt wouldn’t appear. It would get as far as:

1
2
3
...
 * Starting OpenBSD Secure Shell server sshd                             [ OK ] 
 * Running local boot scripts (/etc/rc.local)                            [ OK ]

And then just not show anything. The VM wasn’t hung, just the login prompt didin’t display.

After googling to no avail, I lucked out with button mashing some options in my <vm>.cfg file. Adding this to the end of my <vm>.cfg made it work:

1
extra = 'xencons=xvc console=xvc0'

Update: Immutable, With Exceptions

This is an update to my previous article: Making methods immutable in Ruby.

By popular demand, I’ve made my Immutable module raise an exception, by default, if you try to override an immutable method.

So, the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require 'rubygems'
require 'immutable'

module Foo
  include Immutable

  def foo
    :foo
  end

  immutable_method :foo
end

module Foo
  def foo
    :baz
  end
end

Will raise an error:

1
Cannot override the immutable method: foo (Immutable::CannotOverrideMethod)

Making Methods Immutable in Ruby (or, Death to Monkey Patching)

Update (09-21-2008): I have a followup to this article here.

You’ve probably been told that in Ruby classes are always open and any code can come along and redefine your methods in any way it pleases. Indeed, this is true.

Kinda

What’s not true, despite every reference I’ve read saying the contrary, is that you can’t prevent this from happening.

Ruby provides a method_added() callback that is invoked every time a method is added or redefined within a class. It’s part of the Module class, and every Class is a Module. There are also two related callbacks called method_removed() and method_undefined().

This means you could detect when other code has redefined a method, and do something about it! How about redefining that method (again) to point back to your original code? Indeed, this works.

I’ve encapsulated the details of this in a new module I call Immutable. It provides one class method called immutable_method(). Provide it a list of methods you don’t want touched and it’ll make sure they can’t be redefined. Hence, immutable.

It’s on GitHub: http://github.com/up_the_irons/immutable/tree/master

Here’s an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
require 'rubygems'
require 'immutable'

module Foo
  include Immutable

  def foo
    :foo
  end

  immutable_method :foo
end

# Now re-open Foo and redefine foo()
module Foo
  def foo
    :baz
  end
end

include Foo

foo # => :foo

foo() returns :foo, not :baz, even though we redefined foo() to return :baz.

If this makes you think of Java’s final method modifier, you’d be almost right in saying immutable_method is similar. But there’s one important difference: with immutable_method you can still redefine methods in subclasses. This makes sense, as one can argue that if you want to reimplement or extend a method, a child class is the only place where you should be doing that anyway. I tend to agree, call me a purist.

Why would this be useful to you? I don’t know. But I can tell you what motivated me.

My motivation for writing something that provides what some may call “evil” functionality (heh, and monkey patching isn’t evil?) of closed methods/classes came from my trials of trying to improve Rails loading time by reimplementing some ActiveSupport methods in C (Ruby extension).

I absolutely needed my C versions of certain methods to be present, and not clobbered by ActiveSupport.

So why didn’t I just load my extension after ActiveSupport? Because by then it is too late. Rails is already loaded, along with slow running methods that get called over 10,000 times during initialization.

Run the profiler and see for yourself:

1
./script/performance/profiler "require 'config/environment'"

This is a prelude to my next post, when I present the plugin I’ve built that takes away over 30% of overhead from Rails loading time. Stay tuned (or subscribe :)

But for now, if you want to try Immutable, clone it from GitHub, or if you have RubyGems 1.2.0 or higher, do this:

1
2
3
4
# Requires RubyGems 1.2.0+ (or so I'm told...)

gem sources -a http://gems.github.com
sudo gem install up_the_irons-immutable

Then you can run the example above. You’re all set.

See the README for further details.

Enjoy (or flame me for ruining your monkey patching).

Nicely Formatted JSON on the Command Line

You have a URL that outputs JSON, and you want to quickly see its contents from the shell, but nicely formatted, not the raw output wget spits; just do:

1
2
$ wget foo.com/bar.json -O - --quiet | ruby -rubygems -e \ 
  'require "json"; puts JSON.parse($stdin.gets).to_yaml'

I broke it up into two lines for easier reading, but you can type it all out in one line, or better yet, turn it into a shell script with a single URL argument.

GNU Screen With Vertical Split Support

Just a quick post here. I recently recompiled screen with vertical split support on Ubuntu 8.04. Here’s how you do it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Install dependencies to build screen
sudo apt-get build-dep screen

# Create an area to hold the source
cd ~/debian-src
mkdir screen
cd screen

# Get the source
apt-get source screen

# Apply vertical split patch
cd screen-4.0.3/
wget http://vsp4sdl.yuggoth.org/wrp_vertical_split_0.3_4.0.2.diff.bz2
bunzip2 wrp_vertical_split_0.3_4.0.2.diff.bz2
patch -p1 < wrp_vertical_split_0.3_4.0.2.diff

# Build it!
dpkg-buildpackage -us -uc -rfakeroot
cd ..

# Install it!
sudo dpkg -i screen_4.0.3-0.4ubuntu2_amd64.deb

That’s it.

Automatically Setting Hostname as GNU Screen Window Title

I’m starting to put this in ~/.bashrc of all my servers now:

1
2
3
4
5
6
# Set screen window title
case "$TERM" in
screen)
  PROMPT_COMMAND='echo -ne "\033k$HOSTNAME\033\\"'
  ;;
esac

When I log into the machine, the screen window title (which displays on the hard status line, and in turn my urxvt window title bar) automatically changes to the hostname of the machine I’m logged into. I used to set this manually, but now I don’t have to, yay!

If your distro doesn’t set up your environment so ~/.bashrc is sourced upon login, you’ll want to put this into ~/.bash_login instead.

To get this code on a lot of servers at once, save the above snippet to a file called “prompt-command.sh” and execute:

1
for i in hostname1 hostname2 hostname3; do cat prompt-command.sh | ssh $i 'cat >> ~/.bashrc'; done

Of course, change “hostname1”, “hostname2”, etc… to the real hostnames of your machines.

Cool, huh?