Code

Coding, Programming & Algorithms, Tips, Tweaks & Hacks
Search

Sponsored Ads
WebFaction
Sponsored Ads
GermFREE
MadMimi
  • Mad Mimi Email Marketing

Convert CSV to JSON

Sometimes I find myself converting google doc spreadsheets (CSV) to JSON format. I would later on use the JSON string to insert it into a JavaScript file.
So here is a simple script to convert a CSV file to JSON format.

Python
import sys, csv, json

if len(sys.argv) == 1:
    print "1 argument for filename required"
    sys.exit()

gdoc = csv.reader(open(sys.argv[1]))

# Get the 1st line, assuming it contains the column titles
fieldnames = gdoc.next() 

# Get the total number of columns
fieldnames_len = len(fieldnames)

data = [] # Empty list
i = 0

for row in gdoc:
    
    # Add an empty dict to the list
    data.append({})
    
    for j in range(0, len(row)):
        data[i][fieldnames[j]] = row[j]
    
    # What if the last few cells are empty ? There may not be commas
    for j in range(len(row), fieldnames_len):
        data[i][fieldnames[j]] = ""
    
    i = i + 1

print json.dumps(data)
sys.exit()
Python 2.7.2
Vanakkam !

Using WebP image format for browsers that support it

The WebP image format for the web is starting to get a lot of hype for its massive file compression. Chrome supports it since ver 9 and Opera since ver 11.10.
Image file sizes are reduced by more than 50% in WebPs when compared to JPGs.
Looking at Google Analytics on various sites, Chrome 9+ users constitute 20% - 25%. So providing one-fifth or one-fourth of the users with a much reduced page load is worth the extra effort.

1. Convert JPGs / PNGs to WebPs :

for i in *.jpg; do j=`echo "$i" | cut -d . -f 1`; convert -colorspace RGB "$i" "$i"; ~/libwebp/cwebp -q 75 "$i" -o "${j}.webp"; done

convert is used to convert the colourspace from RGB to CMYK since as of now, webp encoder doesn't support CMYK colourspace.

2. Use 2 different CSS files for background images - one for standard jpg/png and another for webp. Chrome 9+ and Opera 11.10+ would be served webp.css while all others img.css.

get_browser is pretty useful for browser detection, but requires to set browscap in php.ini which is a PHP_INI_SYSTEM directive and can't be set in using ini_set(), .htaccess or user php.ini which rules out almost all shared hosting enviroments.
But interestingly, this is possible in WebFaction where I could set browscap in a user php.ini file which was parsed.

PHP
<?php
$imgCSS = "img";
$browser = get_browser(null, true);
if (($browser['browser'] = "Chrome" && $browser['version'] >= 9) || ($browser['browser'] = "Opera" && $browser['version'] >= 11.10))
$imgCSS = "webp";
?>
.
.
.
<link rel="stylesheet" type="text/css" media="all" href="<?php echo $imgCSS ?>.css" />
PHP 5.2

If you are getting something like ...

<b>Warning</b>:  get_browser() [<a href='function.get-browser'>function.get-browser</a>]: browscap ini directive not set in <b>/path/script.php</b> on line <b>7</b>

and if there is no way to set browscap, then you need to find an alternative browser detection like phpbrowscap.

I benchmarked this on a graphically heavy wordpress site, having 11 photographs in a slider on the homepage which takes a megabyte alone.

BrowserRequestsSizeTime
FireFox 3.6311.9 MB21.48s (onload: 20.62s)
Chrome 1132577.90KB6.51s (onload: 6.51s, DOMContentLoaded: 2.88s)

