Wednesday, November 08, 2006

How to install CVS as a server repository and connect from Eclipse

I tried to find this on the net the other day and could only find it piece-meal. So, in case you're trying to setup a CVS repository. here it all is in one shot.

I make ONE assumption, which is that you already have a remote server that you are accustomed to connecting to that server using ssh and scp.

SECTION A - LINUX COMMAND LINE COMMANDS
SECTION B - REMOTE SERVER CVS REPOSITORY INSTALL
SECTION C: COMMAND-LINE CVS IMPORT / CHECKOUT / COMMIT / UPDATE
SECTION D: ECLIPSE PROJECT CVS IMPORT
SECTION E: ECLIPSE PROJECT CVS EXPLORATION / GET PROJECTS
SECTION F: ECLIPSE PROJECT FILES CHECKOUT / COMMIT / UPDATE / SYNCHRONIZE

*****

SECTION A - LINUX COMMAND LINE COMMANDS

Let's start with some command-line Linux commands for
creating users and groups, since you'll need these shortly
to set up the CVS repository on the server:

To add a user:
useradd -m -c JohnSmith username
or perl script utility (recommended):
adduser username
To delete a user:
userdel -r username

To change a password:
passwd username
You will be asked for a new password.

To add a group:
groupadd groupname
To delete a group:
groupdel groupname

To add a user to a group:
Go to the /etc directory, and use vi
to edit the text file 'group': locate the group name (likely near the bottom.)
It will have the name plus an identifier, ending in a colon, or an existing user.
If it's a colon, just add the username. If a username is there,
type a comma and add the additional username:
groupname:x:1001:dgadd,cvs

*****

SECTION B - REMOTE SERVER CVS REPOSITORY INSTALL
With those commands in hand, you can proceed with a remote server cvs repository install.

Firstm, use ssh to connect.
Let's suppose the server is named 555.555.555.555
In that case:
ssh myusername@555.555.555.555

Now do the following to set up cvs on the remote server:

1) On Ubuntu use apt-get install cvs to install cvs
2) Create a repository folder:
mkdir /var/lib/cvsroot
3) Use Linux commands to create a user, 'cvs' a group 'cvsusers',
and edit the /etc/group file to add 'cvs' to the end of the 'cvsusers' group.
4) Change the group of the repository folder to cvsusers, make directory read/write/execute, and make cvs the owner.
chgrp cvsusers /var/lib/cvsroot
chmod g+srwx /var/lib/cvsroot
chown -R cvs /var/lib/cvsroot
5) Initialize the repository using the cvs command:
cvs -d /var/lib/cvsroot init

SECTION C: COMMAND-LINE CVS IMPORT / CHECKOUT / COMMIT / UPDATE

1) To import a project on your local server to remote server cvs:
Copy the project to a temp directory, because the copy
you use to import needs to be discarded.
Cd into that temp project directory.
Then, to perform the import, run the following command:
cvs -d cvs@555.555.555.555:/var/lib/cvsroot import example MyProject release_0_1

2) To checkout file1 within the project:
cvs -d cvs@555.555.555.555:/var/lib/cvsroot checkout MyProject/file1

3) To commit (checkin) file1 within the project:
cvs -d cvs@555.555.555.555:/var/lib/cvsroot checkout MyProject/file1

4) To update (synchronize) your local files with the (potentially updated) copies on the server:
Go inside the project directory, and type:
cvs update -d // the -d switch will download new directories

SECTION D: ECLIPSE PROJECT CVS IMPORT

The most important thing to know is that when you right-click on an Eclipse project, there is a Team sub-menu that you may not have noticed before. This Team submenu is the key to all of your CVS interaction!

1) Right-click on your Project folder in Eclipse.
2) Select Team, and then click Share Project...
3) If you have not previously set up your CVS repository, then you will be taken to the Share Project dialog box, which asks you to provide repository information.
4) Enter the following information (assuming your remote server repository ip address is 555.555.555.555, and you have set up the repository as described above):
Host: 555.555.555.555
Repository path: /var/lib/cvsroot
User: cvs
Password: your_password
Connection type: extssh
Use default port: selected
Save password checkbox: checked

