Javascript

ภาษาไทยกับ Silverlight

หลังจากที่ Silverlight 1.0 ออกมาแล้ว 11 เดือนก็ยังไม่ได้เคยลองเอามาใช้แบบจริงๆจังๆซักที จะมีลองเล่นๆก็คือตอน BarCamp ครั้งนู้น แต่ว่าช่วงนี้ได้งานมางานหนึ่งซึ่งต้องใช้ Silverlight 1.0 ในการพัฒนาเลยได้ลองใช้ของจริงเลย

ปัญหาอย่างหนึ่งที่พบตั้งแต่เมื่อ 11 เดือนก่อนแล้วไม่คิดว่ามันจะแก้ไขได้ง่ายแบบนี้คือเรื่องการแสดงผลภาษาไทย

Flickr ASP.NET MVC app pt.2 - ajaxified

After we have finished the Flickr MVC app last time. This time will be sequel, ajaxified it.

Although the ASP.NET MVC do provide the abstract ajax helper class, only implementation exists publicly is Nikhil's. Certainly, ASP.NET Team will include the ASP.NET AJAX/Microsoft AJAX Library helper in the MVC framework for next CTP bits. As for this tutorial, I will continue with jquery instead of Microsoft AJAX Library because I'm more familiar with it.

The ajaxified instructions is mainly related to the view. In order to use jquery, put the library in ~/Content and add the reference to it in the layout.

<head runat="server">
    <title>My Sample MVC Application</title>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="../../Content/jquery.js"></script>
</head>

Next, Open the ~/Views/Home/Index.aspx. Then, add a placeholder div called "result" in the view. We'll use this div to display the response from the ajax call. Additionally, add a eye-candy loading indicator to let user knows that the page is being loaded.

<%Html.Form("Search", "Home", FormExtensions.FormMethod.post, new { ID = "theform" });%>
    <label for="tags">
        Tags:
    </label>
    <%=Html.TextBox("tags", 30) %>
    <%=Html.SubmitButton("find", "Find", "") %>
    <img src="../../Content/loading.gif" id="spinner" style="display:none;" />
    </form>
<div id="result"></div>

Last but not least, add some lines of script to make an ajax call once the form is goin to be submitted.

 $(document).ready(function() {        
        $('#theform').submit(function (){            
            $.post('/Home/Search', {'tags':$('#tags')[0].value}, completeRequest);
            $('#spinner').show();                        
            $('#result').slideUp(1500);
            return false;            
        });
    });
    
    function completeRequest(r){            
        $('#result').html(r).slideDown(1500);                            
        $('#spinner').hide();        
    }

The script will be invoked when the DOM is ready. It'll hook the form submit event, post the textbox value to ~/Home/Search, make the loading indicator visible, hide the result div and then, cancel the event to prevent the full post process. And then, after the request is completed, completeRequest function will be called. It will replace the div's content with the result from the response and then reveal the div by using slide down effect. And lastly, hide the indicator.

Try the page and Voila! The ajaxified is completed.

Compare to the traditional web form, MVC has a better degree to integrate with the javascript library. Though I use the web form view engine, extension method on the HTML Helper that makes the markup more flexible, no generated id. However, integration with the jquery may not be the easiest one for ASP.NET MVC as ASP.NET Team will deliver its own Ajax helper.

In conclusion, AJAX in ASP.NET MVC has a lot of room for improvement, either officially or unofficially. ASP.NET AJAX becomes useless when using it with ASP.NET MVC. However, using the alternative libraries in MVC require less effort than the traditional way. jQquery and ExtJs are the most notable. Besides, mootools and YUI are also gaining their share. Anyway, Microsoft will push ASP.NET AJAX little ahead those 3rd party library through their Ajax Helper once again.

ASP.NET MVC Ajax

After the long weekend, Scott announced the ASP.NET 3.5 Extension which includes the preview version of long-waited MVC Framework, ASP.NET MVC. Today, there are many websites and blogs regarding ASP.NET MVC. However, just a few of them are talking about AJAX.