(I could not find the option to view total bytes downloaded in Opera dragonfly's network tab)

Side Note : When uploading webp images to google storage, S3 or any other cloud service, specify the content-type / mime-type.

gsutil -h "Cache-Control:public,max-age=31536000" -h "Content-Type: image/webp" cp -a public-read kitten.webp gs://[bucket]/images/kitten.webp
s3cmd put kitten.webp s3://[bucket]/images/ --acl-public --mime-type "image/webp" --add-header="Cache-Control:max-age=315360000"
Vanakkam !

Alexa Rank function in Google Apps Script

Google Apps Script is JavaScript based scripting for many of Google's services, most noteably, Google Spreadsheets, like VB Macros for Excel.
There are some subtilities in JavaScript, like window and document not being defined. Though the scripting is mostly JavaScript, it is not 100% native JavaScript since it runs in an app and not in the browser.
Currently Google Apps Script has a computeHmacSha256Signature() function but Amazon's AWIS requires a SHA-1 key for its signature which can be obtained from jsSHA. I've clipped the jsSHA code from here as its too lengthy. You can download it from sourceforge, copy-paste the code from /src/sha1.js. A small change is required though. Change b64pad="" to b64pad="=".

Google Apps Script
/*
* When defining a local function 'foo' in a closure, at the end, it is declared global by window.foo = foo
* Google Apps Script has window and document undefined
*/
var window = {};

// Amazon Web Information Services
var AWIS =
{
SERVICE_ENDPOINT : 'http://awis.amazonaws.com/?',
ACTION : 'UrlInfo',
RESPONSE_GROUP : 'Rank',
ACCESS_KEY_ID : "your-access-id",
SECRET_ACCESS_KEY : "your-secret-key"
}

/*
* Validate if a string is of proper domain
* @param String domain
* @return Boolean false if invalid, true if valid
* There are many more tests, this one is just to avoid a bad cell-value
*/
function isValidDomain(domain)
{
if (domain.indexOf(".") < 1) return false;
if (domain.indexOf(":") != -1) return false;
return true;
}

/*
* Get just the hostname from a URL
* @param String URL
* @return String hostname
* http://en.wikipedia.org/wiki/URI_scheme#Examples
*/
function getHostname(url)
{
return url.replace(/http(s*):\/\/(.[^/\?]+)(\/*)(.*)$/g, "$2").toLowerCase();
}

/*
* Validate cellvalue to be of a proper domain
* @param String domain cell-value
* @return Integer Alexa Rank
*/
function getAlexaRank(domain)
{
if (!isValidDomain(domain)) return domain + " is not a valid domain";
var hostname = getHostname(domain);

if (AWIS.ACCESS_KEY_ID == "" || AWIS.ACCESS_KEY_ID == "undefined") return "Error : AWS AccessKey not yet set";
if (AWIS.SECRET_ACCESS_KEY == "" || AWIS.SECRET_ACCESS_KEY == "undefined") return "Error : AWS SecretKey not yet set";

var timestamp = generate_timestamp();
var shaObj = new window.jsSHA(AWIS.ACTION + timestamp, 'ASCII');
var signature = shaObj.getHMAC(AWIS.SECRET_ACCESS_KEY, 'ASCII', 'B64');
var awis_url = AWIS.SERVICE_ENDPOINT + "AWSAccessKeyId=" + AWIS.ACCESS_KEY_ID + "&Action=" + AWIS.ACTION + "&ResponseGroup=" + AWIS.RESPONSE_GROUP + "&Timestamp=" + encodeURIComponent(timestamp) + "&Signature=" + encodeURIComponent(signature) + "&Url=" + encodeURIComponent(hostname);

try
{
var response = UrlFetchApp.fetch(awis_url);
}
catch (err)
{
return "Error in URL : " + awis_url;
}

var sXML = response.getContentText();
var oXML = Xml.parse(sXML, false);
var root = oXML.getElement();
var Response = root.getElements("http://awis.amazonaws.com/doc/2005-07-11","Response");
var UrlInfoResult = Response[0].getElements("http://awis.amazonaws.com/doc/2005-07-11","UrlInfoResult");
var Alexa = UrlInfoResult[0].getElements("http://awis.amazonaws.com/doc/2005-07-11","Alexa");
var TrafficData = Alexa[0].getElements("http://awis.amazonaws.com/doc/2005-07-11","TrafficData");
var Rank = TrafficData[0].getElements("http://awis.amazonaws.com/doc/2005-07-11","Rank");
return Rank[0].getText();
}

/*
* Generate Timestamp of current time
* http://www.w3.org/TR/xmlschema-2/#dateTime
* @return String UTC time in yyyy-MM-dd'T'HH:mm:ss.SSS'Z' format
*/
function generate_timestamp()
{
var now = new Date();

var yyyy = now.getUTCFullYear();
var mm = now.getUTCMonth() < 9 ? "0" + (now.getUTCMonth() + 1) : (now.getUTCMonth() + 1);
var dd = now.getUTCDate() < 10 ? "0" + now.getUTCDate() : now.getUTCDate();

var HH = now.getUTCHours() < 10 ? "0" + now.getUTCHours() : now.getUTCHours();
var ii = now.getUTCMinutes() < 10 ? "0" + now.getUTCMinutes() : now.getUTCMinutes();
var ss = now.getUTCSeconds() < 10 ? "0" + now.getUTCSeconds() : now.getUTCSeconds();

return yyyy + "-" + mm + "-" + dd + "T" + HH + ":" + ii + ":" + ss + ".000Z";
}

/*
* Copy /src/sha1.js from jsSHA (http://jssha.sourceforge.net)
* Currently Google Apps Script has a computeHmacSha256Signature() function but Amazon's AWIS requires a SHA-1 key for its signature
* Also, change b64pad="" to b64pad="="
*/
(function(){var charSize=8,b64pad="=",hexCase=0,str2binb=function(a) ... ;window.jsSHA=jsSHA}());
JavaScript
Vanakkam !

Trigerring error() on a cross-domain AJAX request

Opera was the only browser that triggered the error function when an illegal cross-domain AJAX request was being tried via jQuery.

HTML + JavaScript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>XDOM</title>
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
    $.ajax(
    {
        url: "http://www.microsoft.com/robots.txt",
        dataType: "text",
        beforeSend: function(XMLHttpRequest)
        {
            $('body').append("sending ... <br/>");
        },
        success: function(data)
        {
            $('body').append("<b>success :</b> data = " + data + "<br/>");
        },
        error: function(XMLHttpRequest, textStatus, errorThrown)
        {
            $('body').append("<b>error :</b> textStatus = " + textStatus + ", errorThrown = " + errorThrown + "<br/>");
        },
        complete: function(XMLHttpRequest, textStatus)
        {
            $('body').append("<b>complete :</b> textStatus = " + textStatus + "<br/>");
        }
    });
});
</script>
</head>
<body></body>
</html>
HTML + JavaScript

FireFox, Chrome & Safari :

sending ...
success : data =
complete : textStatus = success

Opera :

sending ...
error : textStatus = null, errorThrown = ReferenceError: Security violation
complete : textStatus = undefined

Internet Explorer just didn't fire any of the events - the debugger reported a security violation.

Vanakkam !

Google Visualization & Google Maps using GeoCoding

Flash & JavaScript examples of using markers & geocoding on Maps.
I've never been a big fan of Flash, given that that's what dominates the web design animation spectrum.
Agreed that you can make things look much cooler very easily using Flash, while achieving the same UI using JavaScript may take 10 times the effort. But this should change over time with the development of HTML5's canvas element.
With Google's Visualization Geomap API you can get the nice map interface that you've seen in Google Analytics.
But the Maps API is lighter and you can move it around & zoom using the mouse.

Google Visualization Geomap API
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Google Visualization Geomap API</title>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1', {'packages': ['geomap']});
var population =
[
['Mumbai',13830884],['Delhi',12565901],
['Bangalore',5438065],['Kolkata',5138208],
['Chennai',4616639],['Hyderabad',4068611],
['Ahmedabad',3959432],['Pune',3446330],
['Surat',3344135],['Kanpur',3221435],
['Jaipur',3210570],['Lucknow',2750447],
['Nagpur',2447063],['Patna',1875572],
['Indore',1854930],['Thane',1807616],
['Bhopal',1792203],['Ludhiana',1740247],
['Agra',1686976],['Pimpri Chinchwad',1637905]
];
google.setOnLoadCallback(function()
{
var data = new google.visualization.DataTable();
data.addColumn('string', 'City');
data.addColumn('number', 'Population');
data.addRows(population);
var geomap = new google.visualization.GeoMap(document.getElementById('geomap'));
geomap.draw(data, {width:'500px',height:'500px',region:'IN',dataMode:'markers',showLegend:false});
});
</script>
</head>
<body>
<div id="geomap" style="width:500px;height:500px;"></div>
</body>
</html>
JavaScript

Google Visualization in Browser

Google Maps & Geocoder
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<title>Google Maps and GeoCoder API</title>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('maps', '3', {"other_params":"sensor=true"});
var population =
[
['Mumbai','13,830,884'],['Delhi','12,565,901'],
['Bangalore','5,438,065'],['Kolkata','5,138,208'],
['Chennai','4,616,639'],['Hyderabad','4,068,611'],
['Ahmedabad','3,959,432'],['Pune','3,446,330'],
['Surat','3,344,135'],['Kanpur','3,221,435']
];
var map;
google.setOnLoadCallback(function()
{
var point = new google.maps.LatLng(24.046464, 81.342773);
var options =
{
zoom:5,
center:point,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("geomap"), options);
geocoder = new google.maps.Geocoder();
for (var i = 0; i < population.length; i++)
{
geocoder.geocode({'address':population[i][0]}, createMarker(i));
}
});

function createMarker(i)
{
return function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
var infowindow = new google.maps.InfoWindow({ content: "<div><h3>Population of " + population[i][0] + "</h3><p>" + population[i][1] + "</p></div>" });
var marker = new google.maps.Marker(
{
position:results[0].geometry.location,
map:map,
title:population[i][1]
});
google.maps.event.addListener(marker, 'click', function() { infowindow.open(map,marker); });
}
else
{
alert("Geocode was not successful for the following reason: " + status);
}
}
}
</script>
</head>
<body>
<div id="geomap" style="width:650px;height:800px;"></div>
</body>
</html>
JavaScript

