Home >

Customize AsyncFileUpload (MS ajax control toolkit ), cross browser too

19. February 2011

(Note: live demo is here and source code can be downloaded at the end of this post)

Ajax control toolkit is a Microsoft open source project. The latest version is released at April 12th 2010, the source code and binary can be downloaded from Microsoft open source site: codeplex.

There is a very useful control called “AsyncFileUpload” according to asp.net demo,

AsyncFileUpload is an ASP.NET AJAX Control that allows you asynchronously upload files to server. The file uploading results can be checked both in the server and client sides.

You can save the uploaded file by calling the SaveAs() method in a handler for the server UploadedComplete event.

The official demo is very promising, see it here.

However, It’s hard to customize the look and feel of this control thus it’s hard to bind it into your own project without sacrifice some of your UI design.

I successfully customized it through two approaches. You can seem my live demo here

The basic idea is to mask the real control by making it invisible but clickable. On bottom (not on top) of it, put an image or a button. So the users think they are clicking the button or image, actually the invisible real control gets clicked.

The idea leads me to two approaches.

(1) Approach 1 is quick and easy but not that flexible:

   1: <asp:Panel ID="PnlFsAttch" runat="server" style="position:relative; overflow:Hidden; width:80px; height:20px; cursor:pointer;"> 
   2:             <ajaxToolkit:AsyncFileUpload
   3:                 runat="server" ID="AfuFsAttch" Width="100px" UploaderStyle="Traditional" 
   4:                 OnClientUploadComplete = "AfuUploadComplete"
   5:                 OnUploadedComplete = "AfuAttch_UploadedComplete"
   6:                 UploadingBackColor="Black" ThrobberID="LblUplProg01"
   7:                 style="position:absolute; left:-20px; z-index:2; opacity:0; filter:alpha(opacity=0);" />
   8:                 
   9:                 <asp:Button ID="BtnFsAttch" BackColor="YellowGreen" ForeColor="Blue"  runat="server" Text="Upload file" Font-Size="x-Small" Width="80px" style="position:absolute; top:0px; left:0px; z-index:1; font-style:italic"   />    
  10:         </asp:Panel>

As you can see, the regular “BtnFsAttch” is masking the AsyncFileUpload control “AfuFsAttch”. AfuFsAttch’s z-index is 2, BtnFsAttch z-index is 1, so AfuFsAttch is on top of the normal button, but I also force AfuFsAttch to be totally transparent, this makes the user only see the normal button but not real control.

 

filup_approach1

I carefully size the AfuFsAttch and BtnFsAttch so they can mask each other very closely, no offset or gap between the two controls. Whenever user clicks, the real control gets clicked without exception.

Why this is not that flexible? Given that AfuFsAttch is hard to adjust its height, imagine you prefer a big huge image as the uploader button.

By using this approach,  there will be a gap or offset between AfuFsAttch and the masking image button. The user can click the gap between the real control and image, and nothing would happen in that case and your user will be very frustrated.

Conclusion: approach 1 is only very good for small uploader buttons.

(2) Approach 2 is much more flexible but need a little bit more coding

The idea is simple: you can’t easily change the size of AsyncFileUpload, but you can move it. That’s it. Move the AsyncFileUpload inside of your masking image by following user mouse.

filup_approach2

 

I put a text box on top to show the real time mouse X/Y positions when it’s inside the image. There is a piece of javascript to move the internal AsyncFileUpload control while the mouse moving.

Here is the javascript:

   1: function AfuTrackMouse(event) {
   2:      //var ctrl = document.getElementById('<%=AfuFsAttch.ClientID %>').getElementsByTagName('input').item(1);
   3:      var ctrl = document.getElementById('<%=AfuFsAttch.ClientID %>');
   4:      var ctrlContainer = document.getElementById('<%=PnlFsAttch.ClientID %>');
   5:  
   6:      var x;
   7:      var y;
   8:  
   9:      var cx;
  10:      var cy;
  11:  
  12:      x = event.clientX;
  13:      y = event.clientY;
  14:  
  15:      cx = getPos(ctrlContainer).cx;
  16:      cy = getPos(ctrlContainer).cy;
  17:  
  18:  
  19:      document.getElementById('X-coord').innerHTML = x + 'px';
  20:      document.getElementById('Y-coord').innerHTML = y + 'px';
  21:  
  22:      document.getElementById('cx').innerHTML = cx + 'px';
  23:      document.getElementById('cy').innerHTML = cy + 'px';
  24:  
  25:      
  26:      ctrl.style.left =  x - 40 + 'px';
  27:      ctrl.style.top =  y - cy - 5 + 'px';
  28:  
  29:  }
  30:  
  31:  function getPos(el) {
  32:      for (var lx = 0, ly = 0; el != null; lx += el.offsetLeft, ly += el.offsetTop, el = el.offsetParent); return { cx: lx, cy: ly }; 
  33:   } 

If you really want to see how the inside control moving, you can make it 50% transparent instead of 100%.

   1: <ajaxToolkit:AsyncFileUpload
   2:               runat="server" ID="AfuFsAttch" Width="80px" UploaderStyle="Traditional" 
   3:               OnClientUploadComplete = "AfuUploadComplete"
   4:               OnUploadedComplete = "AfuAttch_UploadedComplete"
   5:               UploadingBackColor="Black" ThrobberID="LblUplProg01"
   6:               style="position:absolute; z-index:2; opacity:0; filter:alpha(opacity=0);" />

To make it 50% transparent, just change opacity:0 to opacity:50

(3) What you need to be aware of

I didn’t find a good way to gracefully catch the the over size uploading issue. I tried global.asax application error catching, tried AsyncFileUpload built-in error catching. It seems global.asax can catch the specific error, but can not throw it gracefully. So I end up using warning UI and <httpRuntime maxRequestLength="500"/> from web.config. It’s not perfect but works for all major browsers.

Another thing to be aware of: The solution also works under latest IE9 RC, but you have to run it under IE8 compatible mode.

================

Let’s wrap this up. The two approaches can customize the AsyncFileUpload control gracefully. They are tested on all three major browsers: IE8/Firefox 3.6/Chrome 9.

My live demo is coded under .NET 4.0 + VS 2010, but I do have VS2005 + .NET 3.5 source code available for you to download and test.

Source code download here:

FileUploaderAjax40.zip (1.06 mb)(need VS 2010 + .NET 4.0 environment)

FileUploaderAjax35.zip (1.05 mb)(need VS 2005 + .NET 3.5 environment)

Comments are closed