5) Click Next->
6) Select the default 'Use project name as module name'.
7) Click Next->
8) Click Finish. (This should launch the Commit Wizard.)
9) A list of default types is shown, all to be saved as binary. Click next.
10) You are now asked to provide a comment before saving. A recommended format would be Date, User, Platform/Machine, Action:
Date: 2006Nov08
User: John Smith
Platform: Linux
Action: Importing project for first time

11) Click Finish. Your project will be imported.

SECTION E: ECLIPSE PROJECT CVS EXPLORATION / GET PROJECTS
Assuming you have completed the previous section and imported your project, you now need to be able to go to Eclipse on other machines, access the CVS repository and get the project(s) that you have imported. Here's how.

1) In Eclipse, from the Window menu, select the Open Perspective submenu and click Other...
2) In the Select Perspective dialog box, click CVS Repository Explorer, and then click OK.
3) Right-click inside the CVS Repositories pallete and select New > Repository Location...
4) In the Add CVS Repository dialog box, enter the following information (assuming your remote server repository ip address is 555.555.555.555, and you have set up the repository as described above):
Host: 555.555.555.555
Repository path: /var/lib/cvsroot
User: cvs
Password: your_password
Connection type: extssh
Use default port: selected
Save password checkbox: checked

5) Expand the new tree that appears in the CVS Repositories pallete.
6) Expand HEAD, and locate the project you imported earlier.
7) Right-click on the project, and click Checkout...
After a few seconds, the project checkout will have completed.
8) Switch back to the default (Java) perspective.
Your newly checked out project will be visible in the Package Explorer.
9) Since library references are imported, but not the libraries themselves, the project will have a red x on it to indicate problems. Click on the Problems palette (typically at the bottom of the Eclipse window) to determine your list of missing libraries.
10) Rclick on the project, select the Build Path submenu, and click Configure Build Path...
11) In the Properties for [Project Name] dialog box, the project referneces will be listed.
12) One-by-one, remove these outdated references and then use the Add External Jar... button to add a reference to a local copy of each jar.

You're done. You can now proceed to checkout, commit, update and synchronize files (below).


SECTION F: ECLIPSE PROJECT FILES CHECKOUT / COMMIT / UPDATE / SYNCHRONIZE

1) To checkout a file:
You don't. Just start editing a file. As soon as you save a change, the file (and it's containing folder / package) will be marked with a greater-than symbol:
>login.jsp

2) To commit a file:
* Right-click on the file, and from the Team submenu, click Commit...
* The Commit Files dialog will appear. Please provide a comment before saving. A recommended format would be Date, User, Platform/Machine, Action:
Date: 2006Nov08
User: John Smith
Platform: Linux
Action: Added blah blah blah to the file.
* Click Finish. The change will be committed.

3) To update a file / project (i.e. get latest).
* If you aren't worried about changes, you can just "get latest" for the entire project.
* Right click on the Project and from the Team submenu, click Update.
* This will update the entire Project to match the latest contents of the repository.

4) To synchronize with the repository
* If you are worried about changes and want the opportunity to diff your files, use this command
* Right click on the project or a specific file, and from the Team submenu, click Synchronize with Repository
* You will be asked to switch to the Team Repository perspective. Allow this.
* In the Synchronize palette, select files that require synchronization. Proceed to diff them, and then commit changes.

Saturday, April 01, 2006

Debugging AJAX/Javascript for IE and Firefox with Visual Studio .NET

The title of this article is slightly inaccurate, because it implies that both IE and Firefox AJAX/Javascript debugging can be performed directly within Visual Studio .NET. That is not exactly the case. While it is easy to set up AJAX/Javascript debugging with IE and Visual Studio .NET; and while it is easy to use Firefox as your .NET debugging browser with Visual Studio .NET; if you specifically want to debug Javascript for Firefox while using Visual Studio .NET, you have to add a Firefox Javascript debugger.

Let's describe the scenario in more detail, and then discuss the three major activities to get IE and Firefox debugging working with Visual Studio .NET.

A. Scenario
B. Setting Up Javascript debugging for Internet Explorer (and Visual Studio .NET)
C. Redirecting the default browser in Visual Studio .NET between IE and Firefox.
D. Setting Up separate Javascript debugging for Firefox (using venkman).


*****