Google Maps

Limitations with Visualization API :

  • A maximum of 400 entries (markers)
  • Much slower if the data format is an address instead of a Latitude/Longitude pair
  • If you are targetting India, Maps is the better way to go as the Visualization API has cut off a major portion of the J&K !

Limitations with Google Maps :

  • Geocoder has a limit of 2500 requests per day, and looks about like 10 requests at a time.
  • Need to center the map and adjust zoom level manually to show withing the bounding div. Visualization API does this automatically by specifying region:'IN'

In both cases, storing Latitude/Longitude pairs offline and then geo-locating the same renders a whole lot faster.

Vanakkam !

One-liner check for the existence of all required fields from a POSTed form

If you have a simple contact / registration form for a non-CMS / non-framework website with many input fields, it becomes cumbersome to do a server check if all fields passed through doing isset for every field. Many people just check for the existance of a single POST field, but for security reasons, it is better to check for the existence of all required fields.

PHP
if (isset($_POST['name']) && isset($_POST['email']) && isset($_POST['phone']) && isset($_POST['message']))
{
    # POSTed
    # Process form
}
PHP

What if there were 20 fields ? That'll be one long line of issets.
array_diff is a built-in array function in PHP that computes the difference between arrays - it returns an array containing all the entries from the first array that are not present in any of the other arrays.
All we need to check is if the list of required fields are all present as keys in $_POST - this is easily achievable by checking against array_keys of $_POST.
And finally for the count - if all required fields are present in the $_POST's keys, it'll return 0 which is what we want and how we can confirm that all POST field values got sent through.

