Friday, March 20, 2009

Creating a Network Path Text Control




Dynamics supports several types of text fields. One type which is not available in the current version is a text field that supports a UNC path (\\) or a network drive (Y:) to a shared folder on the server or on the user local machine.

The following example converts a regular text field into a network path control. The control works in conjunction with an Explorer page which contains an IFRAME to the actual network share.

The Explorer(.aspx) should be deployed in the ISV folder. When the user double clicks on the field value a window is opened pointing to the shared folder. The control also provides a comfortable API for managing extra query parameters, changing control style, changing explorer window features and setting an initial network path. The last can be a handy feature if you require the explorer to point to an account personal folder within a shared file system tree.

Here is the Explorer.aspx implementation:


<%@ Page Language="C#" %>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Dynamics File Explorer</title>
<style>
.header
{
background-color:#639ace;
padding-left:10px;
color:White;
font-size:x-large;
font-family:arial;
height:30px;
}

.iframe
{
border:1px solid #94b2de;
height:100%;
width:100%;
}

body
{
margin:0px;
border:0px solid;
}
</style>
</head>
<body scroll="no">
<table border="0" cellpadding="1" cellspacing="0" style="width:100%;height:100%">
<tr>
<td class="header">File Explorer</td>
</tr>
<tr>
<td>
<iframe class="iframe" src="<%=Request["path"] %>"></iframe>
</td>
</tr>
</table>
</body>
</html>


The following script should be added to the entity onload event:


// JScript File
function OnCrmPageLoad()
{
var networkPath = new NetworkPath("fax");
//Example Add query string parameter
networkPath.Params.Add("test","1");
//Example Remove query string parameter
networkPath.Params.Remove("test");
//Example change control default style
networkPath.Style.Add("color","red");
//Transform the text field into a network path field
networkPath.Transform();
}

function NetworkPath(baseControlId)
{
nk = this;
nk.ID = baseControlId;
nk.Control = document.all[nk.ID];
/* Default Path */
nk.Path = "\\\\127.0.0.1\\Files"; //default path
nk.Window = null;
/* File Explorer Features (window.open)*/
nk.Features = new Dictionary(",","=");
/* If you wish to extend the Explorer.aspx and add more querystring parameters */
nk.Params = new Dictionary("&","=");
/* Network path control additional styling rules */
nk.Style = new Dictionary(";",":");

nk.Transform = function()
{
if (nk.Control)
{
/* Assign default path if control value is empty */
if (nk.Control.DataValue == null)
{
nk.Control.DataValue = nk.Path;
}

nk.Control.title = "Double Click to Open Network Explorer";
/* Default Window Settings */
if (!nk.Features.Exist("width"))
{
nk.Features.Add("width",700);
}
if (!nk.Features.Exist("height"))
{
nk.Features.Add("height",400);
}
if (!nk.Features.Exist("resize"))
{
nk.Features.Add("resize","yes");
}
if (!nk.Features.Exist("toolbar"))
{
nk.Features.Add("toolbar","no");
}
if (!nk.Features.Exist("menubar"))
{
nk.Features.Add("menubar","no");
}
if (!nk.Features.Exist("titlebar"))
{
nk.Features.Add("titlebar","no");
}
/* Attach validation to change and save events */
nk.Control.attachEvent( "onchange" , nk.Validate );
crmForm.attachEvent( "onsave" , nk.Validate );

/* Adjust control style */
nk.Style.Add("text-decoration","underline");
if (!nk.Style.Exist("color"))
{
nk.Style.Add("color","blue");
}
nk.Style.Add("cursor","hand");
nk.Control.style.cssText += ";" + nk.Style.ToString();

/* Add double click functionality */
nk.Control.ondblclick = nk.Open;
}
}

nk.Validate = function()
{
if (nk.Control.DataValue == null)
{
return true;
}

/* validate \\ unc path or a netwrok drive Y: */
var regex = new RegExp("^(\\\\|[a-zA-Z]:)");
if (!regex.exec(nk.Control.DataValue))
{
alert("Invalid Network Path or Drive");
return (event.returnValue = false);
}

return true;
}

nk.Open = function()
{
if (nk.Control.DataValue != null)
{
nk.Window = window.open( SERVER_URL + "/isv/explorer.aspx?path=" + nk.Control.DataValue + nk.Params.ToString() , "" , nk.Features.ToString());
}
}

nk.Close = function()
{
nk.Window.close();
}

/* Key Value Pair Collection */
function Dictionary(sep,delim)
{
this.list = [];
this.Seperator = sep;
this.Delimiter = delim

this.Add = function(key , value)
{
this.list[key] = value;
}

this.Remove = function(key)
{
this.list[key] = "";
}

this.Exist = function(key)
{
return this.list[key] != null && this.list[key] != "";
}

this.ToString = function()
{
var result = new StringBuilder();
result.Append(this.Seperator);
for(var key in this.list)
{
if (this.list[key]!="")
{
result.Append(key).Append(this.Delimiter);
result.Append(this.list[key]).Append(this.Seperator);
}
}
var tmp = result.ToString();
return tmp.substring(0,tmp.length-1);
}
}

function StringBuilder()
{
this.data = [];

this.Append = function(text)
{
this.data[this.data.length] = text;
return this;
}

this.Reset = function()
{
this.data = [];
}

this.ToString = function()
{
return this.data.join("");
}
}
}

OnCrmPageLoad();

7 comments:

Anonymous said...

nice work

Nick Doelman said...

Awesome! I have been looking for something like this for a while.

I added and CRM form iframe called "IFRAME_docs" and replaced the "window open" command with:

crmForm.all.IFRAME_docs.src = SERVER_URL + "/isv/explorer.aspx?path=" + nk.Control.DataValue + nk.Params.ToString() , "" , nk.Features.ToString();


And I get my file listing right on the form. I thought others might find that useful.

I also noticed (and assume) that it can only be used with URL pathnames and not drive letters and the folders must be shared?

Cheers!
Nick

Andreas said...

It's but I have a question.

When I double click the navigator open. And then I choose a other folder. But the crm system don't save the new folder. How does it work?

Anonymous said...

can someone please give me a quick step by step on what i need to do with the form to get this to work?

Paul said...

This is amazing! I am not a programmer by any means and I need a bit of help if you can please assist.

I want to create a network folder when a new case is saved. So after one of our employees opens and saves a case the network folder is created automatically using that same case number. If would be great if I could also get the network folder to open after saving the case.

Like I said I am not a programmer but rather a network guy and got stuck with doing CRM development work. If you can be as detailed as possible that would help me out so much.

Paul said...

It might be easier if you email me pslager@lwgconsulting.com

Thanks again.

Anonymous said...

Text Control tutorial