Sep 30

Duplication is the mother of all evil in programming. Remaining DRY at all costs should be your goal at all times. A pattern repeats itself one time and your code complexity goes up exponentially.
One great way to DRY up your code is via Traits. Traits are functional equivalent of base classes where you can collect most often used functions and inject these Traits into your objects. Here’s one simple way to do it in Javascript (using extjs here):

MyTrait = {
   xhr: function(config) { return Ext.Ajax.request(config) },
   submit: function(basic_form,config) {
                //perform some checks on config 
               // and call basic_form.submit 
   },
   //...add more utility functions
}
function MyGrid(config) {MyGrid.superclass.constructor.call(this,config)}
Ext.extend(MyGrid, Ext.grid.GridPanel, MyTrait);
Tagged with:
Sep 28

Although the extjs grid is an awesome component, IMO, it suffers from one major drawback – it’s inability to place active components within data cells. At least it’s not straightforward. Here’s a simple solution to place clickable links within cells. The trick is to place s which look like links and then intercept rowclick and determine which of many links was clicked on.

Here’s an example of a custom Grid Component:

function MyComponent() {
   MyComponent.superclass.constructor.call(this);
}
Ext.extend(MyComponent, Ext.grid.GridPanel);
MyComponent.prototype.initComponent = function() {
  var action_tmpl = new Ext.XTemplate(
     "<span class='link' id='edit-{id}'>Edit</span>",
     "<span class='link' id='delete-{id}'>Delete</span>"
   );
   action_tmpl.compile();
   var content = {
     // grid related config
     columns: [
        {header: 'First Name', dataIndex:'fname'},
        {header: 'Action', dataIndex:'id', 
          renderer: function(c) { 
              return action_tmpl.applyTemplate({id: id});
          }}
     ]
   }
   MyComponent.superclass.initComponent.call(Ext.apply(this,content));
}
MyComponent.prototype.afterRender = function() {
  MyComponent.superclass.afterRender.call(this);
  this.on('rowclick', this.row_click, this);
}
 
MyComponent.prototype.row_click=function(grid, ri, evt) {
   var rec = grid.getStore().getAt(ri);
   // See Below for within_el method
   if(evt.within_el('edit-'+r.id)) {
       alert('Edit clicked');
   } else if(evt.within_el('delete-'+r.id)) {
        alert('Delete clicked');
   }
}

The within_el method on Ext.EventObject object looks like this:

Ext.apply(Ext.EventObject, {
    within_el:function(el) {
        el = Ext.get(el);
        if(!el)
            return false;
        var evt_xy = this.getXY();
        var evt_x = evt_xy[0];
        var evt_y = evt_xy[1];
        return (evt_x > el.getLeft() && evt_x < el.getRight() && evt_y > el.getTop() && evt_y < el.getBottom());
    }
});
Tagged with:
Jun 26

Rhtml in Ruby, Template Toolkit in Perl, Python’s Django templates, Java’s JSP or Freemarker, and ASP .Net files. All have the same philosophy – render HTML with data streamed from the corresponding web framework ‘controller’ modules.

It’s a great concept – lets you refactor View Templates and come up with ugly looking prototypes quickly. I say ugly since most enterprise programmers tend to have little or no web design skills. Learning effective UI Design is not trivial and asking your programmers to come up with slick UI is a lost cause.

Then you hire Graphic Designers and UI Developers. And your slick RHTML model starts to break horribly.  Web Designers’ tools such as DreamWeaver etc do not understand the server side Templating languages or they understand parts of it. The Web Developer has absolutely no interest in learning the weird syntax And it’s MUCH harder to design and test web pages in Dreamweaver with pages refactored in mutliple files!

When faced with the stalemate, we went back to basics. Separation of concerns!! Divide and Rule. Let two teams work with their favorite tools and we’ll connect the bridge with good old JSON transport. No need to do server side templating, rendering and refactoring. The backend developers had no need to mess around with HTML, CSS, Gifs and PNGs!

So, here’s our setup which keeps everyone happy. For now.

The only connection between Developers( including  Javascript developers) and designers is via <div> IDs. Once those container blocks are placed in HTML pages, the Programmer renders the UI widgets and takes care of AJAX communication with back end.

The Web Designers can continue using Dreamweaver and it’s associated parameterized templates to manage refactoring.

Going pure JSON also means, we can do away with massive rendering Engines in Rails, Merb or other frameworks and work with much simpler Data Delivery Engines which are REST compliant and serve pure JSON. We’ll talk about building such an Engine using Rack in a separate post.

Tagged with:
Jun 17

Keeping in philosophy of KISS, nginx is an awesome, simple web server. It does few things and does it extremely well.
It doesn’t do CGI but does proxy’ing and that makes it extremely useful as a front end web server. I recently had to implement an extjs based progress bar for large file uploads with nginx acting as a front end to a Rack/mongrel based application. Here are the steps for ubuntu.

Do not install nginx from the repo. Uninstall if it’s already installed.

apt-get remove nginx
mkdir -p /opt/downloads
cd /opt/downloads

Download nginx sources from nginx.net and unpack (I’m working with nginx-0.6.36):

tar zxf nginx-0.6.36.tar.gz

Download an untar upload progress module from nginx wiki

tar zxf Nginx_uploadprogress_module-0.5.tar.gz
cd nginx-0.6.36
./configure --prefix=/opt/nginx --add-module=/opt/downloads/nginx_uploadprogress_module
make install

This’ll install nginx in /opt/nginx

Configuration

open up /opt/nginx/conf/nginx.conf and add following lines:

http {
     client_max_body_size 30M; # adjust as per your need
     upload_progress proxied 1m;
 
     server {
         server_name my.server.com;
         listen 80;
         root /var/www/nginx-default/my-static-files;
 
         location /ajax {
             proxy_pass http://localhost:2300;
             proxy_redirect default;
             track_uploads proxied 30s;
         }
         location ^~ /report_file_uploads {
              report_uploads proxied;
         }
     }
}

This assumes  ‘/ajax’ is the backend application proxy.

In Javascript, to get progress bar going, send following AJAX message in a loop, after the form with file upload field has been submitted.

Lots of details are omitted since these are dependent upon your javascript library of choice (which, btw, for us is extjs).

var upload_id = 'MyUniqueID'; // upload_id must be unique for each upload session
this.send_ajax_message({
       url: '/report_file_uploads',
       headers: {'X-Progress-ID' : upload_id},
       method:'GET',
       success: function(r) {
              r = this.parse_ajax_response(r);
             if(r.state == 'uploading' || r.state == 'starting') {
                var percent = (Number(r.received)/Number(r.size));
                if(percent &gt; 1.0)
                    percent = 1.0;
                 //show percent as you wish on your progress meter
                 // sleep for few seconds and send this ajax message again
             } else if(r.state == 'done' || r.state == 'error') {
                // kill your loop timer
                // finish your progress meter
             }
        }
});

Let me know if you’d like javascript fragment for extjs and I’ll post it but it’s relatively straightforward.

At Yellowfish, we specialize in web2.0 Ajax web application development using open source tools and modern software trends.

Tagged with:
preload preload preload