4/27/2009
I know this sounds like an ad tag line, but I will share some valuable information, how to save money in these hard times.
Owning an old house turned out to be a perpetual remodeling process that seems to never end. New paint, new windows, new roof, new deck, new AC unit… and the worst thing, these things do not come cheap. I still cannot swallow, how somebody with no college education can charge a higher hourly rate than who spend most of his life in books and staring at computer screen.
Oh well… but I usually do not part with a paycheck for contractor services that easy. “Service exchange” has become especially effective method how to get a WIN WIN deal… the last one was, when I needed a new heater for my house. Finally, through recommendation found a friend of a friend who has HVAC. Well in the initial negotiations, the friend of a friend relationship did not really cut me a deal… but when I said the magic sentence: “Do you guys need a website?” the negotiation tool a new direction: website for a new heater/AC unit.
This was really a pet project, I got to make some improvements to my ASP.NET CMS and was able to help with SEO and copy writing (I suck at copy writing) but there was no one else to do this… Anyway, here is the “website for the heater”.
4/14/2009
I have been working on an interesting projects last few days involving JavaScript popups, so here is some code.
The objective was to create class that would manage popups initiation, and refreshing child popups them from the parent window.
In order to refresh a popup from a parent window, the child popup needs to be given a unique ID, which is then used to control the child popup window.
First let's crate our own namespace:
var DP = (typeof DP == "object") ? DP : {};Next, here comes the popup class:
DP.popups = function(){
var ch = []; //popup id array
this.opp = {}; //options object
this.openNewWindow = function(url, id) {
//assings an ID to the popup
if(!id){
ch[ch.length] = window.open(url, '', objToString(_opp));
console.log("opened " + ch.length);
}
else{
ch[id] = window.open(url, '', objToString(_opp));
console.log("opened: " + id + " | " + objToString(_opp));
}
}
var objToString = function(o){
var re = "";
for(var i in o){
if(o[i]){
re = i + "=" + o[i] + "," + re;
}
}
return re;
}
this.refreshChildWindows = function(id) {
//checks which popups to reload
if(!id){
//refreshes all
for (var loop=0; loop<ch.length; loop++){
if(ch[loop]){
if(ch[loop].closed == false){ //checks if window was closed
ch[loop].location.reload(true);
}
}
}
}
else if(typeof id == "object"){
//refreshes by array
for (var loop=0; loop<id.length; loop++){
if(ch[id[loop]]){
if(id[loop].closed == false){ //checks if window was closed
ch[id[loop]].location.reload(true);
}
}
}
}
else{
//refreshes by id
//decides if id is sting or integer
if(typeof id == "number"){
if(ch[id-1]){
if(ch[id-1].closed == false){ //checks if window was closed
ch[id-1].location.reload(true);
}
}
}
else{
if(ch[id]){
if(ch[id].closed == false){ //checks if window was closed
ch[id].location.reload(true);
}
}
}
}
}
} Now let's create an instance of our class with some window options:
var p = new DP.popups();
p.opp.width = "500";
p.opp.height = "500";
var p2 = new DP.popups();
p2.opp.width = "400";
p2.opp.height = "200";
Finally, here comes HTML for our popups:
<input type="button" value="Open new" onclick="p.openNewWindow('popup.aspx')" />
<input type="button" value="Open David" onclick="p2.openNewWindow('popup.aspx', 'david')" />
<hr />
refresh:
<input type="button" value="1" onclick="p.refreshChildWindows(1)"/>
<input type="button" value="2" onclick="p.refreshChildWindows(2)"/>
<input type="button" value="3" onclick="p.refreshChildWindows(3)"/>
<input type="button" value="some" onclick="p.refreshChildWindows([0, 2, 'david'])"/>
<input type="button" value="all ints" onclick="p.refreshChildWindows()"/>
<input type="button" value="refresh david" onclick="p2.refreshChildWindows('david')"/>
3/23/2009
I know there are many similar plug-ins already written, but I was not able to find something that would give me the flexibility I needed, so here is another approach to do client side JavaScript validation using jQuery.
Ok, so lets start, First we need to define our own namespace. For the lack of creativity, let’s just call it DP.
//creates MRX namespace
var DP = (typeof DP == "object") ? DP : {};
Next, we will write our validation class. Notice that I am using private and public methods, to differentiate which methods are to be exposed and should be hidden from the outside.
DP.validateForm = function(){
//generic check value method
var fromReset = function(elmId, wrongValue, messageText){
//reset
$(".from_wrp input").css({"border":"1px solid #ACA69F"});
$(".from_wrp select").css({"border":"1px solid #ACA69F"});
$("#error_messages").empty("");
}
//generic check value method
var valueCheck = function(elmId, wrongValue, messageText){
if($("#" + elmId).val() == wrongValue){
createAlert(elmId, messageText);
}
}
//alert method
var createAlert = function(elmId, messageText){
$("#" + elmId).css({"border":"1px solid #f00"});
//alert(messageText);
$("#error_messages").append("" + messageText + ", ");
}
//zip validation
var isZip = function(s){
var reZip = new RegExp(/(^\d{5}$)|(^\d{5}-\d{4}$)/);
if (!reZip.test(s)) {
return false;
}
return true;
}
//checks if value is integer
var isInt = function(n){
var reInt = new RegExp(/^-?\d+$/);
if (!reInt.test(n)) {
return false;
}
return true;
}
//public method checks fieds
//requires 'valSetting' setting object
this.runCheck = function(){
//reseet form
fromReset();
//run checks
for (i=0;i<this.valSetting.fileds.length;i++){
if(this.valSetting.fileds[i].type == "zip"){
//zip check
if(isZip($("#" + this.valSetting.fileds[i].id).val()) == false){
createAlert(this.valSetting.fileds[i].id, this.valSetting.fileds[i].msg);
}
}
else if (this.valSetting.fileds[i].type == "number"){
//checks for number
if(isInt($("#" + this.valSetting.fileds[i].id).val()) == false){
createAlert(this.valSetting.fileds[i].id, this.valSetting.fileds[i].msg);
}
}
else{
//checks for value
valueCheck(this.valSetting.fileds[i].id, this.valSetting.fileds[i].val, this.valSetting.fileds[i].msg);
}
}
}
}
In this example, we can validate against specific value. In addition, we have options to validate a zip code or an email format. These special methods could be extended with other regular expression validates. This was by the way one of the form validation features, I that I was missing with already written jQuery plug-ins.
Finally, lets look what will the implementation look like. Let’s take a simple form that we need to validate. Each flied that we will validate, we will give an ID, and on the bottom, using inline JavaScript, we will create an instance of a our validation class, and create a settings objects.
<form id="form" class="popup_from_wrp">
<label>First Name:</label>
<input id="first_name" />
<label>Last Name:</label>
<input id="last_name" />
<label>Address line:</label>
<input id="order_address" />
<label>City:</label>
<input id="order_city" />
<label>Choose a State</label>
<select id="order_state">
<option>NY</option>
<option></option>
</select>
<label>Enter Zipcode</label>
<input id="order_zip" />
<label>Email address:</label>
<input />
<span id="error_messages"></span>
<script type="text/javascript">
//creates instance of the validation class
var vl = new DP.validateForm();
//passes validation settings
vl.valSetting = {fileds : [
{id : "first_name", val : 0, msg : "First Name", type : ""},
{id : "last_name", val : 0, msg : "Last Name", type : ""},
{id : "order_address", val : 0, msg : "Address", type : ""},
{id : "order_city", val : 0, msg : "City", type : ""},
{id : "order_state", val : 0, msg : "State", type : ""},
{id : "order_zip", val : 0, msg : "State", type : "zip"}
}]
};
</script>
<a href="#" onclick="vl.runCheck();">submit</a>
</form>
2/3/2009
Image resizing is a common challenge when building web applications which I have realized when building the next version of my ASP.NET CMS. In this tutorial, I will show how to do elegant ASP.NET image resizing combined with URL rewriting in order to create flicker-like image processing API.
First step we need to create a script that resizes an image on the fly. In this case I choose to work with three different image sizes, for the simplicity of the matter.
Public originalimg, thumb As System.Drawing.Image
Public FileName As String
Public inp As New IntPtr()
Public width, height, tmpheight As Integer
Public rootpath As String
Public strSize As String
Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs)
Dim strF As String = Request.QueryString("f")
If strF.Contains("_") Then
Dim arr(3)
arr = Split(strF, "_")
Select Case arr(1).ToString
Case Is = "s"
strSize = "130"
Case Is = "m"
strSize = "350"
Case Is = "l"
strSize = "715"
Case Else
strSize = "350"
End Select
FileName = Server.MapPath("~/img/") + arr(0).ToString + ".jpg"
Else
strSize = "350"
FileName = Server.MapPath("~/img/") + strF + ".jpg"
End If
Try
originalimg = originalimg.FromFile(FileName)
ResizeImage()
Catch ex As Exception
Try
originalimg = originalimg.FromFile(Server.MapPath("~/img/") + "default-user.jpg")
ResizeImage()
Catch exx As Exception
createTextImage(exx.ToString, 200, 200, 9, 4, 4)
End Try
End Try
End Sub
Function GetEncoder(ByVal mimeType As String) As ImageCodecInfo
Dim codecs() As ImageCodecInfo = ImageCodecInfo.GetImageEncoders()
For Each codec As ImageCodecInfo In codecs
If codec.MimeType = mimeType Then
Return codec
End If
Next
End Function
Function Ettienne_Thumbnail(ByVal Source_Img As System.Drawing.Image,
ByVal height As Integer, ByVal width As Integer) As System.Drawing.Image
Dim Dest_Img As System.Drawing.Image
Dim inp As New IntPtr()
Dim Orginal_Width As Integer
Dim Orginal_Height As Integer
Dim Aspect_ratio As Integer
Orginal_Width = Source_Img.Width
Orginal_Height = Source_Img.Height
Dim thumbnail As System.Drawing.Image = New Bitmap(width, height)
Dim objGraphics As System.Drawing.Graphics
objGraphics = System.Drawing.Graphics.FromImage(thumbnail)
objGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic
objGraphics.SmoothingMode = SmoothingMode.HighQuality
objGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality
objGraphics.CompositingQuality = CompositingQuality.HighQuality
If Request.QueryString("thumb") = "false" Then
Return Source_Img
Else
objGraphics.DrawImage(Source_Img, 0, 0, width, height)
Return thumbnail
End If
End Function
Sub ResizeImage()
' Get width using QueryString.
If ((strSize = Nothing) Or (strSize >= originalimg.Width)) Then
width = originalimg.Width ' Use Orginal Width.
ElseIf strSize = 0 Then ' Assign default width of 100.
width = 100
Else
width = strSize
End If
tmpheight = originalimg.Height * width / originalimg.Width
' Get height using QueryString.
If ((strSize = Nothing) Or (strSize >= tmpheight)) Then
height = tmpheight 'orginalimg.Height ' Use Orginal Height.
ElseIf strSize = 0 Then ' Assign default height of 100.
height = tmpheight 'height = 100
Else
height = strSize ' Use User Specified height.
width = width * height / tmpheight
End If
Response.ContentType = "image/jpeg"
thumb = Ettienne_Thumbnail(originalimg, height, width)
Dim codecEncoder As ImageCodecInfo = GetEncoder("image/jpeg")
Dim quality As Integer = 100
Dim encodeParams As New EncoderParameters(1)
Dim qualityParam As New EncoderParameter(Imaging.Encoder.Quality, quality)
encodeParams.Param(0) = qualityParam
thumb.Save(Response.OutputStream, codecEncoder, encodeParams)
originalimg.Dispose()
thumb.Dispose()
Response.End()
End Sub
'creates image text
Sub createTextImage(ByVal strText As String, ByVal intWidth As Integer,
ByVal intHeight As Integer, ByVal intFontSize As Integer, ByVal intTop As Integer,
ByVal intLeft As Integer)
If intFontSize < 1 Then
intFontSize = 10
End If
Dim objBMP As System.Drawing.Bitmap = New Bitmap(intWidth, intHeight)
Dim objGraphics As System.Drawing.Graphics
objGraphics = System.Drawing.Graphics.FromImage(objBMP)
objGraphics.Clear(Color.Gray)
Dim objFont As System.Drawing.Font = New Font("Arial", intFontSize, FontStyle.Bold)
objGraphics.DrawString(strText, objFont, Brushes.White, intLeft, intTop)
Response.ContentType = "image/GIF"
objBMP.Save(Response.OutputStream, ImageFormat.Gif)
' Kill our objects
objFont.Dispose()
objGraphics.Dispose()
objBMP.Dispose()
End Sub
Now lets rewrite the URLs so that we have nice .jpg extensions. I am using HttpModule provide by http://urlrewriter.net. First you have to copy the Intelligencia.UrlRewriter.dll into your bin folder. Second, we need some web.config setting to make this work:
<configSections>
<section name="rewriter" requirePermission="false"
type="Intelligencia.UrlRewriter.Configuration.RewriterConfigurationSectionHandler,
Intelligencia.UrlRewriter"/>
</configSections>
<system.web>
<httpModules>
<add name="UrlRewriter"
type="Intelligencia.UrlRewriter.RewriterHttpModule,
Intelligencia.UrlRewriter"/>
</httpModules>
<compilation debug="true"/></system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRewriter"
type="Intelligencia.UrlRewriter.RewriterHttpModule"/>
</modules>
<validation validateIntegratedModeConfiguration="false"/>
</system.webServer>
<rewriter>
<rewrite url="~/img/(.+).jpg" to="~/img/resize.aspx?f=$1"/>
</rewriter>
Finally, we can just reference our images in the following fashion:
<p>small</p>
<img src="img/389688230_s.jpg" />
<hr />
<p>medium</p>
<img src="img/389688230_m.jpg" />
<hr />
<p>large</p>
<img src="img/389688230_l.jpg" />
<hr />
<p>default</p>
<img src="img/389688230.jpg" />
Almost forgot the most important note. You do need to run IIS 7 in order to have extension-less rewriting. Jut got off the phone with network solutions, disappointed that all their shared hosting servers run IIS 6. I guess I am stuck with good old Godaddy.com.
The sample code can of the ASP.NET image processing script can be downloaded here.
1/21/2009
I have just posted a new code version of my CMS. This CMS is targeted for small business websites. Over the years, I have been building may small byz websites. Since I was not able to find something flexible enough, and easy enough to use, I have build my own CMS. This CMS is free to download and I am trying to encourage the open source community to help me improve it.
Dave’s CMS introduces unique CMS model, where every page is composed from zones, which can be reused on multiple pages.