Monday, December 18, 2006

Disabling the Browser Context Menu

You can disable the browser context menu for an element in your DOM with the following JavaScript recipe:

function disableContextMenu(element)
{
element.oncontextmenu = function()
{ return false; }
}

For example, to disable the context menu over a photo on your page, you could use:

disableContextMenu(document.getElementById("photo"));

Browsers like Firefox do not always allow web pages to disable the context menu (this option is a setting in Firefox), so this recipe will not work 100% of the time in all browsers.

See the example

Sunday, December 3, 2006

JavaScript Debug Log

Date: Monday, 18 Dec 2006 14:08

Even with the most advanced debugging tools, every program requires a little "printf debugging": run your program, print out state as it executes, and visually verify that everything is working properly. Unfortunately, there is no built in console to print debug messages to in JavaScript, forcing many JavaScript programmers to revert to calling alert() in their code. alert is completely infeasible for a function that gets called a lot, as it halts execution until you click an OK button. This recipe creates a simple debug log window that does not halt execution:



function log(message) {
if (!log.window_ log.window_.closed) {
var win = window.open("", null, "width=400,height=200," +
"scrollbars=yes,resizable=yes,status=no," +
"location=no,menubar=no,toolbar=no");
if (!win) return;
var doc = win.document;
doc.write("<html><head><title>Debug Log</title></head>" +
"<body></body></html>");
doc.close();
log.window_ = win;
}
var logLine = log.window_.document.createElement("div");
logLine.appendChild(log.window_.document.createTextNode(message));
log.window_.document.body.appendChild(logLine);
}

To print log messages, you just call log() within your code:



for (var i = 0; i < 10; i++) {
log("This is log message #" + i);
}

When you push your code to production, you can just replace the definition of log with an empty function so your users will not see your debug messages.

See the example

Saturday, December 2, 2006

Only well documented software will survive!

I remember when I started my previous job at 1999 as a software developer I’ve asked
my manager about the standards and policies of the company over the documenting. It wasn’t part of the requirements to produce any technical document that would help to see what is going on in the software. Some people started design documents and in beginning days it has been seen as a nice luxury to have if time allow us. Soon when the first phases of software delivery were over and maintenance became an issue every developer was asking the management to free some time for documentation. Unfortunately the need for documentation was not so crucial for the management as it was for the software developers that were responsible for maintenance of application that have been designed years behind.

In the meantime something else was going on which was very much related to this. First a new requirement was raised by the users. The Analysts brought them to developers to talk about the possibilities. Those architects being sharper than the rest took the opportunity and came up with a solution which was promised to rock. Some raised possible issues but very soon they were rejected as the solution was so “flexible” that those changes could be captured. In the beginning phase, just before users get a version to go live, when the concept is not proven to the users as it is for the architects, the new system can capture every requirement users want.. that seems a success, a big applause!


The architect gets promoted and the software is now in the hands of software developers. The product goes live and users are buying it. From time to time small change requests come to the development department and the responsible developer tries to figure out how it can be implemented. He realises that to get the software robust, he needs more time than expected and he learns not to underestimate the efforts. Next time a request comes he starts to tell the analyst that it is not that easy to implement this request and soon the requests make the developer frustrated. “It seems like they never make up their mind properly and keep changing their mind” he mumbles into his screen sometime while digging into the implementation. There comes a day that one of the requests is becoming too expensive to deliver and therefore the analyst finds a nice way of putting it to the request note to get it rejected. That developer may even leave the company and another one takes the place (they always do), but soon the same happens with the new developer and finally the management realises that “something should be done!” That is when management acknowledge the need for documentation.


One thing I have learned so far is that in IT business everyone is very busy and
nobody gets enough time.


I used to put the responsibility to the management’s shoulders to free up some time for me to get the documentation done. They couldn’t come up with nice and easy paste of project planning and it seemed always to be squeezed plan short on resources and the users want to get the product soon and some one made nice offer just to get the deal and so it is up to development to implement the new requirements. I had an impression that my manager tried to tell me (in a way) that I shouldn’t buy it if the requirements are not clear and detailed. Lost of time I happened to come across the situation where the current system isn’t really suitable to get the new requirements implemented. I should have seen it if I could get the requirements clear and detailed, and also if I know my system pretty well.


At the end of those days, I now realise that it was me whoI maintained that software. And it was me who suffered from the frustration and gave higher estimates for something that actually could have been done easier. And it was me who should have make the documentation happen. One could argue and say hey the time was not given, but I always believed that writing software is an act of art and I am the creator of it and at the end of the day the world is how we make it. So I should not have created any crap.


Fortunately, these days managers are more and more appreciating the documentation and it seems like they do their best to support the development
and free some time for documentation. That is very nice feeling when you have such a manager supporting you and that is how you can deliver maintainable software: Making good documentation at any costs.