In Web form model of ASP.NET, ASP.NET AJAX, along with AJAX Control Toolkit, is the major player for AJAX library. Since ASP.NET AJAX relies on Web form, migrating it to use with ASP.NET MVC which is just a beta bit is not really worth. But in the end, Microsoft will push its AJAX product towards ASP.NET MVC as soon as the latter is ready for production. This can be seen in Nikhil's post about AJAX in ASP.NET MVC. Though Nikhil uses his Script# to create the javascript library, the concept utilizes the behavior/component things which is the concept of ASP.NET AJAX/AJAX Control toolkit. No doubt that ASP.NET AJAX will be the one that shipped with ASP.NET MVC.

As for alternative, jQuery seems to be the winner at the time of writing. Moreover, The latest survey reveals that the most favorite alternative javascript library among ASP.NET developer is jQuery and I don't think ASP.NET MVC will differs from its counterpart. jQuery, in fact , is the fourth but the first two places are in paired, the second actually is not the javascript library so I count jQuery as the most favorite one. However, mootools, prototype/script.aculo.us will gaining their share in MVC as many people will go to ASP.NET for its MVC.

Creating Twitter timeline badge

Recently, I'm getting addicted to Twitter. Since I've moved to my new host, this is a good opportunity to try something new.

Twitter, in fact, does provide a pack of pre-built badges. But they are not my type, 2 flash badges and a html/javascript one. Fortunately, Twitter also provides a set of API over JSON/REST to query almost everything out. After take a look at API, I ended up with an idea to create a new one. I want to display either my friends' or mine in the timeline so I picked 'friend_timeline' method over the 'user_timeline' method because the latter will return only your own tweets. After that, I want the result in JSON therefore I have to ping to http://twitter.com/statuses/friends_timeline/wiennat.json.

Next step is to figure how do I use the json result from twitter. Because of security reason, AJAX call cannot go across the domain. This reason has an impact on me, I can't call to timeline url directly. Then, proxy call came into my head but I hesitated to do it so because I remembered that I found many websites with twitter badges and I was sure they didn't use this technique. After doing some research, I knew the solution, Twitter provides a way to set up a callback by using 'callback' parameter. This reflects a change to target url, http://twitter.com/statuses/friends_timeline/wiennat.json?callback=cbfn (where cbfn is the name of callback function). Instead of only JSON data, using callback parameter causes Twitter to return the JSON data as a parameter of specified function call.

To make it possible in HTML, I wrapped the url in script element and put it at the end of element. I delayed this process by using $(document).ready to wait until DOM is ready before loading the timeline. This prevents the timeline to be loaded while the page still is not loaded completely.

