.

Tuesday, July 25, 2006

EasyPack, pushbutton syntax checking, compression and obsfucation #



So what on earth is EasyPack ?

Basically EasyPack is JSLint combined with packer plus some pixie dust to enable batch processing and AJAXification of sardalya to couple client tier and business tier.

pros:

- To run EasyPack is as easy as clicking a button.
- EasyPack analyzes and compresses scripts in batches.
- No copy-paste of source code needed. Files are read from an XML meta data.
- EasyPack is easy to configure.
- EasyPack is Modular.

cons:

- It is an ASP.Net C# Web Application, hence you require IIS to run it.
- You need a dedicated (ideally a local development) server.

I could have written it as a php, jsp or ruby application; but I found ASP.Net C# quicker to deploy and I've chosen it since I'm running out of time nowadays.

You can have a look at it here:

http://www.codeproject.com/useritems/EasyPack.asp


Cheers.

Labels: , ,


 bu yaziyi sevdin mi?  hemen una ekle!
 

Monday, July 24, 2006

released a new version of sardalya #

I've released a new version of sardalya.

You can have a look at the sardalya wiki for details.

Labels: , , ,


 bu yaziyi sevdin mi?  hemen una ekle!
 

Tuesday, July 18, 2006

packing javascript #

I have been thinking of a new compression algorithm for orkinos for a long time. And because of the stress of other projects over me I had pended development of orkinos a few months ago.
... until I stumble upon Dean Edwards' packer. Dean, generously provides a C# version of his library.

Since orkinos is open source; integrating the library does not conflict with Dean's licensing requirements.

The first thing I do tomorrow will be replacing the core functionality of orkinos with packer (and ammending the CC LGPL license of packer, link to Dean's website etc to the release bundle).

I tried packer on sardalya. It compresses almost twice better than orkinos' core compressor.
I will leave orkinos' JSCodeCompressor class in the next version, for people who just want to trim new lines or strip out the comments and see what can be done with the remaining code.


edit:
I've implemented the wrapper (in less than 10 minutes) but the code is too messy for the next release; and I don't have time to clean it up.

Actually I don't want to release the next version unless it adds a considerable value. I have several things in mind (one of them is merging JSLint and packer into a single C# executable and adding a batch compression option to it).

But I won't have free time to work on it for at least several months.



Thank you Dean for sharing your library with the rest of the world.


I love open source :)

 bu yaziyi sevdin mi?  hemen una ekle!
 

Monday, July 10, 2006

how to preserve client session #

Are you tired of your clients yelling you:

"I have been writing this article for more than an hour and when I submit it to the site the system logs me out and all I have written apriori is lost forever..."

Then this post is just for you.

Using a little bit of ajax and some pixie dust it is really easy to elimate client's session timeout when he is doing a critical task (such as writing a content to post on a forum; authoring a critical article; modifying parts of his web-based CMS etc.)

Here goes the code:
var Ping=
{
init:function()
{
/*
* I'm using sardalya's _.ajax Shortcut:
* http://sardalya.pbwiki.com/Shortcuts
*
* However, the code can be easily
* adjusted to utilize any ajax wrapper.
*/
this.ajax=_.ajax();
this.ajax.oncomplete=this.push_complete;
this.ajax.onerror=this.push_error;
this.clientPush();
},
clientPush:function()
{
Ping.ajax.abort();
Ping.ajax.init();
Ping.ajax.get(URL.ajax.action.PreserveSession);
},
push_complete:function(strResponseText,objResponseXML)
{
if(strResponseText.toLowerCase()=="false")
{
alert(Message.IN_RESTARTING);
window.location.reload();
}
else
{
setTimeout(Ping.clientPush,Ping.interval);
}
},
push_error:function(intStatus,strStatusText)
{
setTimeout(Ping.clientPush,Ping.interval);
},
/* ajax handle */
ajax:null,
/* check interval in milliseconds */
interval:60000
};