In the past ten years I have seen tremendous changes in the way software is developed and maintained. Although there are plenty of methodologies I haven’t even thought about but it is remarkable that in this small world of mine companies have grown their IT departments into a dedicated service businesses. Companies are getting about 10 year service contract when buying the software. That is probably more than the service lifetime of a version of any big software like Oracle or even windows. Companies are investing huge money into the IT products and they want to get the best quality and longest support. It is not a shop-as-you-go business. It is rather a long-term relationship with support for change requests, as the market and the human needs are growing rapidly in these days. And one thing we all know; peoples demands never stops. So we need to make our software ready for that. We can’t assume that the system will cater all kind of situations and we need to document all aspects of it to make the changes coming in the near future possible.


So, who knows what I am writing right know? And who would want
to know that in 10 years over and over? It is me. And I can not remember it right if I wouldn’t right it down.

Wednesday, June 21, 2006

Asynchronous Invocation Using BackgroundWorker / Threading / C#

Sample Image

Introduction

When you have a function that takes a long time and it freezes the screen, the user gets nervous. They simply don't like to lose the control. It would give a friendly impression when they can still click on the form while the application is busy with getting the information, for example. When you start implementing asynchronous methods, you will wonder which technique is best suitable for your application. Would you use a Timer class or a Thread class or a BackgroundWorker? This article uses a BackgroundWorker class to show how easy it is, and where you need to pay attention when using it.

Background

I have tried to compare different methods of implementing Asynchronous Invocation in my weblog. With Microsoft Visual Studio 2005 , I discovered this class which is new to me.

Using the code

I have put extra comments everywhere possible, to make the sample a snippet of code you can use to start your own implementation. The code implements a very simple action, which is finding files in a directory to simulate the time consuming action. This is the place where you need to change. For the rest, the skeleton should be kept the same.

The background worker is able to send an event to the called thread to change the screen appearance. That is very easy, and I thought it would be easy for everyone to discover. But what if that is not enough and you would like to send other messages back to the caller? So I used BeginInvoke to invoke a call on the caller thread.

I have two delegates used from the sub thread, to call the method implemented in the main thread.

private delegate  void PaintMessage(TreeNode root,                                     string childText); private PaintMessage myAddNode = null;

The OnPaontMessage implements the adding of a newly found file into an existing (given) root. This is called when the sub-thread finds a new item.

private  delegate void EnableCancel(bool enabled); private EnableCancel myEnableCancel = null;

The second delegate is to indicate that the thread has been started and that it could be stopped. It is implemented by the main thread to enable the Cancel button.

Starting the action will be done by calling the RunWorkerAsync method on the worker.

this.backgroundWorker1.RunWorkerAsync(treeView1.Nodes[path]);

When a sub-folder is found, I send a notification to the main thread to create a node for the sub-folder. Then, I use that node to create a file node in it. But the dilemma is that I can not proceed with filling the file, if the main thread didn't get the chance to create the sub folder. Thus, I need to wait and let the main application take the chance to create it. One simple way to do this is the following loop:

// Create a folder node before proceeding IAsyncResult ar = BeginInvoke(myAddNode, new object[]                   { root, di.Name }); // Update the screen  // Wait until the folder has been created before // proceeding with the content of the folde while (!ar.IsCompleted) {     Application.DoEvents();     ar.AsyncWaitHandle.WaitOne(-1, false); }

First, I invoke the delegate and I keep the reference to it. I use the reference to see if it has been completed. And in the loop, I let the application take the chance and do its events. Meanwhile, I tell my sub-thread to wait a bit.

Tuesday, June 6, 2006

Searching tables and columns

I am working with some big databases having similar tables for different group.
It seems to be poluted by different parties and have no administrator. Some developers
put their application initials as a prefix of the table names and as a result we
got several Contact tables and several Items each with diffeent layouts.

When I am dealing with these tables I need to find everything to do with lets say
Code. I need to find out all the tables having a field like Tax_Code or TaxCode
or ItemCode etc. It might be even good to know if there are tables called like Meta_Code
or Item_Code etc.

To find these two things I have written two stored procedures to use as follows
:

sp_FindColumns ‘Code’
And
sp_FindTables ‘Code’

When I was using these two I realised that also some stored procedures
are dealing with changing a field internally. So I had to also write something to
search the definitions of the stored rocedures to find al those mentioning the field
in the code and I came up with the following procedure:

sp_FindInProcedure ‘Tax_Code’

.And below are the defenitions for them.


--------------------------------------------------------------------------------

if exists (select * from sysobjects
where id = object_id(N‘[dbo].[sp_FindColumns]’) and OBJECTPROPERTY(id,
N‘IsProcedure’) = 1)
drop procedure [dbo].[sp_FindColumns]
GO

