Thursday, January 31, 2013

Wednesday, January 30, 2013

DataTables Fixed Height

I've already confessed that I am a big fan of Twitter Bootstrap and jQuery. In my apps I often deal with tables and grids. In the past I was using the wonderful ExtJS grid. But ExtJS is rather heavy and it does not play well with Bootstrap. So I was looking at alternatives, and there is a nice (and free!) jQuery Plugin for this: DataTables.
While DataTables gives you a lot of flexibility I could not find a nice way of having the table's height fixed. There is a discussion on their forum for this topic but the solution did not work that well for me so I came up with a simpler alternative that seems to work well. The following JS snippet refers to the examples on DataTables website.
$table = $('#example');
$table.dataTable( {
  "sDom": 'tif', 
  "bScrollInfinite": true, 
  "bScrollCollapse": true, 
  "sScrollY": "200px",
  "oLanguage": { 
    "sLengthMenu": "_MENU_ / page",
 "sInfo": "(_START_ to _END_) of _TOTAL_",
 "sSearch": ""
  }
  ,"fnDrawCallback": function() {
        $table.dataTable()._fnScrollDraw();        
        $table.closest(".dataTables_scrollBody").height(200);
   }  
} );
From the snippet above, only the fnDrawCallback is important. It will fix the table's height to 200px as instructed in the scroller configuration. The trick is to let the component do its work and then simply adjust the height of the scroller element.
A better version would not duplicate the height and would reuse the value configured in sScrollY property, but I did not find yet how to access it.

Wednesday, January 23, 2013

Inline editable fields for an HTML table

I am a fan of Twitter's Bootstrap. It is simply fantastic. But you can make it more powerful if you use jQuery plugins and Bootstrap extensions. So here is Bootsnipp - a site that lists cool Bootstrap extensions.
Traditionally on the web, when you want to capture information from the user you have to create a form. This is great, but sometimes building a form is not that natural. Sometimes we want to edit a value in the middle of a text, or edit the value from a table. There are a lot of solutions out there, and this is just one of them using Bootstrap and a neat extension named X-editable.
While the X-editable site shows a lot of examples, I could not find a way to make my table handle more like a form. What this means is that I want to edit the fields in the table without posting the changes and have a "Save" and "Reset" buttons to apply the changes or revert to the original values.
The "Save" button is nicely demo-ed on X-editable site but the reset functionality was not to my liking as the example is not truly reverting the values to their original state, but instead it is setting them to null (which is fine for that example as it deals with creating a new entry).
Then I realized that the library does not save the original value and it is lost. So I plugged in my handlers for save and reset in order to add my desired functionality.The trick is that I save the original value in the element itself on the "save" event and then make sure I clean it up when the processing completes (either successfully or the reset is invoked). My example also extends the original example and looks for next editable item on the rows as well as columns.
// this is to automatically make the next item in the table editable
$('.edit').on('save', function(e, params){
    var that = this;
    // persist the old value in the element to be restored when clicking reset
    var oldItemValue = $(that)[0].innerHTML;
    if (!$(that).attr('oldValue')) {
     $(that).attr('oldValue', oldItemValue);
    }
    setTimeout(function() {
        // first search the row
        var item = $(that).closest('td').next().find('.edit');
        console.log(item);
        if (item.length == 0) {
            // check the next row
            item = $(that).closest('tr').next().find('.edit');
        }
        item.editable('show');
    }, 200);
});
The "Reset" button handler:
$('#resetbtn').click(function() {
    $('.edit').each(function() {
        var o = $(this);
        o.editable('setValue', o.attr('oldValue')) //clear values
         .editable('option', 'pk', o.attr('pk')) //clear pk
         .removeClass('editable-unsaved')
      .removeAttr('oldValue');
    });
});
And the "Save" button handler:
$('#savebtn').click(function() {
   $('.edit').editable('submit', { 
       url: '/post', 
       //ajaxOptions: { dataType: 'json' },           
       success: function(data, config) {
           $(this).removeClass('editable-unsaved') //remove unsaved class
               .removeAttr('oldValue'); // clear oldValue
       },
       error: function(errors) {
           console.log('error');
           var msg = '';
           if(errors && errors.responseText) { //ajax error, errors = xhr object
               msg = errors.responseText;
           } else { //validation error (client-side or server-side)
               $.each(errors, function(k, v) { msg += k+": "+v+"
"; });
           } 
       }
   });
});
You can find the code and a demo here.

Tuesday, January 15, 2013

Play Framework 2.0.3 to 2.1 RC2 upgrade

If you were expecting that upgrading your Play project from 2.0.x to 2.1 will be a simple replacement of the play libraries you will be disappointed. But don't worry, as it is not that bad. Here is a mini guide for the upgrade.

  1. Download Play Framework 2.1RC2.
  2. Edit [yourApp]/project/plugins.sbt file and set SBT version to "2.1-RC2"
  3. Edit [yourApp]/project/build.properties file and set SBT version to “0.12.2-RC2”
  4. The [yourApp]/project/Build.scala file needs to be updated to remove a warning about “using a deprecated version of Play's SBT Project”. To do this you will need to: 
    1. Replace “import PlayProject._with “import play.Project._
    2. Update appDependencies object value and make sure the sequence contains "javaCore, javaJdbc, javaEbean".
      Example:
      val appDependencies = Seq(javaCore, javaJdbc, javaEbean)
    3. Replace
      val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA)” 
      with
      val main = play.Project(appName, appVersion, appDependencies)
  5. 1.       It is recommended to run “play clean-all” before compiling anything. This will ensure a cleanup of sbt.
  6. A change in the API that will likely impact every application out there is in how you access the form. Every reference to Controller.form() will error as that is no longer available. Instead you should change your code to use play.data.Form.form().
  7. Launch the play console and try and compile the application. You might get new warnings regarding your routes. They are just warnings but you should have a look at them.
  8. If your code compiles and you are using Eclipse as your IDE of choice you should re-eclipsify your project as Play 2.1 will have a different classpath and a different set of libraries. Note that the old "eclipsify" command is no longer available as it was replaced by "eclipse" command.
If you are wondering about differences regarding classpath, tasks, commands between 2.0.3 and 2.1 RCs you can have a look here.

Friday, January 11, 2013

Thread Deadlock

Instead of long articles, here is a picture that describes the thread deadlock nice and clearly:
Can't get simpler than that!