Friday, October 29, 2010

Retrieving checkboxes values using JQuery...

I have an html like this in my page
    ...
    <div id="container1">
        <input type="checkbox" value="1" /> a
        <input type="checkbox" value="2" /> b
        <input type="checkbox" value="3" /> c
        <input type="checkbox" value="4" /> d
        <input type="checkbox" value="5" /> e
        <input type="checkbox" value="6" /> f
    </div>

    <div id="container2">
        <input type="checkbox" value="11" /> a1
        <input type="checkbox" value="12" /> b1
        <input type="checkbox" value="13" /> c1
        <input type="checkbox" value="14" /> d1
        <input type="checkbox" value="15" /> e1
        <input type="checkbox" value="16" /> f1
    </div>
    <input id="mybutton" type="button" value="click me" />
    ...

Demo

container1
a b c d e f

container2
a1 b1 c1 d1 e1 f1

result


Now what I want is, whenever I click the button I want to retrieve all the values from the checked checkboxes. This is pretty easy in JQuery. Here's how my JS will look like
    ...
    $("#mybutton").click( function() {
        var myarray = [];
        
        $('input:checkbox:checked').each( function() {
            myarray.push($(this).val());
        });
        
        alert(myarray.join(', '));
    } );
    ...
What if I want it only from the first <div>? I just need to pass context to the selector
    ...
    $("#mybutton").click( function() {
        var myarray = [];
        
        // passing container1 as context to selector
        $('input:checkbox:checked', '#container1').each( function() {
            myarray.push($(this).val());
        });
        
        alert(myarray.join(', '));
    } );
    ...
JQuery makes my life a lot easier :).

Tuesday, October 26, 2010

The beauty of JQuery...

Query by element tag name
    $("div")
Query by element id
    $("#myid")
Query by css class name
    $(".css-whatever")
Query by input type
    $("input:checkbox")
Query by a set of element ids
    $("#myid1,#myid2,#myid3")
Query by input type but exclude the one with 'whatever' id
    $("input:checkbox:not(#whatever)")

Monday, October 18, 2010

Creating DBHelper that can support various types of database...

Yes I know there's a framework (EF, NH and whatever name that I've never heard before) that can solve the problem. Unfortunately, EF only works on new technologies (at least with .NET framework 3.5). What if we're stucked with an old Microsoft technologies (NH is another option, but I still couldn't figure out on how and where to begin with - ~ I ain't a .NET superstar ~)? Is it possible to do it then? Yes!!! back to basic stuff!!!

I've try it on .NET framework 2.0. IDBConnection, IDBTransaction and IDBDataParameter are available in System.Data namespace since .NET framework 1.1 however, DBDataReader in System.Data.Common was available not until .NET framework 2.0 (DBDataReader was derived by SqlDataReader, OracleDataReader and OleDbDataReader). Those are the important interfaces and class needed.

Basically we need to create an abstract layer to our db helper. Let's just call it IDBHelper. Define all basic methods that can support various databases. It's important not to have a method that is specific to any data provider such as ExecuteXmlReader.
    ...
using System.Data;
using System.Data.Common;

public interface IDbHelper
{
IDbConnection CreateConnectionInstance(string connectionString);

...

DbDataReader ExecuteReader(IDbConnection connection, string query, CommandType cmdType, params IDbDataParameter[] commandParameters);

...

IDbDataParameter CreateParam(string paramName, object paramValue);
}
For concrete implementation. Create a class that implement IDBHelper interface. I named the class as SqlClientHelper.
    ...
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.Common;

public class SqlClientHelper : IDbHelper
{
public IDbConnection CreateConnectionInstance(string connectionString)
{
return new SqlConnection(connectionString);
}

...

public DbDataReader ExecuteReader(IDbConnection connection, string query, CommandType cmdType, params IDbDataParameter[] commandParameters)
{
...
}

...

public IDbDataParameter CreateParam(string paramName, object paramValue)
{
SqlParameter param = new SqlParameter(paramName, paramValue);
...
}

...
}
Then, the code for OracleClientHelper.
    ...
using System;
using System.Data;
using System.Data.OracleClient;
using System.Data.Common;

public class OracleClientHelper : IDbHelper
{
public IDbConnection CreateConnectionInstance(string connectionString)
{
return new OracleConnection(connectionString);
}

...

public DbDataReader ExecuteReader(IDbConnection connection, string query, CommandType cmdType, params IDbDataParameter[] commandParameters)
{
...
}

...

public IDbDataParameter CreateParam(string paramName, object paramValue)
{
OracleParameter param = new OracleParameter(paramName, paramValue);
...
}

...
}
Noticed that the instantiation of connection and parameter object has been done in the class itself. Ideally, if we don't use any specific data provider namespaces in DAL layer, it should be flexible enough to use any database without the need to change the code logic. The concern is more on the abstract layer method signature.

Create an object factory that'll return the helper instance. This is the only place that we need to change if the project owner aka our client suddenly decided to use different data provider in future (reality is cruel).
    ...
public static class SomeObjectFactory
{
public static IDBHelper GetHelperInstance()
{
return new SqlClientHelper();

// uncomment the code below for oracle client
// return new OracleClientHelper();
}
}
The code at DAL
    ...
using (IDbConnection connection = SomeObjectFactory.GetHelperInstance().CreateConnectionInstance(connectionString))
{
connection.Open();

string query = "SELECT * FROM tblSomething WHERE Id = @Id";
IDbDataParameter param = MyObjectFactory.GetDBHelperInstance().CreateParam("@Id", id);

DBDataReader reader = SomeObjectFactory.GetHelperInstance().ExecuteReader(connection, query, CommandType.Text, param);

...
}
...
This way, adding System.Data and System.Data.Common namespace should be sufficient enough to our DAL.

Thursday, October 14, 2010

Creating custom event in JavaScript...

First, define custom event.
    var CustomEvent = function() {
//name of the event
this.eventName = arguments[0];
var mEventName = this.eventName;

//function to call on event fire
var eventAction = null;

//subscribe a function to the event
this.subscribe = function(fn)
{
eventAction = fn;
};

//fire the event
this.fire = function(sender, eventArgs)
{
if(eventAction != null)
{
eventAction(sender, eventArgs);
}
else
{
alert('There was no function subscribed to the ' + mEventName + ' event!');
}
};
};
Then create an event handler.
    var myEvent = new CustomEvent("helloworld event");
myEvent.subscribe(event_triggered);

function event_triggered(sender, eventArgs)
{
alert("hello world");
}
Now, the triggering part.
    ...
if(typeof(myEvent) != "undefined")
{
myEvent.fire(null, {
message: 'you just witnessed the firing of a custom event called ' + this.eventName + '!'
});
}
...