PHP
$requiredFields = array('name','email','phone','message');
if (count(array_diff($requiredFields, array_keys($_POST))) == 0)
{
    # POSTed
    # Process form
}
PHP
Vanakkam !

Python2's String = Python3's Text Vs. Data

A significant change from Python 2 to Python 3 is the way strings are dealt with.
Python 3 doesnt always return a string when expected.
For example, the return type of read() in version 2 has always been a string. But in version 3, its very often a "bytes" string.
When you print a "bytes" string, you'll see every character in its byte format, special characters as escape secquences (newline as \n) and other unicode characters as escape sequences.
This is because Python 3 differentiates between text (string) and data ("bytes" string) as oppossed to Unicode vs 8-bit string. (Text Vs. Data Instead Of Unicode Vs. 8-bit)

My localhost/index.html contains just this :
<html><body><h1>It works!. stärke gläser</h1></body></html>

Python 2.x
import urllib

url = "http://localhost"
fp = urllib.urlopen(url)
data = fp.read()
print "%s, %s" % (type(data), type(data).__name__)
print data
Python 2.6.4
Python 2.x
~$ python
Python 2.6.4 (r264:75706, Nov 2 2009, 14:44:17)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib
>>> url = "http://localhost"
>>> fp = urllib.urlopen(url)
>>> data = fp.read()
>>> print "%s, %s" % (type(data), type(data).__name__)
<type 'str'>, str
>>> print data
<html><body><h1>It works!. stärke gläser</h1></body></html>