var URL=
{
ajax:
{
action:
{
/* initiates a simple server-side check to validate session
* (checks whether Session["user"] is null or not)
* Prints true if Session["user"] is not null; false otherwise.
*/
PreseveSession:
"http://example.com/ajax/action/PreseveSession.aspx";

}
}
};

var Message=
{
IN_RESTARTING:"Sorry, the system is in an "+
"inconsistent state. I have to restart..."

};
and all you need to call is Ping.init() on window.onload and sleep peacefully at nights.
window.onload=function(evt)
{
Ping.init();
};

However using it all over your site may have a slight impact on performance
(since you can be holding more than optimum number of session in server's memory).

Although this will be insignificant to an average web application; if you have a high-traffic site this may have some effect on performance.

Thus the best way to use this technique is to include it only in misson-critical pages (such as and edit/send comment page of a forum post which in general includes a textarea to edit and send back to server upon submit) but not in every single page of your web application.

Your users may not get that angry when they incidentially fall down to login page from the default page because of a session timeout since they are not doing a mission-critical task.

The users' (or your client's) face may turn into red from anger if s/he loses the session after having written and posted a 6-paragraph article :)

 bu yaziyi sevdin mi?  hemen una ekle!
 

Saturday, July 08, 2006

How to make a diary with notepad #

