3/5/2010
I have been doing some “stealth” development of a new version f my ASP.NET CMS. This time, I started from scratch with a totally new approach. The CMS now runs on ASP.NET 3.5 on the MVC framework, the DB access layer is all linq and the part I am really proud is that the admin is a 100% AJAX app: (page only load once, and all the loading, and posting happens in ajax). I was also able to extract all the UI into MVC views, so that the UI developer has full control over the templating. Finally, I added an “installer” much like the one Wordpress , has so the installation of the CMS is very straight forward: 1 copy code to FTP, 2. Create the DB, 3, change the connection string, 4. Run the installer.
Now I wish I had the number of templates Wordpress has, and this ASP.NET CMS could be an equal competitor. But it’s actually not that hard to port Wordpress templates to my CMS, so maybe this will not be an issue.
Here is a couple showcase sites that I have put up: one about modern glass coffee tables, and the other about my new hobby: flying RC helicopters.
I am still doing some final tweaks before I release the code to the public, but if anybody is interested to see the current version, shoot me an email and I will send the ASP.NET MVC CMS code.
1/28/2010
It looks like nobody has written a jQuery plugin Savings calculator for compound interest, so here is one.
This time I really did my best to showcase the best jQuery plugin authoring best practices: all possible options are exposed, including HTML templates. The plugin even has an option to return pure data object, which lets you create your own markup from scratch.
In Particular, I have fallen in love with the two small utility functions here: StringBuilder, "sub string templator" which merges object and string in the MVC manner.
(function($) {
//util framework
var lib = {
StringBuilder: function() {
var s = [];
return {
append: function(v) {
if (v) {
s.push(v);
}
},
clear: function() {
s.length = 1;
},
toString: function() {
return s.join("");
}
}
},
template: function(m, v) {
v = v.replace(/\{[^\}]*\}/g, function(key) {
return m[key.slice(1, -1)] || '';
});
return v;
},
formatNumber: function(n) {
return Number(n).toFixed(2);
}
}
//calculator results in string
var buildTable = function(data, _op) {
var sb = lib.StringBuilder();
//header template
sb.append(_op.template.header);
for (var i = 0, l = data.length; i < l; i++) {
//alt row swhitch
if (i % 2) {
//repeat
sb.append(lib.template(data[i], _op.template.repeat));
}
else {
//repeat alt row
sb.append(lib.template(data[i], _op.template.repeatAlt));
}
}
//footer template
sb.append(_op.template.footer);
return sb.toString();
}
//creates summary object
var summaryData = function(data, _op) {
var amountInvested = (data.length * _op.monthlyAmount) + _op.initialDepost;
var totalAmount = data[data.length - 1].currentAmount;
return {
totalAmount: totalAmount,
totalAmountInvested: amountInvested,
earnedInterest: lib.formatNumber(totalAmount - amountInvested)
}
}
//calculator ouput data
var dataCalc = function(obj) {
var _data = [];
//some pre-calcs
var mRate = (obj.interestRate / 100) / 12;
var numberOfMonths = obj.numberOfYears * 12;
//Get a decimal
var currentAmount = 0.1 - 0.1;
var currentContributions = 0.1 - 0.1;
var currentInterest = 0.1 - 0.1;
currentAmount += obj.initialDepost; //initial depost
currentContributions += obj.initialDepost;
//amort table loop
var currentMonth = 0;
while (currentMonth < numberOfMonths) {
currentMonth++;
var interest = Number(currentAmount) * Number(mRate);
currentInterest = Number(currentInterest) + Number(interest);
currentContributions = Number(currentContributions) + obj.monthlyAmount;
currentAmount = Number(currentAmount) + Number(interest) + obj.monthlyAmount;
//gets table in row format
_data[currentMonth - 1] = {
currentContributions: lib.formatNumber(currentContributions),
currentInterest: lib.formatNumber(currentInterest),
currentAmount: lib.formatNumber(currentAmount),
currentMonth: currentMonth
};
}
//final bild out:
return _data;
}
// plugin definition
$.fn.savingsCalculator = function(op) {
// build main options before element iteration
var _op = $.extend({}, $.fn.savingsCalculator.defaults, op);
// iterate and reformat each matched element
return this.each(function() {
var T = $(this); //selected element
var o = $.meta ? $.extend({}, _op, $this.data()) : _op; // build element specific options
//final insert
//gets data in object
var _data = dataCalc(_op);
//builds HTML table
var _tableHtml = buildTable(_data, _op);
//summary HTML
var _summaryHtml = lib.template(summaryData(_data, _op), _op.template.summary);
T.html(_summaryHtml + _tableHtml);
});
};
//gets row data
$.savingsCalculatorData = function(op) {
// build main options before element iteration
var _op = $.extend({}, $.fn.savingsCalculator.defaults, op);
var _data = dataCalc(_op);
return {
table: _data,
summary: summaryData(_data, _op)
};
}
//defaults
$.fn.savingsCalculator.defaults = {
initialDepost: 0,
interestRate: 5,
numberOfYears: 1,
monthlyAmount: 100,
template: {
summary: "<p>Total amount at the end of the term: {totalAmount}<br />Total amount invested: {totalAmountInvested}<br />Interest earned: {earnedInterest}</p>",
header: "<table class=\"data_table\"><tr><th>Month</th><th>Contributions</th><th>Interest</th><th>Total</th></tr>",
repeat: "<tr><td>{currentMonth}</td><td>{currentContributions}</td><td>{currentInterest}</td><td>{currentAmount}</td></tr>",
repeatAlt: "<tr class=\"alt\"><td>{currentMonth}</td><td>{currentContributions}</td><td>{currentInterest}</td><td>{currentAmount}</td></tr>",
footer: "</table>"
}
};
})(jQuery); And here is how you use it:
$("#calc").savingsCalculator({
initialDepost: 1000,
interestRate: 5,
numberOfYears: 1,
monthlyAmount: 100
}); Or you can just get the data object like this:
console.log($.savingsCalculatorData());
1/26/2010
It looks like I have invested myself in the right technology, since developing AJAX applications is growing a very hot field. I have done some searches in google on this keyword, and there is not much comprehensive material on this topic, so decided to contribute some of my experiences from developing AJAX apps.
First, let's define what I mean when I refer to AJAX app: Ajax Application, is a web page, that only loads once for the session of its use, and other interaction, rendering happens behind the scene via AJAX calls.
The main objective when architecting AJAX apps is to design a framework that will be easy to work with, perform well, and highly scalable: can be used to develop something to the level of google documents for example.
The main challenge in this pursuit becomes catering to very un-level filed of used browser create interesting challenges. This is well understood by those who have developed cross-browser XHTML/CSS, less by those who have been writing server-side business logic for a specific platform. To sum it up, the browser have many performance limitations, when developing business logic in JavaScript, and the common denominator becomes quite small.
Currently, there are many JavaScript frameworks available, however some are more suited for developing "FULL" AJAX applications, than others.
Design proposition:
1. Ajax application should initially only load JavaScript code which is shared by all future code: since we want to have a framework that can scale, we don't want our code base grow with our business logic.
2. For simplification and mainstreaming purposes, all AJAX calls should use a single protocol JSON wrapper.
3. Javascript will be always separated from the presentation layer, adding interaction through the DOM selectors.
4. If possible, there should be a one to one relation between user action, and AJAX request: user action (click) should not result into 5 ajax calls.
5. Creating presentation markup (HTML) should be limited in the UI: creating table views from JSON in the UI for example can be quite costly on several fronts: growing our code base, and computation cost.
This is all for the intro... in the next post I will start with examples.
1/26/2010
This is another cool way to create a namespace wrapper that I have seen today. Kind of reminds the of the module patter.
var NameSpace = (typeof (NameSpace) === "object") ? NameSpace : (function() {
var b = {
method1: function() {
},
method2: function() {
}
}
return b
})();
12/30/2009
It took me some time to compile the features of the Object Oriented language such as C# into one JavaScript Template bundle. Here is what I came up with. This code template supports the following features:
Class block cope
NameSpace importing (“using” in C#) and dependancy checking on load
Privat string
Public string method
Privat void
Public Class (can have instances)
BaseClass / SubClass inheritance
//base class closure
(function($){
//Createst Namespace Object
if (!window.MyNamespace) {
window.MyNamespace = {}
};
//Createst local shortuct
var m = window.MyNamespace;
m.baseClass = {
baseClassMethod : function(var1, var2){
return var1 + var2;
}
};
})(jQuery); //importing JavaScript framework
//sub class closure
(function($, baseClass){
//Createst Namespace Object
if (!window.MyNamespace) {
window.MyNamespace = {}
};
var privatSettign = {
set1 : "test",
set2 : "test"
};
var privatString = function(){
return privatSettign.set1;
}
var privatVoid = function(){
}();
//class definition
window.MyNamespace.myClass = {};
//Createst local shortuct
var m = window.MyNamespace.myClass
//enherit from base class
$.extend(m, baseClass);
//adding methods:
m.publicStringMethod1 = function(){
//use pirvat class like this
var a = privatString();
return a;
}
m.publicStringMethod2 = function(){
//use public same object class like this
this.publicStringMethod1();
var localVar;
var anotherPrivatVoid = function(){
localVar = privatSettign.set1 + " " + privatSettign.set2;
}();
//call base class method:
var added = this.baseClassMethod("resut is: ", localVar);
return added;
}
m.publicInstanceMethod = function(){
var privatVar;
//call another method
privatVar = this.publicStringMethod2()
return {
getVar : function(){
privatVar;
},
setVar : function(_var){
privatVar = _var;
},
alertVar : function(_var){
alert(privatVar);
}
};
}
})(jQuery, MyNamespace.baseClass); //importing JavaScript framework and class dependancy
//class usage:
(function($, myClass){
//now sub class is available directly so we can call it
var someVar = myClass.publicStringMethod1;
//creating instnaces
var inst = myClass.publicInstanceMethod();
//baseClass method:
var baseVar = myClass.baseClassMethod(1, 2);
//alert original
inst.alertVar();
//lets now set some var
inst.setVar("some var" + baseVar);
//do something with the var
inst.alertVar();
})(jQuery, MyNamespace.myClass); //importing JavaScript framework and class dependancy