在MS CRM 2011上开发JScript脚本的一些小技巧
MS CRM 2011中,客户端扩展所涉及的JScript脚本已经不是通过表单编辑器来直接输入了,而是将脚本库放置于Web Resource中了。有关如何使用Web Resource来存储脚本,以及在表单编辑器中对客户端扩展添加脚本库连接的内容,可以参看我之前的文章,链接地址http://www.cnblogs.com/StoneGarden/archive/2010/12/10/1902201.html。
本文将介绍两个我自己开发过程中的小技巧,以能够为各位同学带来一些借鉴吧。
第一个技巧,令JScript脚本资源具有层次。
在介绍之前,让我们先看看MS CRM系统是如何使用我们上传的JScript脚本资源的。当表单中引入某个JScript脚本资源时,系统在渲染界面时,会将相关的脚本资源以script标签的形式写入表单的html代码中。如下图的样例所示,我在实体new_test的表单中使用了new_testEntity.js以及new_include_script.js两个脚本资源,那么在页面的HTML代码中,可以找到这两个脚本资源所对应的script标签,如红色区域所示。
由图中可见,MS CRM系统将脚本资源填入了表单的HTML代码中的格式如下所示:
<script src=”/<组织唯一名称>/<随机数>/WebResources/<脚本资源名称>” type=”text/javascript”></script>
由这种格式可见,系统利用脚本资源的名称作为src属性的一个组成部分。src属性中的每一个“/”,代表了网站中的一个文件夹。考虑到脚本资源的名称中,允许存在“/”——形如”new_scripts/mytest.js”是合法的脚本资源名称。以此方式命名脚本资源,较之不使用“/”作为JScript资源名称的一部分,将使得src属性值中多出一个“/”,而在通常意义上来讲,两个“/”之间的内容代表了CRM站点对应的文件系统中的一个文件夹。同时,一个文件夹中的内容在逻辑语义上是属于同一类别的内容,例如_imgs文件夹下面存放的是图片信息,code下面存放的是代码文件等等。所以,使用“/”作为资源名称的一部分,就为从逻辑上面区分JScript资源,做出了一定的标识。
此外,如果将同一类别的脚本资源使用以“<类别>/<具体功能>.js”进行命名,在浏览网络资源列表时,一目了然,如下图所示。
从图中可见,类别为“验证”validation的两个脚本资源分别完成“验证整数”和“验证浮点数”功能,我将这两个JScript脚本分别命名为new_validation/validInt.js以及new_validation/validFloat.js,使用如此命名,在浏览脚本资源的时候,可以很容易的看到,这两个脚本属于同一个分类——验证输入数据,只不过被验证的数据类型不同。
上面说的是利用资源名称,显示层次的小技巧,简而言之,就是在资源名称中加入“/”,以分割不同的类别。
下面来介绍另一个小技巧,减少Jscript脚本资源发布次数的小技巧。
第二个技巧,减少Jscript脚本资源发布次数。
其实这已经不是什么新鲜的技巧了,在ms crm 4.0的时候,就已经使用过了,我也是新瓶装老醋,说一下在CRM 2011上面使用该技巧的方法。
这个技巧的出现的原因在于,每次修改了JScript资源之后,都需要重新发布,否则,修改是不会生效的,不知道各位同学是什么感受了,反正我是很烦这样子频繁修改、发布、修改、发布。
有没有什么好方法呢?使用物理文件,因为CRM网站上的文件发生改变后,IIS是会自动更新其内存中的该文件版本的,从而在客户端请求时,将最新版本的文件发送给客户端。
我们现在说到的技巧就是,将表单事件和物理文件关联起来,令crm系统知道:当前的表单,依赖于哪些文件。
实现的原理是,书写javascript代码,在html的head部分,添加一个script标记,在其中引用我们放在网站目录下的jscript文件。如此,在调试的时候,直接修改该物理文件即可,而不必每次都去修改JScript资源文件,然后再发布。
具体做法如下,首先创建一个jscript脚本资源,用于创建script标记,代码如下:
function IncludeScript(src)
{
var head = document.getElementsByTagName("HEAD")[0];
var script = document.createElement("script");
script.type = "text/javascript";
script.language = "javascript";
script.src = src;
head.appendChild(script);
}
将该资源命名为:new_include_script.js,效果如下图:
发布该资源。
根据需要进行客户端扩展的功能命名一个JScript脚本,我的样例中,命名为new_testEntity.js——因为是要在实体new_test上面进行客户端扩展,所以使用了实体名称作为JScript脚本资源的名称了。而new_testEntity.js资源中的脚本代码就一行:
IncludeScript("/new_test/test.js");
其中IncludeScript函数是在new_include_script.js中定义的。而new_scripts/test.js文件,是需要在crm站点的根目录下创建名为“new_scripts”的文件夹,并在该文件夹中创建test.js文件。如下图所示。
之所以要创建一个文件夹,而不是放在根目录下,是为了维护的方便。
根据具体需要,在test.js中书写JScript代码,例如书写一段代码,根据字段new_option1的选择项,确定new_option2字段的值和状态。
function SetFieldReadOnly() {
try {
alert(“这是物理文件”);
if (Xrm.Page.getAttribute("new_option1").getSelectedOption().text == "1") {
Xrm.Page.getControl("new_option2").setDisabled(true); // Disabled
Xrm.Page.getAttribute("new_option2").setValue(100000001);
Xrm.Page.getAttribute("new_option2").setSubmitMode("always");
}
else {
Xrm.Page.getControl("new_option2").setDisabled(false); // Enabled
}
}
catch (e) {
alert(e.message);
}
}
打开需要编写客户端扩展的表单设计器,选择new_option1字段,点击Ribbon工具条的“更改属性”按钮,系统弹出“字段属性”对话框,选择“事件”页签,在“窗体库”部分,添加对脚本资源“new_include_script.js”以及脚本资源“new_testEntity.js”的引用。如下图所示。
接下来,设置该字段的事件处理程序。点击事件处理程序部分的“添加”按钮,系统弹出“处理程序属性”对话框,在对话框的“函数”文本框处输入在test.js文件中撰写的函数的名称SetFieldReadOnly作为事件处理函数,点击确定按钮。如下图所示。
如此,完成new_option1字段的onchange事件的扩展,发布后。进入new_test实体的表单,执行的时候,会弹出一个alert对话框,如果需要取消该对话框的显示,直接修改crm站点new_scripts目录中的test.js文件即可。如果是使用标准的JScript资源的方式,那么每次修改后,都要重新发布该资源,费时费力。
当调试、修改完成后,用test.js文件中的代码覆盖new_testEntity.js资源中的代码。并在表单设计器中,取消对new_include_script.js资源的引用。