Create Procedure sp_FindColumns
@sToSearch varchar(255)
AS
BEGIN
/************************************************************************************* *
* sp_FindColumns
*
* This stored procedure will look into all table collumns
* search the string which is given as the only parameter.
*
************************************************************************************* * By Asghar Panahy
* 12-jun-2006
**************************************************************************************/


SELECT SO.name + ‘.’ + Sc.name
FROM SysColumns Sc
Inner Join SysObjects SO
on SO.ID = SC.ID
Where SO.xtype=‘U’
And Sc.Name like ‘%’ + @sToSearch + ’%’

END

--------------------------------------------------------------------------------

if exists (select * from sysobjects
where id = object_id(N‘[dbo].[sp_FindTables]’) and OBJECTPROPERTY(id,
N‘IsProcedure’) = 1)
drop procedure [dbo].[sp_FindTables]
GO

Create Procedure sp_FindTables
@sToSearch varchar(255)
AS
BEGIN
/************************************************************************************* *
* sp_FindTables
*
* This stored procedure will look into all table names
* search the string which is given as the only parameter.
*
************************************************************************************* * By Asghar Panahy
* 12-jun-2006
*************************************************************************************
*/
SELECT Distinct So.Name
FROM SysColumns Sc
Inner Join SysObjects SO on SO.ID = SC.ID
Where So.xtype= ’U’
And SO.Name like ‘%’ + @sToSearch + ‘%’

END

if exists(select * from sysobjects where id = object_id (N‘[dbo].[sp_FindInProcedure]’) and
OBJECTPROPERTY(id, N‘IsProcedure’) = 1) color="#0000ff”
drop procedure [dbo].[sp_FindInProcedure]
GO

Create Procedure sp_FindInProcedure
@sToSearch
varchar(255)
AS

BEGIN
/************************************************************************************* *
* sp_FindInProcedure
*
* This stored procedure will look into all stored procedures defenitions to
* search the string which is given as the only parameter.
*
************************************************************************************* * By Asghar Panahy
* 12-jun-2006
**************************************************************************************/


SELECT so.name, sc.text
FROM syscomments sc
JOIN sysobjects so ON sc.id = so.id
WHERE so.xtype = ‘P’
And sc.Text like ’%’ + @sToSearch + ‘%’
Order By so.Name Asc

END

Column Description in SQL Server

The biggest challenge for me to learn de the business is to figure out how it hasbeen translated into a database. The more information I get out of the databasethe more familiar I feel myself with the business.
For applications living or quite some times and evolved by several developers, thisbecomes difficault if you can’t find out what those columns meant to keep. Speciallywhen they are keeping codes and flags which has not direct meaning for the businessbut rather they are stored as a meta data.
One of the handy implementation for such an information is the database itself.Lots of database administrators (and also developers) choose to keep the descriptionof a column somewhere reserved by the database. SQL-Server is not so convinientin this matter. Or maybe the system is while the user interface is not so open forit.
There is a so called undocumented stored procedure in the SQL-Server called sp_columns_rowset which shows you al you need and even more about atable. I am not going to talk about my experience with this undocumented storedprocedure which you can search the net and find some examples about it. Just mentioningit that it givs you something it calls DESCRIPTION of the field.
The question I have is where is this DESCRIPTION maintained? or even better, Howcan I fill this attribute? What should I do to get the descriptions of the columnsupdated with meaningfull sentence?

Tuesday, February 21, 2006

How to merge two Visual SourceSafe databases

This is a piece of cake when you know VSS has already provided tools for that. Irealised that some companies have different teams keeping their sources in differentVSS repositories. Maybe not all of them willing to merge these but certainly somedo. I was thinking of creating such a tool to bring all the history of the filesusing VSS programming API. I have investigated the VSS Admin and yes it doesit for free.
  • Open the VSS Admin screen (obviously you need to have administrative privilages)
  • From the menu’s select Archive->ArchiveProjects.. and create archive files foreach database.
  • Repeat this for all the vss databases you want to merg together
  • Create the destination VSS databased from the admin screen.
  • In that database create projects on the root. This is making it conviniet to importeach database into a seporate project. Although this step is not necessary and youcan do that during the next step too.
  • From the menu’s select Archive->RestoreProjects.. and select the archived file.Follow the wizard to select a location to restore the old database into the newlacation.


    Isn’t this just simple!
  • Importing source history from VSS to TFS

    I have managed to import a Visual SourceSafe database including the historyof it into the Microsoft Team Foundation System.
    It requires you to create a new project in the TFS as destination ream project,and by the way you can do this in Visual Studio using the menu File->New->TeamProject,doing the analyse and read the nice and handy report which gives you beautiful listof all warnings and errors. Then I had to map the users of one repository to theother one by editing the users.xml that comes out of the analyse step. You can mapdifferent folders from one to the other if you like to do so by editing the settings.xmlwhich is very convinient.
    During the exercise you will be asked to type in the VSS administrator password.