Saturday, November 10, 2012

Hello world with nodejs and script#

I have used S# at work before to write client side javascript. It really shines when you have a lot of javascript files/modules in your application. You get all the benefit of leveraging C# oops paradigm, managing dependencies among various modules in javascript as well as benefiting from all the tools Visual studio has to offers.

Recently, I was playing with nodejs in one of my project and wanted to see if I can build a simple Hello World nodejs application with S#. Even though the public version of S# extension for Visual Studio does not support NodeJs out of the box, the functionality already exists as part of S# github repository. So to get started, I need the latest bits from S# github repository. To do so, 


1. Clone the repository


git clone https://github.com/nikhilk/scriptsharp.git

2. Once its cloned, go to scriptsharp/src folder and open ScriptSharp.sln solution. Now build the solution with both debug and release setting.

3. Once done, go back to scriptsharp root folder. At this point, you should see a bin folder containing following folders.




4. At the time of writing, this should corresponds to 0.8 version of S#. Simply double click on ScriptSharp extension and install it. As a best practice, I always keep a copy of the whole folder under my external libraries folder and add a README file to note the time stamp when I build this library.


5. Once the extension is installed, create a new project in visual studio and select nodejs application as follows:





6. You project should now contain a single class (Class1.cs) which essentially creates a program that listens to all the http requests on your localhost at port 1337 and spits "Hello Node.js World, from Script#!" in response.

7. To run this program, simply build it, It will output <yourappname>.js file in bin folder. Navigate to the either bin/debug or bin/release (depending on how you build your app) folder in your command prompt and simply run 


node <youappname>.js

Now navigate to http://127.0.0.1:1337/ and you can see your Hello World program in action.


NOTE: For some reason port 1337 did not work for me. When I ran node command from command line , I got:



events.js:71
        throw arguments[1]; // Unhandled 'error' event
                       ^
Error: listen EACCES
    at errnoException (net.js:769:11)
    at Server._listen2 (net.js:892:19)
    at listen (net.js:936:10)
    at Server.listen (net.js:993:9)
    at dns.js:71:18
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)

To get rid of this error, I simply changed the port to 1338 and it started working for me. I am not sure why it is throwing that error. My guess is I have some other service running on that port.


As I mentioned before, though the power of S# might not seem obvious with this Hello world example, but I am sure that as you app logic grows, you will appreciate the power of S#.

Wednesday, March 14, 2012

How to fix the commenting system on internet

I personally think that the current commenting system on internet is suboptimal as also mentioned recently by Nick from Gawker Media. I believe that they are considered second class citizen on page even though many times they provide much more useful data and reveal more issues around the whole topic. I definitely think there is an opportunity to rethink the whole commenting system. Here are my some initial thoughts -

Do you know how in Microsoft Word you can attach comments with a particular section of the document ? I personally think that those sort of comments tends to be more concise and useful. In my last project, everybody was encouraged to review any doc offline and add comments. During the review, they would only go through comments. It went very well and the meetings were very productive. Another similar example - remember back when we were in school, how our teachers used to grade our exams ? They would add their remarks next to a particular answer or part of the answer which required attention. My point is attaching comments with a section feels much more natural , much more human. I think we need to have a way such that comments are attached to certain section of the article. My hypothesis is that such a mechanism would encourage more constructive criticism of an article which would in turn increase the quality of the article. Note that the section necessary does not have to be text - it could be part of an image or at some point in time for a video ( I am sure you must have seen - go to 12:15 in the video for blah.)

I also think the placement of the article on the page is not optimal. Currently comments are placed at the bottom of the page - for most part (This also sort of reflects that they are second class citizen). When a new user comes to the article, he/she only engages with the comments after they went through the whole article even though comments sometime contains a lot of facts, figures and/or alternative thoughts. However, I think the comments should be read as part of the article. While you are in the middle of an article, all the applicable comments should have equal chance to be read at the same time for that section. This keeps the current context in perspective and would empower user to better make his/her opinion about the whole article. This would make comments more engaging and useful. Furthermore, this would also help to increase the quality of the new comments.