If you are a windows user

  1. Open a new Notepad from your start menu (shortest way is to use {Windows Key + R} and type "notepad" in the prompt that pops up)

  2. Type .LOG on the first line (all caps don't forget to start with a dot (.) )

  3. Press enter to go to the next line.

  4. Give a meaningful file name, save and exit.

If you did it correctly; each time you open the text file with notepad a timestamp will be automatically ammended to the bottom of the text. A simple diary to track your progress.

Here is what it looks like:


 bu yaziyi sevdin mi?  hemen una ekle!
 

Thursday, July 06, 2006

AJAX Wrapper enhanced #

After creating a simple leak free defensive AJAX wrapper, and tweaking a bit to more effectively handle leaks, I found out that under certain (really uncommon, infrequent and abnormal) situations the object can still leak a little bit of memory.

So I decided to attach an onunload handler to the constructor and get rid of the leaks for good.

In addition, I enhanced the object further. It will be available to the rest of the world when I release the new version of sardalya. But for you lucky guys out there, I'm pasting entire code below.

/** XHRequest ----- **/

function XHRequest()
{
this._fields=[];
this._values=[];
this._initialized=false;
this.init();

}

_this=XHRequest.prototype;

_this.removeAllFields=function()
{
this._fields.length=0;
this._values.length=0;
};

_this.addField=function(strField,strValue)
{
this._fields.push(strField);
this._values.push(TextFormatter.escape(strValue));
};

_this.post=function(strURL,_blnSync)
{
if(!this._xhr)
{
return;
}

if(!_blnSync)
{
_blnSync=false;
}

var uq=this._generateURL(strURL);

this._xhr.open("POST",uq.url,!_blnSync);
this._setRequestHeaders();
this._xhr.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
this._xhr.send(""+uq.query/*null -- Opera does not like null.*/);

this._postProcess(_blnSync);
};

_this.postSynchronized=function(strURL)
{
this.post(strURL,true);
};

_this.get=function(strURL,_blnSync)
{
if(!this._xhr)
{
return null;
}

if(!_blnSync)
{
_blnSync=false;
}

var uq=this._generateURL(strURL);

this._xhr.open("GET",uq.url+"&"+uq.query,!_blnSync);

this._setRequestHeaders();
this._xhr.send("");

this._postProcess(_blnSync);
};

_this._postProcess=function(blnSync)
{
if(blnSync)
{
/*
* note that 99.99% of the time you'll make async requests
* so this method will not be executed at all.
*/
this._processAsyncRequest();
}
else
{
AjaxController.incrementCount();
}
};

_this._processAsyncRequest=function()
{
var obj=this._xhr;

if(obj.status==200||obj.status==304)
{
this.oncomplete(obj.responseText,obj.responseXML);
}
else
{
this.onerror(obj.status,obj.statusText);
}

this._cleanup();
};

_this.getSynchronized=function(strURL)
{
this.get(strURL,true);
};

_this.getObject=function()
{
var request=null;
var arProgID=null;

if(this._xhr)
{
request=this._xhr;
}
else if(window.XMLHttpRequest)
{
request=new XMLHttpRequest();
}
else if(window.ActiveXObject)
{
try
{
request=new ActiveXObject("Msxml2.XMLHTTP");
}
catch(othermicrosoft)
{
try
{
request=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (failed)
{
arProgID=[
"Msxml2.XMLHTTP.7.0",
"Msxml2.XMLHTTP.6.0",
"Msxml2.XMLHTTP.5.0",
"Msxml2.XMLHTTP.4.0",
"MSXML2.XMLHTTP.3.0"];

for(var i=0;i<arProgID.length;i++)
{
try
{
request=new ActiveXObject(arProgID[i]);
break;
}
catch(ignore)
{
}
}
}
}
}

return request;
};

_this.finalize=function()
{
if(!this._xhr)
{
return;
}

this._cleanup();
this._xhr=null;
};

_this.init=function()
{
var sourceElement=this;
var obj=null;
var cleanme=null;

this._xhr=this.getObject();

if(!this._xhr)
{
return;
}

if(!this._initialized)
{
/*
* Since we cannot add onreadystatechange event
* to the EventRegistry using EventHandler.addEventListener
* we need a special cleanup process to take care
* of circular references.
*
* If for some reason this._xhr still remains on memory
* before window unload; then this method will take
* care of it.
*/
cleanme=function(evt)
{
/* finalize the sourceelement */
sourceElement.finalize();

/* detach cleanup event. */
_.unchain(window,"unload",cleanme);

/* Remove the final remaining references */

/*
* The three lines below are not necessary.
* They are just for defensive coding.
*/
cleanme=null;
obj=null;
sourceElement=null;
};

_.chain(window,"unload",cleanme,true);
}

this._xhr.onreadystatechange=function()
{
obj=sourceElement.getObject();

if(obj.readyState==4)
{
/*now that the request is completed*/
AjaxController.decrementCount();

/*
* 404: file not found.
* 200: OK.
* 304: reading from cache.
*/
if(obj.status==200||obj.status==304)
{
sourceElement.oncomplete(obj.responseText,obj.responseXML);
}
else
{
sourceElement.onerror(obj.status,obj.statusText);
}

/*to prevent IE memory leak due to circular COM referencing.*/
sourceElement._cleanup();
}
};

this._initialized=true;
};

_this._setRequestHeaders=function()
{
this._xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");
this._xhr.setRequestHeader("X-Sardalya-Version",Sardalya.version);
this._xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");
this._xhr.setRequestHeader("Accept",
"text/javascript, text/html, application/xml, text/xml, */*");
};

_this.abort=function()
{
/*now that the request is completed*/
if(AjaxController.getActiveThreadCount()>0)
{
AjaxController.decrementCount();
}

if(this._xhr)
{
this._xhr.abort();
}

this._cleanup();
};

_this.oncomplete=function(strResponseText,objResponseXML)
{
alert("Completed everything.");
};

_this.onerror=function(intStatus,strStatusText)
{
alert("An error occured but my owner is too lazy to handle it.");
};

_this._cleanup=function()
{
/* release circular reference to solve the memory leak proble in IE. */
this._xhr.onreadystatechange=_.nill();
};

_this._generateURL=function(strURL)
{
var len=this._fields.length;
var append="";
if(len>0)
{
for(var i=0;i<len;i++)
{
append+="&"+this._fields[i]+"="+this._values[i];
}
}

if(append==="")
{
append="&";
}

return {url:(strURL+"?rnd="+Math.random()),query:append.substring(1)};
};

Hope that helps.

 bu yaziyi sevdin mi?  hemen una ekle!
 



Recent Posts

RSS

RSS register icon

Other Blogs

Archive

Various

Sponsor

Profile Information

Browser I Suggest

Sponsor

Dikkatimi Çekenler