9/30/2009
I have been doing some ASP.NET MVC experiments lately, and one of the major features missing in the framework is a nice API to page, so here is what I came up with. What do you think? Not bad for a UI guy huh ?
using System.Data.SqlClient;
using System.Data;
using System;
using System.Configuration;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Configuration;
using System.Collections;
namespace FNG
{
//returns DS (dataset)
public class ReturnDs
{
public string dbConnectionString;
public DataSet populate(string strSQL)
{
SqlCommand dbcomm;
SqlDataAdapter DA = new SqlDataAdapter();
DataSet DS = new DataSet();
using (SqlConnection connection = new SqlConnection(dbConnectionString))
{
dbcomm = new SqlCommand(strSQL, connection);
DA.SelectCommand = dbcomm;
DA.Fill(DS);
return DS;
}
}
}
//paged class
public class Paged
{
public string dbConnectionString;
public string sql;
public string currentPage;
public int itemsPerPage;
public string strPreviousText;
public string strNextText;
public string pageNumberPrefix = "";
//templage
public string templateHeader;
public string templateFooter;
public string template;
public string template2;
private int intNumberofItems;
private DataSet ds = new DataSet();
//gets records HTML
public string GetHtml()
{
int perPage = itemsPerPage;
string p = currentPage;
StringBuilder sb = new StringBuilder();
ReturnDs DataAdapter = new ReturnDs();
DataAdapter.dbConnectionString = dbConnectionString;
ds = DataAdapter.populate(sql);
int RowCount;
RowCount = ds.Tables[0].Rows.Count;
//sets shared number of rows
intNumberofItems = RowCount;
//gets girst page if nothing
if (String.IsNullOrEmpty(p))
{
p = "1";
}
int i;
int start;
int end;
int page = int.Parse(p);
int lastPage = (RowCount / perPage);
//set max possble page number
if (RowCount <= lastPage)
{
end = RowCount - 1;
}
if (page != 1)
{
start = ((page - 1) * perPage);
end = (start + perPage) - 1;
}
else
{
start = 0;
end = perPage - 1;
}
sb.Append(templateHeader);
ArrayList fieldPlaceHolder = new ArrayList();
Regex r = new Regex(@"{(.*?)}", RegexOptions.IgnoreCase);
Match m = r.Match(template);
while (m.Success)
{
for (int i3 = 1; i3 <= 2; i3++)
{
Group g = m.Groups[i3];
CaptureCollection cc = g.Captures;
for (int j = 0; j < cc.Count; j++)
{
Capture c = cc[j];
fieldPlaceHolder.Add(c);
//sb.Append("Capture" + j + "='" + c + "', Position=" + c.Index);
}
}
m = m.NextMatch();
}
for (i = start; i <= end; i++)
{
//make sure index does not run over
if (i <= (RowCount - 1))
{
//append table
//generates alternating grows
if (i % 2 == 0)
{
//checks if alt template was set
if(String.IsNullOrEmpty(template2))
{
sb.Append(template);
}
else
{
sb.Append(template2);
}
}
else
{
sb.Append(template);
}
//runs replace for the object placehodlers
for (int i2 = 0; i2 < fieldPlaceHolder.Count; i2++)
{
sb.Replace("{" + fieldPlaceHolder[i2].ToString() + "}", ds.Tables[0].Rows[i][fieldPlaceHolder[i2].ToString()].ToString());
}
}
}
sb.Append(templateFooter);
return sb.ToString();
}
//gets pagin links
public string PagingLinks()
{
StringBuilder sb = new StringBuilder();
if (String.IsNullOrEmpty(currentPage))
{
currentPage = "1";
}
int intCurrentPage = int.Parse(currentPage);
int intPerPage = itemsPerPage;
string strPageFileName = pageNumberPrefix; //adds prefix before the paging (useful for ajax by adding '#')
if (intCurrentPage < 1)
{
intCurrentPage = 1;
}
var number_of_pages = (intNumberofItems / intPerPage);
int i = 0;
//hide paging if only one page
if (number_of_pages >= 1)
{
sb.Append("<div id='paging' class='clearfix'>");
//previous record
if (!(intCurrentPage == 1))
{
sb.Append(" <a href='" + strPageFileName.ToString() + (intCurrentPage - 1).ToString() + "' class='p'>« " + strPreviousText + "</a>");
}
if (number_of_pages < 20)
{
// if there are less than 20 record no paging breaking
//numbers
for (i = 0; i <= number_of_pages; i++)
{
if (!(i == intCurrentPage - 1))
{
sb.Append(" <a href='" + strPageFileName + (i + 1) + "'> " + (i + 1) + " </a>");
}
else
{
sb.Append("<span>" + (i + 1) + " </span>");
}
}
}
else
{
if (intCurrentPage <= 10)
{
//numbers
for (i = 0; i <= 10; i++)
{
if (!(i == intCurrentPage - 1))
{
sb.Append(" <a href='" + strPageFileName + (i + 1) + "'> " + (i + 1) + " </a>");
}
else
{
sb.Append("<span>" + (i + 1) + " </span>");
}
}
sb.Append("<span class='pg_dots'>...</span>");
//numbers
for (i = number_of_pages - 2; i <= number_of_pages; i++)
{
if (!(i == intCurrentPage - 1))
{
sb.Append(" <a href='" + strPageFileName + (i + 1) + "'> " + (i + 1) + " </a>");
}
else
{
sb.Append("<span>" + (i + 1) + " </span>");
}
}
}
else if (intCurrentPage >= number_of_pages - 8)
{
//last 10 numbers scenerio
//numbers
for (i = 0; i <= 3; i++)
{
if (!(i == intCurrentPage - 1))
{
sb.Append(" <a href='" + strPageFileName + (i + 1) + "'> " + (i + 1) + " </a>");
}
else
{
sb.Append("<span>" + (i + 1) + " </span>");
}
}
sb.Append("<span class='pg_dots'>...</span>");
//numbers
for (i = number_of_pages - 10; i <= number_of_pages; i++)
{
if (!(i == intCurrentPage - 1))
{
sb.Append(" <a href='" + strPageFileName + (i + 1) + "'> " + (i + 1) + " </a>");
}
else
{
sb.Append("<span>" + (i + 1) + " </span>");
}
}
}
else
{
//numbers
for (i = 0; i <= 3; i++)
{
if (!(i == intCurrentPage - 1))
{
sb.Append(" <a href='" + strPageFileName + (i + 1) + "'> " + (i + 1) + " </a>");
}
else
{
sb.Append("<span>" + (i + 1) + " </span>");
}
}
sb.Append("<span class='pg_dots'>...</span>");
//numbers
for (i = intCurrentPage - 5; i <= intCurrentPage + 3; i++)
{
if (!(i == intCurrentPage - 1))
{
sb.Append(" <a href='" + strPageFileName + (i + 1) + "'> " + (i + 1) + " </a>");
}
else
{
sb.Append("<span>" + (i + 1) + " </span>");
}
}
sb.Append("<span class='pg_dots'>...</span>");
//numbers
for (i = number_of_pages - 3; i <= number_of_pages; i++)
{
if (!(i == intCurrentPage - 1))
{
sb.Append(" <a href='" + strPageFileName + (i + 1) + "'> " + (i + 1) + " </a>");
}
else
{
sb.Append("<span>" + (i + 1) + " </span>");
}
}
}
}
//next record
if (!(intCurrentPage == number_of_pages + 1))
{
sb.Append(" <a href='" + strPageFileName + (intCurrentPage + 1) + "' class='n'>" + strNextText + " »</a>");
}
sb.Append("</div><!-- end of 'paging' -->");
//builds string
return sb.ToString();
}
else
{
return "";
}
}
}
}
Now, here is how you can use this class:
public ActionResult Paging(string p)
{
Paged pg = new Paged();
pg.dbConnectionString = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["dataConnectionString"].ConnectionString;
pg.sql = "SELECT TOP 500 * FROM guests";
pg.currentPage = p;
pg.itemsPerPage = 6;
pg.strNextText = "Next";
pg.strPreviousText = "Prev";
//pg.pageNumberPrefix = "";
pg.templateHeader = "<table class=\"data_table2\" style=\"width:100%\"><tr><th>id</th><th>name</th><th>email</th></tr>";
pg.template = "<tr><td>{id}</td><td>{name}</td><td>{email}</td></tr>";
pg.template2 = "<tr class='alt'><td>{id}</td><td>{name}</td><td>{email}</td></tr>";
pg.templateFooter = "</table>";
ViewData["message"] = pg.GetHtml() + pg.PagingLinks();
return View();
}
8/11/2009
As I am constantly working on my JS framework I have been thinking what JS OO pattern is most suitable to use for creating my “classes/objects” Looking around everybody has their own preference when it comes to creating JavaScript objects. In this article, I would like to do a simple comparison of the three popular ways objects can be created, and go over some of the pro and cons of using each of the methods.
First, lets look at Object Literal. Here is simple example of Object literal:
//literal
//////////////////////////////
var person_literal = {
name : "literal",
sayMyName : function(){
alert(this.name);
}
}
//we can create shortcuts: however no instance
var lit = person_literal;
//this modifies the global varilable
lit.name = "dave mod lit";
console.log(lit);
As I say in the comments, the main disadvantage of this pattern is that you cannot create instances, however, this may be a desired feature, when you create a “static public class” type of framework. Douglas Crockford also mentions (in his book JavaScript: the Good Parts”) that there are some performance implications.
Next is the Constructor:
//constructor
//////////////////////////////
var person_constructor = function(){
this.name = "constructor";
this.sayMyName = function(){
alert(this.name);
}
};
//we CANNOT access the constructor directly
console.log(person_constructor);
//this would only return the function
//but we can create instances
var con = new person_constructor();
con.name = "some constructor property";
console.log(con);
var con2 = new person_constructor();
con2.name = "another constructor property";
console.log(con2);
This method is popular with backend developers, since it mimics the “classical” approach to programming. So what are the pro and cons? Well, whenever you want to use it, you have to make and instance, which might be an issue in large apps, and if you have a framework that does not require different “version” of the object each time you use it, this may be an overkill.
Lastly comes Douglas Crockford’s Module Pattern
//module
//////////////////////////////
var person_module = function(){
return {
name : "module",
sayMyName : function(){
alert(this.name);
}
}
}();
//we can access the object directly
console.log(person_module);
//or we can create instances and modify the object on the fly
var mod = person_module;
mod.name = "some name";
console.log(mod);
var mod2 = person_module;
mod2.name = "another name";
console.log(mod2);
Apart from other advantages such as closure/information hiding which can be accomplished in the other patterns also, the module pattern in fact lets you take advantage of the features of both of the previous ones: you can access it directly like the object literal, and you can still create copies “instances” and augment them.
8/10/2009
In recent weeks, I decided to rewamp my code base framework, that I use to build all my new sites, and started from scratch using ASP.NET MVC. Only in a few days I felt in love with this MVC! This is all I dreamed about that .NET would have. In fact I have been already hacking .NET to behave this way for some quite time, and now, there is a native support for a clean fast flexible UI.
The more my love for ASP.NET MVC grew, to more I started to worry that this emotional dating was going to turn out to be too young and immature for a serious relationship. Yes I was afraid that I will not find suitable hosting solution for it. Reading the forums that overflow with frustrations that ASP.NET MVC is hard to deploy even increased my worries. Finally I ran cross Phil's blog post about ASP.NET MVC deployment, and tried this on one of my free accounts. As Phil advices, I used the Visual Studio 2008 publisher, set up the FTP login and oala... the site is up and running. As Phil points out, all VS needs to do is include the non-present MVC dlls in the bin folder, and everything runs perfectly.
After all those years of frustrations from standard breaking user controls, ASP.NET made a great leap ahead. Now we have a very clean and simple UI with the richness of the .NET middle tear, all running on a $5/month hosting plan. What else to wish for?
UPDATE: Yes I got the MVC site working on the GoDaddy, shared hosting plan, however, every few hours, it would totaly back out giving 500 erros. I spend a few days trying to figure out what is wrong with my code, finally I called GoDaddy support, and after the issue got escalated, I got a email: "We do not support .NET MVC, use a different tool for hosting your website"... just like that, really this broke my heart... I almost got emotianl about this framework, how much I liked it, and now the most advertised hosting company on the internet does not even want to deal with it.
7/6/2009
Lately, I have been interviewing many developers for a new JavaScript position, that we have opened at my company, so I would like to post some of my favorite questions for others to benefit, when preparing for an interview.
Q: What is the difference between the three following scenarios:
var myFunction = function(){
var person;
person;
window.person;
} A: The first is local variable, the last two are global.
Q: How do you create an object in JavaScript?
A:
var person = new Object; or var person = {}; Q: How to you assign a value to an object?
A:
person["name"] = "dave"; or person.name = "dave";
Q: What is the difference between object and constructor in JavaScript?
A: Constructor works like a class, and before using, we need to create an instance. Object can be accessed directly: no instance creation.
Q: How do you create a local and global method in a constructor?
A:
var myClass = function(){
var PrivatMethod = function(){
}
this.PublicMethod = function(){
}
}Q: Have you heard of Douglas Crockford?
A: Yes he is the "inventor" of JSON.
Q: How do you inherit from one object to another?
var Object1 = {someProp : "some value", someOtherProperty : "some other Value"};
var Object2 = {someProp2 : "some value", someOtherProperty2 : "some other Value"};
Object1.prototype = new Object2;
//now we can alert
alert(Object1.someProp2);
Q: What debugging tools do you use?
A: Firebug in Firefox (console.log(); method) and Visual Studio in IE ('debug' command inserted in javascript file)
Finally, here is some reading list:
http://oreilly.com/catalog/9780596000486/
http://oreilly.com/catalog/9780596517748/
Also, watch the JavaScript videos at:
http://developer.yahoo.com/yui/theater/
You should also understand:
jQuery pluging authoring:
http://www.learningjquery.com/2007/10/a-plugin-development-pattern
Module pattern:
http://www.yuiblog.com/blog/2007/06/12/module-pattern/
Object Oriented JavaScript:
https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript
Firebug console:
http://getfirebug.com/console.html
7/2/2009
There is a difference between object literal and what is called a "constructor" in JavaScript. For some reason a lot of people think that these two are interchangeable, but they are a totally different thing.
Here is an example:
var objLit = {
someProperty : "some value",
someMethod : function(){
console.log(this. someProperty)
}
}
This is most people refer to as object literal in JavaScript. It is an object that can be a accessed right away, with all its nodes, so when you want to call a method, it works like this:
objLit.someMethod();
On the other side you have a simple constructor, which might look like this:
var myConst = function(){
this.someOtherProperty = "some value";
this.someOtherMethod = function(){
console.log(this.someOtherProperty);
}
}
Obviously, if you want to call the inner method directly, it will not work, because it is not an object yet.
myConst. someOtherMethod();
First you have to create an "instance of a class:"
var myInst = new myConst();
Now you you have your public methods play with the public methods:
myInst. someOtherMethod();
Now there are more differences in implementing these two patterns. With a constructor, if you want to create a copy, you create a new instance:
var myInst = new myConst();
With an object literal, you can just simply make a copy of the object.
var newLitInstance = objLit;
And with this copy, you can do most of the things you would do with an instance, except inheritance. Yes, the prototype property does not work the way you are used to, so the following will not work:
objLit.prototype = new myConst();
Anyway, these things might be pretty simple, but I found that many people confuse these two quite a lot, so hopefully this clerification email will help to bring some light in the foggy waters JavaScript wold.