var Twitter = {
_twitter_parent:'',
_tweet_count : 20,
init : function (username, parent, count){
$(document).ready( function() {Twitter.loadTwitter(username); });
Twitter._twitter_parent = parent;
Twitter._tweet_count = count || 20;
}

loadTwitter : function(username){
var ttdata = document.createElement("script")
ttdata.src = 'http://twitter.com/statuses/friends_timeline/'+username+'.json?count='+Twitter._tweet_count + '&callback=Twitter.twcb';
document.body.appendChild(ttdata);
}
.... // still not complete

After append twitter script to the body element, timeline will be loaded and will call the function specified with callback parameter, inthis case Twitter.twcb. Twitter.twcb is a function that processes the returned data and put it in desired element.

twcb : function(ob) {
var twitterpane = $('#' + Twitter._twitter_parent);

ot = '<ul id="'+twitterpane.id+'_inner" class="twpane">';
for (var j=0;j<Twitter._tweet_count ;j++ ) {
at = Twitter.relative_time(ob[j].created_at);
us = ob[j].user.screen_name;
id = ob[j].id;
tx = ob[j].text;
ot += ('<li><span class="twus"><a href="http://twitter.com/' + us + '">'+us+'</a></span>: ' + tx + ' <span class="twdtxt"><a href="http://twitter.com/'+us + '/statuses/'+ id+'">#</a> <small>~'+at+'</small></span></li>');
}
ot += '</ul>';
ot += '<div style="font-size:xx-small;text-align:right">powered by <a href="http://twitter.com">twitter</a></div>';
twitterpane.css('overflow', 'hidden');
twitterpane.css('height',0);
twitterpane.html(ot);
twitterpane.animate({
height: twitterpane[0].scrollHeight
}, 750 );

As for relative time, I copied it out from the twitter badges. Actually, jquery doesn't provide blind effect likes script.aculo.us. To do it so, set the overflow property of desired element to hidden and then animate its dimension to achieve the effect. In this step, I got struck for 4 hrs. because I don't know how to specified target height dynamically. Thank you iPats for his advice on scrollHeight. To run this script, I put the script into external script and initialize the script with this code

<script type="text/javascript" src="/misc/twitterj.js"></script>
<script type="text/javascript">
$(document).ready(function() {
Twitter.init('wiennat', 'itwitterpane', 7); });
</script>
<div id="itwitterpane"> <img src="/images/spinner.gif" />loading... </div>

That's not too hard for me to create such a simple badge like this.

YSlow, why slow?

After Yahoo! Developer Center released their analysing tool, YSlow!, last week. I just have a chace to try it with my blog today. Here is the result.

Let’s see what can I do to make my blog faster.

  1. Make fewer HTTP requests - My blog has 9 external javascript references. Half of them are Google Analytics, BeYello and Google Reader relates. I can’t do anything much for them. The rest are ASP.NET Ajax related scripts. I can use the AjaxControlToolkit and take advantages of ToolkitScriptManager to combine all scripts into one request. Luckily, Subtext Dev team has integrated YUI Compressor into the build script and has already implemented script combiner for next version of Subtext which will be released soon. As for CSS, I have to reimplement my custom skin to take the advantages of new Subtext’s CSS Handler.
  2. Use a CDN - I can’t afford for this thing. Pass.
  3. Add an Expires header - There’re 16 links that don’t have expires header. Since adding the expires header means I must have the permission to access IIS Manager which I don’t. I have nothing to do here. Pass.
  4. Gzip components - Normally, Subtext has an integrated GZip Module. But all of unGzippped components are images and javascripts which don’t pass through ASP.NET Pipeline. Same as HTTP Requests number, I should wait for next release of Subtext that can help me resolve this issue. Pass.
  5. Reduce DNS lookups - Front page of my blog has more than 4 domains. Again, they’re Google Analytics, BeYello, and Google Reader scripts.Nothing to do here either. Pass
  6. Minify JS - JavaScript plays an important part nowsaday. In production environment, every JavaScript libraries should be compressed. Subtext has an uncompressed common script but it has been resolved in the next release. The another is BeYello script, again.
  7. Configure ETags - Same as expires header and GZip components. Pass.

After analysed each part, I can make my score a little higher. While I waiting for next release of Subtext, I can compress my JS and combine my css.

Last but not least, remember that YSlow! suggestions are just suggestion. Sometimes their suggestions are good, but for some conditions. You can ignore them if they’re not suit but you have to know what you are doing. Check the other people advice on YSlow! before take any action.

PS. Beyello, if you can hear me, please compress your javascript to let your clients load your scripts faster and save your precious bandwidth. You service is great and don’t let this little thing spoils it. ;)

f*cking ASP.NET AJAX Animation

ใน ASP.NET AJAX ไม่มีความสามารถด้าน Animation และ Effect เลย ตรงนี้ต้องไปใช้ AJAX Control Toolkit แทน แต่ว่า Animation ที่มีให้ก็เป็นแบบง่ายๆ ไม่ค่อยสวย ใช้ยาก แล้วส่วนใหญ่จะเอาไปประกาศใน Server Side แถมเอามาใช้ผ่าน javascript ก็ลำบาก นั่งเล่นมันตั้งกะบ่ายเมื่อวาน ป่านนี้ยังใช้ไม่ได้เลย โชคดีที่สามารถเอา prototype กับ script.aculo.us มาใช้แทนได้เลย

แต่ขนาดของ prototype + script.aculo.us มันใหญ่นี่สิ จะทำไงดี ก็ได้แต่หวังว่า MS และทีม AJAX Control Toolkit จะยอมเพิ่ม animation กับวิธีการใช้ หรือไม่ก็ทำให้มันใช้ง่ายๆด้วยเท้อออ

Script.aculo.us bug

try to click at any effect demos rapidly. it will get stuck.

http://wiki.script.aculo.us/scriptaculous/show/CombinationEffectsDemo

Technorati tags: , ,