>>>
Python 2.6.4

In Python 3, we need to need to explicitly convert it to string format via the str() function and specify the encoding-type.
If you are getting errors using Python 3.0, you may want to update to atleast Python 3.0.1 - many have reported possible Unciode encoding/decoding bugs in 3.0.

Python 3.x
import urllib.request

url = "http://localhost"
fp = urllib.request.urlopen(url)
data = fp.read()
print ("%s, %s" % (type(data), type(data).__name__))
print (data)
data = str(data,'utf-8') # convert a byte datatype to string datatype using utf-8 encoding. For ASCII, data = str(data,'ascii')
print (data)
Python 3.1.1
Python 3.x
~$ python3
Python 3.1.1+ (r311:74480, Oct 12 2009, 02:14:03)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib.request
>>> url = "http://localhost"
>>> fp = urllib.request.urlopen(url)
>>> data = fp.read()
>>> print ("%s, %s" % (type(data), type(data).__name__))
<class 'bytes'>, bytes
>>> print (data)
b'<html><body><h1>It works!. st\xc3\xa4rke gl\xc3\xa4ser</h1></body></html>\n'
>>> data = str(data,'utf-8') # convert a byte datatype to string datatype using utf-8 encoding. For ASCII, data = str(data,'ascii')
>>> print (data)
<html><body><h1>It works!. stärke gläser</h1></body></html>

>>>
Python 3.1.1
Vanakkam !

Sorting a String in SQL

Even though stored procedures are really slow, sometimes they come in handy.
SQL
DROP FUNCTION IF EXISTS `SORTEDSTRING`;
DELIMITER ///
CREATE FUNCTION SORTEDSTRING(s VARCHAR(1000)) RETURNS VARCHAR(1000) DETERMINISTIC
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE j INT;
    DECLARE si CHAR(1);
    DECLARE sj CHAR(1);
    DECLARE ss VARCHAR(1000); -- Sorted String

    SET ss = s;
    SET @length = LENGTH(s);

    WHILE i < @length DO
        SET j = i + 1;
        WHILE j <= @length DO
            SET si = SUBSTRING(ss, i, 1);
            SET sj = SUBSTRING(ss, j, 1);
            IF si > sj THEN
                SET ss = INSERT(ss, i, 1, sj);
                SET ss = INSERT(ss, j, 1, si);
            END IF;
            SET j = j + 1;
        END WHILE;
        SET i = i + 1;
    END WHILE;

    RETURN ss;
END
///
DELIMITER ;

mysql> SELECT SORTEDSTRING("elephant");
+--------------------------+
| SORTEDSTRING("elephant") |
+--------------------------+
| aeehlnpt                 |
+--------------------------+
1 row in set (0.00 sec)

mysql>
MySQL 5.0
Vanakkam !

Loading AJAX locally, without a webserver

So far, while developing web applications I have always taken one point into assumption - that it has to run on a web-server. But when dealing with pure client-side web apps, we often overlook the fact that it should be able to be run by simply double-clicking on the homepage file (index.html). When XMLHttpRequest's readyState reaches a value of 4, we further check for a response code 200 from the web-server before doing anything with the responseText / responseXML. But when running it locally - not on a webserver, the status code value will alway be 0.
JavaScript
window.onload = function()
{
    var xhr = NewXMLHttpRequest();
    if (xhr != false)
    {
        try
        {
            xhr.open("GET", "local-ajax.txt", true);
            xhr.onreadystatechange = xhr_load;
            xhr.setRequestHeader("Connection", "close");
            xhr.send(null);
        }
        catch(e)
        {
            alert("Error Loading File\n" + e.code + "\n" + e.message);
        }
    }
    else
    {
        alert("AJAX not supported");
    }
}

function xhr_load()
{
    switch (this.readyState)
    {
        case 1: // Open
        case 2: // Send
        case 3: // Receiving
        break;

        case 4: // Loaded
        if (this.status == 200 || (this.status == 0 && document.location.protocol == "file:")) // OK
        {
            var text = this.responseText;
            alert(text);
        }
        break;
    }
}