I understand that all the comments are not useful. Once a comment is shown, how do you determine which one is most useful to the current section ? Let the user decide which one is better. Let them vote and then bubble them up to the top. If you buy my previous hypothesis that attaching comments to a section is useful - now imagine how the whole system would work. Reader reading an article and get to read the most useful comment at the same time. To add up - imagine there is one global commenting system and you carry your reputation across the sites on internet.

Thursday, February 03, 2011

For .... with innerhtml

I want to talk about a very simple fact about DOM manipulation using javascript. This is not specific to mobile but is applicable to all the browser in general.

On a higher level, I want to append three child elements (div) to a div container. I also want to hold a reference in javascript as I want to add/manipulate their content. My javascript was as follows:
var domContainer = new Array();
var n = 3;
var p = document.getElementById("parent");
for(var i=0;i<n;i++)
{
var cntId = "cnt"+i;
p.innerHTML += "<div id='"+cntId+"'></div>";
domContainer[i] = document.getElementById(cntId);
}

Essentially, I first got hold of the parent container and then changed the inner html of the container to add a child. As soon as I append the child, I get the hold of the child element and store it in the array. To manipulate the content of a child element with index i, I did
domContainer[i].innerHTML = "dummy content";

To my surprise, for all child container with index < n-1 (in this case for i=0 and 1), browser never displayed the dummy content. It also never fired any javascript error. Interesting, isn't it ? What is happening is here when we are changing the innerHTML of the parent container, it is destroying all the existing child elements of the container and recreating them again along with appending the new child element. From browser perspective, this is what is happening:

for i=0, it is creating a child element to parent container with id as cnt0;
for i=1, it is destroying the existing child element with id cnt0 and then creating two child elements with id cnt0 and cnt1.
for i=2, it is destroying the existing child elements with id cnt0 and cnt1 and then creating three child elements with id cnt0, cnt1 and cnt2.

Note that the browser just destory those elements from UX but do not remove it from browser memory as javascript is still holding a reference to those dom objects (in domContainer array). Therefore, by the end of the loop all the values in array for index 0 to n-2 refers to a DOM element which is still in browser memory but are no longer displayed to the user. Since child elements are not re-created after the end of the loop, therefore the element at index n-1 is the same as the one that is currently being displayed. This explains the behavior I was observing. So how did I fixed this ?
for(var i=0;i<n;i++)
{
var cntId = "cnt"+i;
var cnt = document.createElement("div");
cnt.setAttribute("id", cntId);
p.appendChild(cnt);

domContainer[i] = document.getElementById(cntId);
}

Monday, January 31, 2011

Why real time feed does not make sense for a news service

I am a news savy or I try to be one. I would like to know about the topic as soon as possible. Recently, people started talking about real time feed. And when they say that, they essentially means Twitter feed. They are real time feed because people are tweeting about it somewhere out in real world. In contrast, a search result on web is not considered real time as those are indexed by a web spider at some point of time. That means, ideally real time feed is the best place for me to check about the latest topic. Ok, that make sense. I go to twitter and look at the trending topics. But that just tells me about the topic but not what about it. Sure, I can then look through what people are talking about it. But most of the time, a tweet in itself does not make sense. Sometime people emote about the item. Sometime people talk in twitter code language that I can't understand. After spending some more time, I might be able to understand what the heck is going on. That's OK way to know about something. Let's see the alternative. I take a trending topic and I do a Google/Bing news search. I tried this for some of the trending topic. For most part, I got some very recently published article about it. In this manner, I get all the information at one place and I do not need to compose a story from multiple tweets.

This brings me back to where I started this article. Where should I go to get the recent news? Why would I ever want to start with real feeds at first place ? A news aggregator/indexer service such as google/bing anyways surface those articles quickly. So why would I ever bother about real time feed ?

Saturday, January 29, 2011

Cross domain requests - how it is not scalable for Mobile Web

Many times, you might want to download data from a service hosted on a different or a sub domain. The usual approach is you add a script tag in your DOM with src tag set to the request url. The request url in turn returns javascript that calls a javascript function on your client passing the data as an argument to that function.

However, this technique is not scalable for all mobile web browsers. I know for sure that this technique fails on HTC Incredible. I will tell you why in a moment. But to verify my claim, I went ahead and looked at Google mobile site. Google Mobile usually hosts its autosuggest service on a different domain (for many reasons - less load on their main production server, increasing maximum number of parallel connections etc.). Look at the server to which the browser makes request for an iPhone and HTC Incredible UA:





As you can see, Google clearly differentiates between these two phones in the way it make request for autosuggest, for iphone case - it uses cross domain request and for HTC incredible, it uses ajax to download the suggestions. What essentially happens in case of HTC incredible is browser gets in old state. If you keep making requests using the same script tag or creating new script tags or each request, the browser does not evaluate the script response from the server immediately. But if you give some sort of poke to browser (by either touching the screen or by invoking alert etc), it will invoke all the pending functions call immediately.

I wonder on how many other phones this behavior happens. I hope not a lot.

If you wonder how I produced these waterfall chats, by ofcourse faking the UA from my firefox browser. But may be in future, I can use steve souders bookmarklet to produce waterfall directly on mobile devices.

Tuesday, January 18, 2011

Mobile browser market share in US

This graph indicates mobile browser share of total mobile internet traffic in US market in past 12 months. Datasource: StatCounter



Trend is clear. More and more mobile traffic is coming from non-iOS devices. On an average over the year, this is how the share looks like

Blackberry: 29.57%
iPhone: 26.83%
Android: 18.02%
iPod: 13.88%

Note that the above will not total to 100% as I omitted share for other browsers such as Opera etc as these 4 constituted the top 90% traffic source. Note that all the 4 devices have a webkit browser with HTML 5 capabilities (Blackberry announced it last year). This is good news as HTML 5 features would help to a create a user experience which would feel like native app.

Write once and run everywhere ;)

EDIT: I just found out that Google recently released the relative number of active devices running a given version of the Android platform.

Friday, January 14, 2011

Mobilism - 12th & 13th of May, 2011: Amsterdam

I recently came to know about Mobilism, the first conference that exclusively focus on web design and development on mobile devices. I am happy to see that mobile web development is getting more and more traction. Few days back, Steve souders, the famous author of High Performance Website and Even faster web sites, also announced that his research wings will now focus on finding bottlenecks and building tools for mobile websites.

With so many different mobile platforms becoming popular,I believe that the only way to deliver a kick ass experience without creating a big engineering effort is build the experience in html(5) and deliver it through web.

Go Mobile !

Sunday, January 09, 2011

Enter keyboard event with animation on Samsung sch-i400

In this post, I am going to talk about a very surprising animation bug on Samsung SCH-i400 running on Android 2.1 OS and what I had to do to overcome the problem.

The other day, I was trying to perform some animation when the input field gets focus . Let me be specific. I have a text input field and when it gets focus, I want to move the input field towards the left as shown in figure. After the animation is complete, I want to run some validation logic once the user submits the form.


<style>
.normal{margin-left: 50px;}
.animate{margin-left: 0px;-webkit-transition: all 0.3s ease-out; }
</style>

<div id="sb" class="normal">
<form>
<input id="q" name="q" type="text" value="flowers" onfocus="OnFocusEventHandler(event);"/>
</form>
</div>

function OnFocusEventHandler(e)
{
var ele = $("sb");
ele.className = "animate";
}


OnFocusEventHandler changed the css class of the input field container which essentially performed the animation. This worked so far. As I mentioned in one of my previous blog post, I hooked up the validation logic to keydown event of the input field. But to my surprise, when the user tapped on "return" key on the keyboard, the keydown event handler never got fired ! Browser also didn't fire submit event on the form.

To debug the problem, I tried animating the input field by clicking on a button, putting focus on input field manually by tapping on it and then submitting the form by hitting the "return" key. This time everything worked fine - keydown event handler got called and the validation logic ran just fine. I also tried attaching the animation logic to mousedown / touchend events of the field but met with no success. With some more experimentation, I found that if I move the input element as soon as it gets focus (and at the same time browser brings up the virtual keyboard), the keyboard events are not properly attached to the input field.

