Sunday, January 27, 2008
Here’s how to handle mouse wheel events in prototype, code heavily borrowed from other places on the net, but brought together and made unobtrusive:
/* Mouse Wheel */
Object.extend(Event, {
wheel:function (event){
var delta = 0;
if (!event) event = window.event;
if (event.wheelDelta) {
delta = event.wheelDelta/120;
if (window.opera) delta = -delta;
} else if (event.detail) { delta = -event.detail/3; }
return Math.round(delta); //Safari Round
}
});
SetupMouseWheel = {
initialize: function() {
Event.observe(document, 'dom:loaded', this.setup_mouse_wheel);
},
setup_mouse_wheel: function() {
Event.observe($('element'), "mousewheel", function(e) { SetupMouseWheel.handleDiv(e) }, false);
Event.observe($('element'), "DOMMouseScroll", function(e) { SetupMouseWheel.handleDiv(e) }, false); // Firefox
},
handleDiv: function(e) {
direction = Event.wheel(e) < 0 ? leftSeek : rightSeek;
console.log(direction); //handle scroll
console.log(Event.wheel(e));
direction(); //call leftSeek or rightSeek depending on direction.
}
};
The problem with this code though, and the reason I haven’t found a productive use for this yet is that the browser always scrolls the viewport when it extends beyond screen dimensions. So you have your scroll handler and the browser’s scrolling viewport playing hanky-panky, and it’s not a good sight to see. For applications which always stays within the browser window though, this is useful code.
Tags: code • development • snippet • web
Comment! |
Permalink
Tuesday, January 15, 2008
Like previous code snippets, this one is mostly all code and no explanation.
A brief primer: you’ve often seen self-labeling input boxes, the ones that display a label inside in gray text, and when you click replaces with an empty input element using Javascript. This is a simple class to help you achieve that effect:
SelfLabelingBox = {
initialize: function(box_id, message) {
this.setup_behavior(box_id, message);
},
setup_behavior: function(box_id, message) {
box_id = $(box_id);
if(box_id) {
if(box_id.value == '') {
box_id.value = message;
box_id.addClassName('inactive');
}
Event.observe(box_id, 'focus', function() {
if(box_id.value == message) {
box_id.value = '';
box_id.removeClassName('inactive');
}
});
Event.observe(box_id, 'blur', function() {
if(box_id.value == '') {
box_id.addClassName('inactive');
box_id.value = message;
}
});
}
}
};
SetupDefaultInputs = {
initialize: function() {
Event.observe(document, 'dom:loaded', this.setup_default_inputs);
},
setup_default_inputs: function() {
SelfLabelingBox.initialize('search_text', 'Search');
}
};
Until next time!
Tags: code • javascript • prototype • snippet
Comment! |
Permalink
Wednesday, September 19, 2007
Inspired by the latest Ruby Quiz: IP to Country: #139, I coded up a utility to map ip addresses to country codes in erlang. It’s available on google-code at http://code.google.com/p/ip2country-erlang/.
Some experiences while making this thing work:
- It took me the better part of six hours to get this running. I suspect if I’d done this with Ruby, I’d have completed an elegant, fast solution in less than a half hour. However I did make this harder for me (see below).
- It uses the in-memory database that Erlang has: mnesia. There’s functions in there to populate the mnesia table with the csv file and then perform lookups on it.
- Higher-order functions is the name of the game. For just about every useful thing from looping down to iteration, to mapping elements of a list. Coming from a non-functional background, I find this very hard to grasp still. Also: non-mutable state. Count +=1 doesn’t work. [So how do you implement a counter? Recurse with a parameter].
- I miss the Ruby Standard Library very very badly. Of all the languages I’ve used, Ruby’s is the most concise and clear and manages to have just about every function you need in there. String manipulation in Erlang esp. is very cumbersome. Somebody probably should port over all the functions asap. lists:join, string:delete, string:delete_if etc. would be invaluable.
- The comma, semi-colons and fullstop craze (along with proper indentation) is sometimes very confusing. The rules are actually easy to remember, but when I nest functions using funs, I find I lose track of where I am and what’s supposed to happen. I started programming this using Aquamacs but it crashed on me midway while using the inbuilt shell. I hate stuff which crashes so I switched to Textmate’s erlang mode which isn’t as functional but does a decent job of parenthesis matching and auto-indent.
- Mnesia is a joy to use. I spent a lot of time just playing around with many examples because it’s fun to make a record, dump it and use list comprehensions to perform selects. It’s way more intuitive than using SQL. Witness this fragment:
qlc:q([X#ip_address_map.country_code || X <- mnesia:table(ip_address_map),
X#ip_address_map.range_from =< Ip_address_as_integer,
X#ip_address_map.range_to >= Ip_address_as_integer
]).
That actually just says: get the country code for all X where X is an mnesia table of type ip_address_map and where X’s ip_ranges are within range_from and range_to. No SQL and exactly as you’d do within the language.
- It feels very awkward to get Erlang to be a shell scripting language. I’m not sure escript is even supported anymore but it does work. Erlang is not for scripting.
- The whole exercise reminded me of my extreme newbiness. I’ve been dabbling off and on in Erlang for over four months now and still I’m not at a stage where I can code in it off the top of my head (this hasn’t happened before with any language, but admittedly all the others were just procedural ones). The problem is I’m not using it for anything big. That should hopefully change someday. [Not much hope, but does somebody want to hire me to work on erlang or lisp? :-)]
- The erlang mailing lists help a lot. Just being there you soak up a lot of info.
- Concurrent erlang is another ball game altogether.
Get started!
Tags: code • erlang
Comments (2) |
Permalink
Sunday, September 9, 2007
So here’s a SlideShare/Twitter Mashup (command-line ruby code) that does these things:
- Gets buzzwords from Twitter. It does this by analyzing tweets and getting popular words (filtering out common ones) with the Twitter API.
- Gets the most popular buzz word and searches the SlideShare tag database with it (using the SlideShare API).
- Prints out the buzzword and the slideshows that’s associated with it.
The source code might not be a great example of filtering and getting popular words, but it’s a good demo of how simple the Twitter and SlideShare APIs are (REST yay) and how easy Hpricot makes parsing XML docs.
There’s a zip (with the source code, common_words.txt, twitter_words.txt) here: slideshare_twitter.zip. Enjoy.
Tags: api • code • development • slideshare • twitter
Comments (2) |
Permalink
Saturday, September 1, 2007
Ponder this:
fact (0) ->
1;
fact (N) ->
N * fact (N - 1).
versus this:
fact(N) ->
fact_helper(N, 1).
fact_helper(1, T) ->
T;
fact_helper(N, T) ->
fact_helper(N - 1, T * N).
The advantage of learning Erlang (albeit very slowly, with lots of interruptions) is that it directly introduces a lot of concepts I’ve been marginally aware of before. For instance, the second example implements factorial using tail recursion. The advantage is that a compiler doesn’t have to implement a call-stack when playing with arguments. See wikipedia entry.
Tags: code • development • erlang
Comments (1) |
Permalink
Friday, August 10, 2007
This is a fix for the excellent Miniposts plugin by Morgan Doocy. There’s a miniposts2 variant that includes this fix as well, but since I don’t use widgets yet (or maybe will never) here’s the fix. Took me around a half hour of hacking. Thanks to this excellent guide. [The problem was every time somebody commented I lost the ‘mini-postiness’ of the post. Kinda nasty.]
mini-postsphp.txt and just the diff.
Tags: code • PHP • wordpress
Comments (5) |
Permalink
Tuesday, April 3, 2007
Witness: algorithm for finding factorial of a number.
fact(0) -> 1;
fact(N) -> N * fact(N - 1).
That of finding all permutations of a given string. "abc" -> ["abc", "acb", "bac", "bca", "cab", "cba"]:
perms([]) -> [[]];
perms(L) -> [[H|T] || H < - L, T <- perms(L--[H])].
That of getting the ‘next’ iteration of any string. next("a") -> "b". next("z") -> "aa". next("az") -> "ba":
next(L) -> lists:reverse(incr(lists:reverse(L))).
incr(L) when L =:= [] -> [$a];
incr([H|T]) when H =:= $z -> [$a|incr(T)];
incr([H|T]) -> [H + 1|T].
Deliciously, all these are also (with the addition of a module and export line) complete and valid erlang programs.
Stay tuned. I’m loving erlang.
Tags: code • erlang
Comments (2) |
Permalink
Tuesday, September 5, 2006
Rails, if you’ve used it, has a rather elegant way of manipulating time. Stuff like 1.hours and 2.minutes.from_now just work. Let’s see how Ruby modules can be extended really really easily:
#! /usr/bin/env ruby
class Integer
def seconds
self
end
def minutes
seconds * 60
end
def hours
minutes * 60
end
def days
hours * 24
end
def months
days * 30
end
def years
months * 12
end
def from_now
Time.now + self
end
def before
Time.now - self
end
end
class String
def palindrome?
self == self.reverse
end
end
class Time
def leap_year?
(year % 4).zero? and ((not (year % 100).zero?) or (year % 1000).zero?)
end
end
class TrueClass
def say
"is"
end
end
class FalseClass
def say
"is not"
end
end
#2 is an Integer
puts 2.minutes.from_now
#"vishnu" is a String
puts "vishnu".palindrome?
puts "malayalam".palindrome?
puts 2.years.from_now.leap_year?
#Check if n years before is a leap year
puts "How many years before?"
year = Integer(readline)
puts "#{Time.now.year - year} #{year.years.before.leap_year?.say} a leap year."
The interesting thing about Ruby is not that metaprogramming is possible, but Ruby makes it really easy to do it.
Tags: code • ruby+rails
Comments (1) |
Permalink
Friday, August 4, 2006
I’ve been using Ruby a lot lately, and recently had to implement a “related” objects feature in Rails. You know, “Related Videos”, “Related Pages”, etc. I decided to sort them by objects that have the most common tags. Try this one-liner:
#Inside video.rb Model, Related videos
def related(count=5)
tags.collect { |tag| tag.videos }.flatten.uniq.sort_by { |video| (video.tags & tags).length }.delete_if { |video| self == video }.reverse[0..count-1] end
Let’s try dissecting that:
tags.collect { |tag| tag.videos }
Collects all videos associated with the current object’s tags into an array of arrays (each array representing the slideshows for a particular tag).
.flatten.uniq
Flatten that array (make it a single dimensional array, preserving logical order) and then eliminate duplicates
.sort_by { |video| (video.tags & tags).length }
sort_by sorts the arrays by a particular attribute. So for each video in the array, video.tags & tags gives the intersection of tags for the video under consideration, and the current object’s tags. Because of .length, the sort_by function sorts by the number of such intersecting tags.
.delete_if { |video| self == video }
And, remove self references.
.reverse
Sorting is by default ascending, so reverse the array, and:
[0..count-1]
return only the first n elements.
So, you’d call it by something like video = Video.find(1) and @related_videos = video.related.
The interesting thing is that, I never ever was a programmer given to verbose lengths of code like this. Doing this in any other language would feel so clunky. But in Ruby, it somehow feels natural. Like you can read through the code in your head and have it make perfect sense.
Tags: code • ruby+rails
Comments (4) |
Permalink
Saturday, March 11, 2006
Rather inspired by today’s Neural Networks exam, and Anoop’s amazing tutoring on the topic, I created a simple MENACE emulator in Python. Both the source and the Win executable are available below, and licensed under an MIT/Academic Free License. In other words, do anything you want with it, and try to give me credit
A simple menacing in a console would show you a tic-tac-toe board with a player choice to make. menacing --state shows the current state of the matchboxes. menacing --debug shows how the program thinks as it plays the game. menacing --train [iterations] allows you to train the matchboxes using a computer vs. computer mode.
If you download the Windows executable bundle, go to the dist folder to find menacing.exe. It’s a console application, so you’ll have to run cmd.exe, navigate to this folder and then execute it for maximum satisfaction. If you’re downloading the source, run menacing --init first.
I’d love it if you post your experiences with menacing here. Thanks
How do you train it from a dumb saved matchbox? Initially play to lose (say for about 10 tries, and then play to win always, I find this to be the best method to train). Or use --train and your work is done for you
Learn more about MENACE here and here.
The Windows bundle is slightly out of date as of this posting, should be resolved soon. So get the source for the latest.
Source | Source + Windows executable bundle
Tags: code
Comments (10) |
Permalink
Wednesday, August 31, 2005
Wordmaker is a python program that helps people learn words and their meanings. It’s a console program, so run it from the command line. Use wordmaker --update initially to retrieve a seed list from the web (fetched from the Sig9 Words database), and then use wordmaker to output a list of word/meaning/usage triads. The mode I find most useful though is wordmaker --question which lists the word first allowing you to recall it from your memory, and only then displays the meaning and usage.
It’s a very simple and ad hoc python program with less than 65 lines of code. I’ve uploaded both the source and the windows binary out here. It’s BSD licensed, feel free to do what you want with it.
TODO: It’s not entirely synced with the words list as of now, but that requires a server patch-up. Maybe if/when Vivek feels like it, he’ll work on that.
Download: Source | Windows Binary
Tags: code
Comment! |
Permalink
Saturday, June 5, 2004
SMS Yell is a bulk SMS messenger for the Windows platform. It is coded using Python but uses COM so it’s platform specific, but it’s modeled on a unix console app. It can be used for sending a message to multiple users multiple number of times. The source is released under the MIT academic/free license. Enjoy!
Download: Source (2K) | Windows Binary (1.3MB)
Tags: code
Comments (1) |
Permalink
Wednesday, February 4, 2004
Mangle is a python script that converts html code into mangled javascript. It’s mostly used to prevent spam harvesters from getting your mail id, though it can be used in any instance where you want to hide your content in the code.
Mangle is a command-line program, it accepts a single argument which is the code to be mangled, and outputs the complete javascript code that you should paste where you want the text to appear. Note that mangle makes it very hard for a spammer to harvest your mail, but with a javascript capable mail-harvester, this method fails.
This is inspired by one of the methods in the Hiveware Enkoder since the offline solution provided by the site is way out-of-date.
Download: [Python script, Windows .ZIP]
Tags: code
Comment! |
Permalink