Sunday, February 21, 2010

Solve absolute URL – relative URL issue without code changes using BASE tag (Google AJAX Feed API)


The Application


I was trying out a sample application using Google AJAX Feed API. The feeds were requested from a C# windows application and the responses (feed’s HTML content) were shown in a WebBrowser control.

The Problem

The weird problem was that the HTML snippet for some feed has relative URLs and they failed to display in the WebBrowser control. [For those, who are wondering what a relative and absolute URL is, see below.]

<!-- absolute URL -->
<img src="http://www.mywebsite.com/images/image.gif" />

<!-- relative URL -->
<img src="images/image.gif" />

When i searched for it, few were trying to do a content search and to replace the relative URLs with absolute URLs. Well, this might be needed in some scenarios, but, not in my case, since the content gets rendered in a WebBrowser control.

The Solution

The BASE tag can help us here. For me, I just put the feed content inside an HTML header section with BASE tag as shown below and now my feed renders fine; added the BASE-Target option also to make it better.


<html>
<head>
<base href="http://www.mywebsite.com/images/" />
<!-- in the case of Google API, this was feed's link -->
<base target="_blank" />
<!-- Provided this so that the links will open in new window -->
</head>

<body>
<!-- in the case of Google API, body has feed content -->
<img src="image.gif" />
<a href="http://www.mynewwebsite.com">New Website</a>
</body>
</html>

The Conclusion

Hope this solves the problem for few and the logic (use of BASE tag) will be useful in other scenarios too. As for the Google AJAX Feed API, I'm hoping that Google will fix this in the upcoming versions.

Saturday, February 13, 2010

Create simple and reusable objects for AJAX in JavaScript – ajaxRequest

Well, there are similar ones out there. jQuery, YUI and AjaxObject are just to name a few, which has their own implementations along with other in-built functionalities. Then there is mine, which is done in a much simpler way with the cost of flexibility. If you’re just looking for a simple reusable JavaScript class for making AJAX calls (and AJAX calls only), you're at the right place.