Then I tried the obvious thing - I waited for sometime after onfocus event to begin the animation by using Window.setTimeout. And that did the trick. I set the delay of 500 ms (100, 200 ms etc didn't solve the problem) before I started the animation. Essentially I had to wait for the keyboard to become visible completely before I can start the animation.

function OnFocusEventHandler(e)
{
window.setTimeout(function()
{
var ele = $("sb");
ele.className = "animate";
}, 500);
}


I was hoping that a very simple thing like this would just work out of the box. But it didn't. Sad Web Developer :(.

Backspace event on input fields

As a part of my job, I had to write code which would do something when the user hits the backspace on an input field (type=text). At first glance, this looked like a piece of cake. I listened to keydown event of input field and invoked the logic when the event keycode is 8 (browser sets the keycode of the event to 8 on backspace).

function OnKeyDownEventHandler(e)
{
if(e===null) e=window.event;
if(e!= null && typeof e != 'undefined')
{
if(e.keyCode===8)
{
// That means user tapped on backspace
// Run your logic here
}
}
}

This logic ran smoothly on all the different versions of iOS (iPhone and iPod). But this logic would fail on iphone 3 and lower devices when the value of the input field is empty. In that case, for some reason, browser would fire event with keycode as 127 and that too multiple times ! So, I had to make sure that I would listen for event with keycode of 127 and also had to make sure that I invoke my logic only once by maintaining a boolean flag. Also note that some android devices, for example, Samsung Focus (Android 2.1 and I think on 2.2 also) would not fire any event when the value of the input field is empty and user hits backspace. There were some other android devices which had the similar.

In short, you would expect simple things like this would work on atleast webkit browsers on mobile devices but sadly it does not. Make sure you know which devices you are going to support for your application and test your logic on those devices ( running on different versions of OS too, my experience tells me that Android 2.2 is well behaved than Android 2.1) and test your application with extensive test cases.

Saturday, January 08, 2011

Html form validation on a webkit mobile browser

In this post, I am going to talk about how can we run validation logic on form fields on mobile webkit browser and stop it from being submitted if the validation fails and submit it if the validation passes. It is well known that if the browser/ or your javascript code has invoked the submit event on the form, it is too late to run the validation logic i.e. you can never stop the browser to submit the form if the validation logic fails. Even if you try to set the return value of the event to false or if you try to stop default action from submit event handler. I always use the following method to kill an event

 // e: Event
function stopEvent(e)
{
if(e===null) e = window.event;
if(e!=null && typeof e != 'undefined')
{
e.cancelBubble = true;
e.returnValue = false;
if (e.stopPropagation) {e.stopPropagation();};
if (e.preventDefault) {e.preventDefault();};
}
}

On mobile devices, user would submit a form by hitting "Go" or "Search" button on iPhone or "return" button on Android unless you have your own submit button on the page. When the user hits the button, browser would fire the submit event on the form and if you call stopEvent method from your form submit event handler, the browser would still submit the form. So in order to solve the problem, we need to get hold of an event that browser fires before it fires submit event on the form. If we can find such an event, then we can run the validation logic in that event handler and stop bubbling of the event if the validation logic fails. In that case, submit event would never be triggered on the form and we will achieve our goal.

In my case, I have an input field (type=text) and for discussion purpose, I just want to make sure that the value in input field is not empty. The way I solved this problem is by running the validation logic in keydown event handler of the field. When the user taps on "Go" or "return" button on the phone, browser sets the event keycode to 13. So assuming OnKeyDownEventHandler is your event handler for keydown event, you can do the following:

function OnKeyDownEventHandler(e)
{
if(e===null)e=window.event;
if(e!=null && typeof e != 'undefined')
{
var keycode = e.keyCode;
if(keycode===13)
{
// IsValid runs the validation logic
if(!IsValid())
stopEvent(e);
}
}
}

Note that on iPhone 3 (not sure below iphone 3), browser sets the keycode to 10 instead of 13. So you to make this logic work on iphone 3 and above, you need to run the logic when the keycode is also 10.

function OnKeyDownEventHandler(e)
{
if(e===null)e=window.event;
if(e!=null && typeof e != 'undefined')
{
var keycode = e.keyCode;
if(keycode===13 || keycode===10)
{
// IsValid runs the validation logic
if(!IsValid())
stopEvent(e);
}
}
}

Some might argue that other browsers might fire keycode 10 for a different key and this would break the logic. True. But practically I have never came across such a situation. If you want, you can do device sniffing by getting the UA and running the logic for keycode = 10 only if the device is iphone with version 3.