function NewXMLHttpRequest()
{
    var xhr = false;

    if (window.XMLHttpRequest) // native XMLHttpRequest object
    {
        try { xhr = new XMLHttpRequest(); }
        catch(e) { xhr = false; }
    }
    else if (window.ActiveXObject) // IE/Windows ActiveX version
    {
        try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); }
        catch(e)
        {
            try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
            catch(e) { xhr = false; }
        }
    }

    return xhr;
}
JavaScript 1.5
Vanakkam !

1 pixel wide line parallel to the axis in HTML's Canvas element

I was playing around with HTML's Canvas element and I spent a whole day trying to figure out why I can't draw a 1-pixel wide straight line (parallel to the axes). If you try dawing a black (#000000) straight line parallel to the axes, then for all odd numbered widths :
  • the first line is of colour #9d9d9d and the last one is of #8d8d8d
  • The width of the line is one pixel more
Canvas Lines
<html>
<head>
        <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
        <title>HTML5 - Canvas</title>
        <meta http-equiv="Content-Language" content="en-us"/>
        <script type="text/javascript">
        function foo()
        {
            var canvas = document.getElementById("canvas-line");
            var ctx = canvas.getContext('2d');
            
            for (i = 1, j = 0; i < 15; i++, j+=i+7)
            {
                ctx.beginPath();
                ctx.lineWidth = i;
                ctx.strokeStyle = "black";
                ctx.moveTo(50,25 + j);
                ctx.lineTo(300,25 + j);
                ctx.stroke();
            }
        }

        </script>
</head>
<body onload="foo()">
<canvas id="canvas-line" width="350" height="250" style="border:1px solid #cf1313; margin-left:100px;"></canvas>
</body>
</html>
HTML 5 + JavaScript
The above should give an output like this : If you zooom in, you should be able to see the top and bottom border colours. This happens in all canvas-supported browsers (FF 3, FF 3.5 beta 4, Opera 10 beta, Chrome 2 beta, Safari 4 beta). Reason : https://developer.mozilla.org/en/Canvas_tutorial/Applying_styles_and_colors#section_8 Mozilla's canvas tutorial on drawing shapes shows a screenshot which has the inner most rectangle of exactly 1 pixel wide and colour black. But viewing the example itself in the browser, shows otherwise - 2 pixel wide with faded colours. I've written a small function that draws exactly 1 pixel wide straight line parallel to the axis.
1 pixel wide Canvas line
<html>
<head>
        <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
        <title>HTML5 - Canvas</title>
        <meta http-equiv="Content-Language" content="en-us"/>
        <script type="text/javascript">
        /*
        draw1pxLinePA
            Draw a 1 pixel width line parallel to the axis
        Parameters
            x : x coordinate
            y : y coordinate
            l : length
            o : orientation
                0 = horizontal (default)
                1 = vertical
            bg : erase-with colour - for background
        */
        CanvasRenderingContext2D.prototype.draw1pxLinePA = function(x, y, l, o, bg)
        {
            o = o || 0;
            bg = bg || "white";

            this.beginPath();
            this.lineWidth = 2; // 1 creates a 2 pixel wide line with fading
            this.moveTo(x, y);
            this.lineTo(x + (l * !o), y + (l * o));
            this.stroke();

            var strokeStyle = this.strokeStyle; // Save current strokeStyle

            // Erase the extra line
            this.beginPath();
            this.lineWidth = 2;
            this.strokeStyle = bg;
            this.moveTo(x + (1 * o), y + (1 * !o));
            this.lineTo(x + (l * !o) + (1 * o), y + (l * o) + (1 * !o));
            this.stroke();

            this.strokeStyle = strokeStyle; // Restore strokeStyle
        }

        function foo()
        {
            var canvas = document.getElementById("canvas-line");
            var ctx = canvas.getContext('2d');

            ctx.strokeStyle = "black";
            ctx.draw1pxLinePA(20, 20, 260, 1);
            ctx.draw1pxLinePA(30, 150, 400);
        }

        </script>
</head>
<body onload="foo()">

<canvas id="canvas-line" width="450" height="300" style="border:1px solid #cf1313; margin-left:100px;"></canvas>

</body>
</html>
HTML 5 + JavaScript
Vanakkam !