For Beginners:
For the sake of the simplicity of this article, i will not be going in much detail about the basics of HTTP calls, the different modes (POST, GET) of communications and their related topics. Let’s just say that, an HTTP call or an AJAX call can be made to a URL (Ex: http://www.mywebsite.com) using either GET (where URL has all the information like http://www.mywebsite.com?name=john&age=25) or POST (where the form data is submitted as key-value pair like key1=value1&key2=value2 with appropriate header information on the request). Oops! did i just said everything about HTTP calls in one sentence? No, there is more.

The ajaxRequest Snippet
Here is the ajaxRequest’s code. The code is pretty straightforward and is designed in such a way that it works with minimum arguments. There are comments embedded in the code (download from below) and sample usage code provided below to make it’s use seamless.

function ajaxRequest(url, method, postData) {
//validation start
if (url == undefined) return false;
this.method = method == undefined ? "GET" : method.toUpperCase();
if (this.method != "GET" && this.method != "POST") return false;
if (url == undefined || url == "") return false;
//validation end
this.url = url + ((url.indexOf('?') > 0) ? "&ajts" : "?ajts") + new Date().getTime();
var mainCls = this;
this.inProgress = false;
this.xmlHttpObj = null;
this.postData = postData;
this.toString = function() { return "Ajax by Sanal"; }
this.abort = function() {
if (mainCls.inProgress) {
mainCls.xmlHttpObj.abort();
mainCls.inProgress = false;
mainCls.xmlHttpObj = null;
}
}
this.execute = function(statusChangeFunction) {
try {
// Firefox, Opera 8.0+, Safari
mainCls.xmlHttpObj = new XMLHttpRequest();
}
catch (e) {
// Internet Explorer
try {
mainCls.xmlHttpObj = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
mainCls.xmlHttpObj = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {

return false; //No support for AJAX
}
}
}

mainCls.xmlHttpObj.onreadystatechange = function() {
if (statusChangeFunction) {
statusChangeFunction(mainCls.xmlHttpObj.readyState, typeof (mainCls.xmlHttpObj.responseText) == "unknown" ? null : mainCls.xmlHttpObj.responseText, typeof (mainCls.xmlHttpObj.responseXML) == "unknown" ? null : mainCls.xmlHttpObj.responseXML, mainCls.xmlHttpObj.readyState==4 ? mainCls.xmlHttpObj.status : null);
}
if (mainCls.xmlHttpObj.readyState == 4) {
mainCls.inProgress = false;
mainCls.xmlHttpObj = null;
}
}

mainCls.xmlHttpObj.open(mainCls.method, mainCls.url, true);
if (mainCls.method == "POST") {
mainCls.xmlHttpObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
mainCls.xmlHttpObj.setRequestHeader("Content-Length", mainCls.postData.length);
}
mainCls.inProgress = true;
mainCls.xmlHttpObj.send(mainCls.method == "POST" ? mainCls.postData : null);
return true;
}
}

Code Download
The above code with embedded comments, along with the minified version, can be downloaded from here. [In case, if you don't know, minified version will not have the comments and spaces, to keep the file size to a minimum possible, making the server-browser communication faster.]

Sample usage:
Provide a reference

First, let the browser know that it needs to load the script.

If you're using the minified version, change the file name appropriately.

Create an Object
Then, in another scripting place, create an object for ajaxRequest as shown below. In the example below, the testAjax function will be the function that triggers the AJAX call to the server url “ajaxprocessor.aspx” which in turn processes the aynschronous requests. Since there are no other arguments passed, the call is defaulted to a GET call and the URL is expected to have input parameters for server processing.

function testAjax() {
var myAjaxRequest = new ajaxRequest("ajaxprocessor.aspx?name=john");
myAjaxRequest.execute(processMyRequest);
myAjaxRequest = null;
}

One minor point to note here. Among the query strings that are being passed to the URL, it is not recommended to use the key "ajts" (AJAX timestamp) since that is being used by the ajaxRequest to make every AJAX call unique to the browser. This is applicable to both GET and POST requests.

Track your AJAX call
The “processMyRequest” function in the above code is the callback method, that gets executed when for every state change of your AJAX call. A simple implementation of the “processMyRequest” can be something like this. I’m assuming that you have a DIV with the id “myDIV” placed in your web page. [Beginners, you might want to know more about readyState and status for asynchronous calls]

function processMyRequest(readyState, responseText) {            
if (readyState == 1)//loaded
document.getElementById("myDIV").innerHTML = "Loading...";
else if (readyState == 4)//complete
document.getElementById("myDIV").innerHTML = responseText;
}

The callback function can be created with any number of arguments depending on the need. The arguments are in the order as specified in the main ajaxRequest code comments.

The sample approach can be used to make a POST call by changing the object creation as

var myAjaxRequest = new ajaxRequest("ajaxprocessor.aspx","POST","key1=value1&key2=value2”);

Refer the downloaded ajaxRequest code for more technical details on each of these methods and variables.

Browser Compatibility
This code has been tested with IE, Firefox and Chrome and is expected to be working in most of the browsers. If problems are found, share them so that everyone will know.

Enhancements
Well, as mentioned at the beginning of this article, this might not be flexible enough. if you dig deep enough, you might find functionalities that could’ve included to make it better. Feel free to change the code for your usage and let me know what was missing.

Thursday, February 4, 2010

Retrieve an element's width or height using JavaScript

Even though, not 100% browser independent, the following JavaScript code will get you an element's current/rendered width or height. The code is pretty simple and self-explanatory.

Code to retrieve element's width:
function getWidth(element){

    if (typeof element.clip !== "undefined") //netscape
    {
        return element.clip.width;
    }
    else {
        if (element.style.pixelWidth)//opera 
        {
            return element.style.pixelWidth;
        }
        else //IE and firefox
        {
            return element.offsetWidth;
        }
    }
}
Code to retrieve element's height:
function getHeight(element){

    if (typeof element.clip !== "undefined")    //netscape
    {
        return element.clip.height;
    }
    else {
        if (element.style.pixelHeight) //opera
        {
            return element.style.pixelHeight;
        }
        else //IE and firefox
        {
            return element.offsetHeight;
        }
    }
}
Sample Usage:
function usage(){
 alert(getWidth(document.getElementById("yourElementId")));
}
This code works for most of the input (dropdown/select-one/Select-multiple, textbox, textarea) elements in an HTML form. Feel free to share any better solutions.

Thursday, January 7, 2010

Picasa Vs Windows Live Photo Gallery - A quick comparison

If you're someone who went out to choose between Picasa and Windows Live Photo Gallery, don't look further. Picasa is the clear winner. At this instant, there are not even comparable. Read ahead for more information.

User Interface - Intuitiveness and simplicity
    Live photo gallery is simple and easy. The UI is not much congested as Picasa; may be because of the less visible features of Live gallery. Gallery is easy to play with. Picasa's UI has more options with various view modes and sliders all around providing greater flexibility. If your priority is for simplicity, Live Gallery wins here. But if you prefer flexibility, Picasa is the one.

Face Recognition
    This is one place where Picasa rocks! Picasa has the easiest workflow (to assign the names for the detected faces in photos) available. As soon as the photos are added, Picasa scans them and groups them for you to name them. Each naming seems to improve Picasa's intelligence and face detection becomes more reliable and less error-prone. Live Gallery needs more manual activity to add people tags, making the workflow more cumbersome. Both the tools sometimes detects some part of the images as faces, while actually they are not. Live Gallery needs to improve a lot on this aspect.

Image Editing
    Again, Picasa is much better here. You will love the one touch abilities to fix your images and the ability to provide watermark or captions.

Sharing, Syncing, Email and Printing
    Both of them inherently supports their own photo sharing services online. Live Gallery supports adding Plug-ins too for sharing to other sites. Sync is much customizable and powerful operation in Picasa when compared to Live Gallery.

Export
    Picasa allows you to export photos in bulk to the desired quality and size while Live gallery just provides a rename and resize facility for single images. Just in case, if you ended having some raw images for conversion, Picasa does this job much easier. You can even export them with watermarks. Common raw formats are supported by default in Picasa. Windows Live Gallery asks us to install plug-in for this.

Multiple format support for image and video
    Well, this one may vary per user. Based on the formats that i had, Picasa handled all my videos and images without the need of any additional codec installs. Live Gallery did asked me to install additional plug-in.

Tagging
    Picasa has the leading edge here due to the availability of Quick tags and it seems to support all the standard tagging mechanisms like IPTC and EXIF.

Search
    They both performed good here since they all searched based on tags and file names and provided the results.

Additional Features
    Live Gallery provides the facility to make a blog post and to create a Data CD with the images. Picasa goes much further in this aspect with Blogging, Collage, Geo-Tagging, Places association, multiple-image Screensaver, Movie Creation, Poster creation and list goes on...

Conclude Now
    This comparison can go further covering more minute details which doesn’t seem to be necessary for inferring the result. Picasa provides much more flexibility and features in all those individual modules implemented when compared to Windows Live Gallery. Hopefully, we can expect more from Windows Live Gallery in the near future.

If you’re in the lookout for similar tools with comparable capabilities, search for iPhoto (Mac) and Adobe Lightroom.

Sunday, December 20, 2009

Compare Google, Bing and Yahoo webmaster tools – who indexes faster?


Well, we all know that these giants provide search-engines which make our life better, by pointing us to the right web pages that we’re searching for. They have their own crawlers to find out what all of these web pages has as contents and to index (assuming that you know what is indexing) them. To assist this process, they all have webmaster tools too, so that web site owners can submit and update the information related to the websites they own to these search engines using sitemaps. The following list shows their webmaster tools and the links to them, as currently available.

Google Google Webmaster Tools http://www.google.com/webmasters/
Bing Webmaster Center http://www.bing.com/webmaster
Yahoo! Site Explorer http://siteexplorer.search.yahoo.com/

Following is my experience with the above tools and the inference based on them, which might be totally different from yours and can change from time to time.

The First Experience:
    For one of my website, a standard sitemap was created and was submitted to all of these webmaster tools almost at the same time. To be precise, Sitemap was submitted to Google and Bing on the same day and was submitted to Yahoo few days later.

Result:
    Google indexed the pages first which happened with few days and started showing them in their search results. Bing took slightly more than a week to index them while Yahoo totally ignored them.

The second experience:
    After around 2 months, the site had to be moved to another domain, which means another URL. The same content had to be placed in the new links. For the sake of indexing, the old domain was kept alive with only the updated sitemap (removed old links) and the content was moved to the new website with a sitemap of its own. Again, both the website’s sitemap was submitted to these tools at the same time.

Result:
    Here again, Google found my new website within a week and started showing them as indexed. It took slightly more than a week for Google to remove my old website links from their list. For Bing, even after two months, my old website links are still showing up in results and nothing from my new website is indexed. Yahoo Site Explorer is the simple one here, since nothing from my websites has been indexed in their list until now.

Conclusion:
    May be, there are technicalities involved based on moving the same content among websites OR the dependency of various aspects that controls the indexing process for search engines is too complex to accommodate the above scenario OR the other tools does well in other scenarios. But, whatever that is, for a user, for a specific content, based on the previous and the experiences stated above, it is found Google comes up with result of your sitemap submission first regardless of whether that is positive or negative. For a moment, I thought that we are going to have multiple options for web searches. But, it looks like I will have to stick with Google for updated results.