A. Scenario
1. You want to do an AJAX call from your Javascript in an html page, to an ASPX page that is sending back simple XML (REST protocol, not SOAP).
2. Therefore, you begin by creating a Visual Studio .NET project and creating an ASPX page that sends out XML. (How? That's outside the scope of this article. For examples, download the sample projects for the book "Ajax in Action" (Manning)).
3. You then create an html page in the same project, and write AJAX-style Javascript to call the ASPX page. (Again, outside the scope of this article. Again, consult the "Ajax in Action" sample code).
4. When you run the project, you can set breakpoints in your .NET code and debug the .NET code as usual.
5. However, what if you have Javascript bugs? How do you set breakpoints and debug these Javascript errors?
6. Also, since different browsers use different versions of Javascript and the DOM, you need to be able to debug Javascript not only in Internet Explorer, but also in Firefox. How do you do this?

B. Setting Up Javascript debugging for Internet Explorer (and Visual Studio .NET)

Debugging your Javascript code from Internet Explorer is extremely simple--the functionality is already there, it is simply disabled by default.

To enable IE Javascript debugging:
1. Launch Internet Explorer.
2. From the Tools menu, click Internet Options...
3. In the Internet Options window, select the Advanced tab, and then uncheck Disable Script Debugging.
4. Now relaunch Visual Studio, and put two breakpoints: one in your Javascript code, one in your .NET code.

When you run the project, both breakpoints can now be reached. However, what if you now want to perform the same debugging with Firefox and Visual Studio .NET?

C. Redirecting the default browser in Visual Studio .NET between IE and Firefox.

To get Visual Studio .NET to launch Firefox as your default browser, instead of IE, you need to do the following:
1. In the Solution Explorer, right-click on your HTML or ASPX page and click Browse With. (You can also access Browse With from the File menu when an HTML or ASPX page is currently loaded in the main window of Visual Studio .NET).
2. In the Browse With dialog box, select Firefox, click Set as Default, and then click Close.
3. Now, set a breakpoint in both your Javascript code and your .NET code.

What happens? Firefox launches as the browser, and the .NET code breakpoint is reached, but the Javascript breakpoint is ignored.

D. Setting up separate Javascript debugging for Firefox (using venkman).

Visual Studio .NET does not recognize the Javascript breakpoints when Firefox is the default browser. However, you can get around this by installing a Firefox extension for a Firefox Javascript debugger. In our case, we'll use venkman.

To install the venkman extension
1. Google "venkman" to locate the installer.
One current location as of the time of this writing is: https://addons.mozilla.org/extensions/moreinfo.php?id=216
2. Make sure you select the version that corresponds to your version of Firefox, then proceed to install the extension.
3. Restart Firefox.

Now you're ready to put it all together: running Firefox as the default browser in Visual Studio .NET, accessing your .NET code breakpoints with Visual Studio .NET, and accessing your Javascript breakpoints with Venkman.

Tying it all together
1. From Visual Studio, set a .NET code breakpoint (but not a Javscript breakpoint).
2. Verify that you have selected Firefox as your default browser.
3. Run the project.
Firefox will launch.
4. In Firefox, from the Tools menu, click Javascript Debugger.
Venkman Javascript debugger launches. The debugger displays a number of subwindows, including Loaded Scripts, Local Variables,Breakpoints, and the Source Code window.
5. In the Loaded Scripts window, double-click the HTML page or ASPX page to load it. (Or, if you wish to set a breakpoint in a related Javascript, double-click the related script instead.)
6. In the Source Code window, right-click on the line of code that you wish to set a breakpoint and click Set Breakpoint.
7. Now, return to Firefox and perform an action (such as a button or link click) to trigger the Javascripts in the page.

The end result? You should now be able to hit both the Javascript breakpoints (in venkman) and the .NET breakpoints (in Visual Studio .NET).

Thursday, March 30, 2006

Using Javascript to create draggable divs (no frames!)

Today's entry provides sample code for creating draggable div columns to store information in multiple columns without needing to use frames.

Feel free to copy the HTML below into notepad and save it as an HTML file. I've tested this in both Firefox and IE. You should be able to successfully drag the columns wider and narrower and watch the text in the middle column follow the widening and narrowing of the column.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<title> Dynamic Table </title>
<style type="text/css">
#DragColumn_0
{
     position:relative;
     z-index:5;
}

#ContentColumn_1
{
     border: 1px solid #006699;
     position:absolute;
     overflow:hidden;
     z-index:10
}

#DragColumn_1
{
     position:absolute;
     cursor:e-resize;
     z-index:11;
}

#ContentColumn_2
{
     border: 1px solid #006699;
     position:absolute;
     overflow:hidden;
     z-index:10
}

#DragColumn_2
{
     position:absolute;
     cursor:e-resize;
     z-index:11;
}

#ContentColumn_3
{
     border: 1px solid #006699;
     position:absolute;
     overflow:hidden;
     z-index:10
}

#DragColumn_3
{
     position:absolute;     
     cursor:e-resize;
     z-index:11;
}
</style>

<script type="text/javascript">

window.onload = function()
{
     PageSetup();
}


// global constants
var ZERO_AMOUNT = 0;
var ONE_MILLISECOND = 1;
var SIX_MILLISECONDS = 6;

// global variables
var _xMousePosition = 0;
var _yMousePosition = 0;
var _mouseButtonDown = false;


// event handlers
function MouseMoveHandler(event) {
     var e = event || window.event;
     _xMousePosition = e.clientX + document.body.scrollLeft;
     _yMousePosition = e.clientY + document.body.scrollTop;
}

function MouseDownHandler(event) {
     var e = event || window.event;     
     var elementID = e.srcElement ? e.srcElement.id : e.target.id;
     var columnIndexValue = elementID.slice(elementID.length-1, elementID.length);
     _mouseButtonDown=true;
     ChangeColumnWidth(columnIndexValue);
}     

function MouseUpHandler(event){
     var e = event || window.event;
     _mouseButtonDown = false;
     var cursorResetFunctionCall = 'document.body.style.cursor = ""';
     window.setTimeout(cursorResetFunctionCall, SIX_MILLISECONDS);
}

function PageSetup()
{
     document.onmousemove = MouseMoveHandler;
     document.onmouseup = MouseUpHandler;
     
     var drag0 = document.getElementById("DragColumn_0");
     var drag1 = document.getElementById("DragColumn_1");
     var drag2 = document.getElementById("DragColumn_2");
     var drag3 = document.getElementById("DragColumn_3");
     var column1 = document.getElementById("ContentColumn_1");
     var column2 = document.getElementById("ContentColumn_2");
     var column3 = document.getElementById("ContentColumn_3");
     var colWidth1 = _columnWidthSettings[1];
     var colWidth2 = _columnWidthSettings[2];
     var colWidth3 = _columnWidthSettings[3];
     
     drag0.style.left = TABLE_LEFT + "px";
     drag0.style.top = TABLE_TOP + "px";
     drag0.style.height = TABLE_HEIGHT + "px";

     column1.style.left = TABLE_LEFT + "px";
     column1.style.width = colWidth1 + "px";
     column1.style.top = TABLE_TOP + "px";
     column1.style.height = TABLE_HEIGHT + "px";

     drag1.style.left = (TABLE_LEFT + colWidth1) + "px";
     drag1.style.width = DRAG_WIDTH + "px";
     drag1.style.top = TABLE_TOP + "px";
     drag1.style.height = TABLE_HEIGHT + "px";
     drag1.onmousedown=MouseDownHandler;
     
     column2.style.left = (TABLE_LEFT + colWidth1 + DRAG_WIDTH) + "px";
     column2.style.width = colWidth2 + "px";
     column2.style.top = TABLE_TOP + "px";
     column2.style.height = TABLE_HEIGHT + "px";

     drag2.style.left = (TABLE_LEFT + colWidth1 + DRAG_WIDTH + colWidth2) + "px";
     drag2.style.width = DRAG_WIDTH + "px";
     drag2.style.top = TABLE_TOP + "px";
     drag2.style.height = TABLE_HEIGHT + "px";
     drag2.onmousedown=MouseDownHandler;

     column3.style.left = (TABLE_LEFT + colWidth1 + DRAG_WIDTH + colWidth2 + DRAG_WIDTH) + "px";
     column3.style.width = colWidth3 + "px";
     column3.style.top = TABLE_TOP + "px";
     column3.style.height = TABLE_HEIGHT + "px";

     drag3.style.left = (TABLE_LEFT + colWidth1 + DRAG_WIDTH + colWidth2 + DRAG_WIDTH + colWidth3) + "px";
     drag3.style.width = DRAG_WIDTH + "px";
     drag3.style.top = TABLE_TOP + "px";
     drag3.style.height = TABLE_HEIGHT + "px";
     drag3.onmousedown=MouseDownHandler;
}



function ChangeColumnWidth(columnIndexValue){
//alert("You reached to the top of the ChangeColumnWidth method!");
var columnIndex = parseInt(columnIndexValue);

if(columnIndex >= 0){
     document.body.style.cursor = "e-resize";
     
     var previousDragColumn = document.getElementById("DragColumn_" + (columnIndex-1));
     var currentDragColumn = document.getElementById("DragColumn_" + columnIndex);
     var currentContentColumn = document.getElementById("ContentColumn_" + columnIndex);
     
     var leftString = previousDragColumn.style["left"] ? previousDragColumn.style["left"]:previousDragColumn.currentStyle["left"];

     var previousDragLeftColumnPosition = parseInt(leftString.slice(0,leftString.length-2));
     var previousDragRightColumnPosition;
     if(columnIndex > 1)
     {
          previousDragRightColumnPosition = previousDragLeftColumnPosition + DRAG_WIDTH;
     }
     else
     {
          previousDragRightColumnPosition = previousDragLeftColumnPosition;
     }
     
     var distanceFromMouseToPreviousColumn = _xMousePosition - (previousDragRightColumnPosition);
     var dragColumnLeftPosition = 0;
     
     if(distanceFromMouseToPreviousColumn < MINIMUM_ALLOWED_WIDTH)
     {
      _columnWidthSettings[columnIndex] = MINIMUM_ALLOWED_WIDTH;
      dragColumnLeftPosition = previousDragLeftColumnPosition + MINIMUM_ALLOWED_WIDTH;
     }
     else
     {
      _columnWidthSettings[columnIndex] = distanceFromMouseToPreviousColumn;
      dragColumnLeftPosition = _xMousePosition;
     }

     currentContentColumn.style.width = (_columnWidthSettings[columnIndex]) + "px";
     currentDragColumn.style.left = dragColumnLeftPosition + "px";
     currentDragColumn.style.width = DRAG_WIDTH + "px";

     
     for(iteration=(columnIndex+1); iteration<_columnWidthSettings.length; iteration++)
     {
          var nextDragColumn = document.getElementById("DragColumn_" + iteration);
          var nextContentColumn = document.getElementById("ContentColumn_" + iteration);
          
          nextContentColumn.style.left = (dragColumnLeftPosition + DRAG_WIDTH) + "px";
          nextContentColumn.style.width = _columnWidthSettings[iteration] + "px";
          nextDragColumn.style.left = (dragColumnLeftPosition + DRAG_WIDTH + _columnWidthSettings[iteration]) + "px";
          nextDragColumn.style.width = DRAG_WIDTH + "px";
          
          dragColumnLeftPosition += DRAG_WIDTH + _columnWidthSettings[iteration];
     }
     
}

var recursiveFunctionCall = "ChangeColumnWidth('"+columnIndex+"')";

if(_mouseButtonDown)
{
     window.setTimeout(recursiveFunctionCall, ONE_MILLISECOND);
}
}


// CUSTOMIZABLE LAYOUT SETTINGS - FEEL FREE TO MODIFY THESE.
var MINIMUM_ALLOWED_WIDTH = 30;
var MINIMUM_ALLOWED_HEIGHT = 30;
var TABLE_LEFT = 25;
var TABLE_TOP = 25;
var TABLE_HEIGHT = 500;
var DRAG_WIDTH = 10;
var _columnWidthSettings = new Array(0,200,300,200);
</script>
</head>


<body>

<div id="DragColumn_0"></div>
<div id="ContentColumn_1"></div>
<div id="DragColumn_1"></div>
<div id="ContentColumn_2"></div>
<div id="DragColumn_2"></div>
<div id="ContentColumn_3"></div>
<div id="DragColumn_3"></div>

</body>
</html>