一. 客户端代码开发工具
Openbravo3.0客户端代码开发是大量的javascript代码,CSS代码和极少量的html代码开发。我们是通过浏览器加载来查看客户端主要的javascript代码的,一般如下两个工具选择一个,Chrome Developers Tools和Firebug
二. smartclient源码整合入Openbravo项目
1. 到如下地址将smartclient源码下载下来: https://code.openbravo.com/erp/mods/org.openbravo.userinterface.smartclient.dev/,点击如下图的zip即可。
2. 将下载下来的smartclient源码,解压缩(注意先要重命名一下,名称太长,解压缩会报错)放到openbravo项目的modules文件夹下面,比如:G:\openbravo3.0\Openbravo-3.0MP11\modules。
3. 命令行窗口,切换到openbravo项目的顶层目录,比如:G:\openbravo3.0\Openbravo-3.0MP11。运行如下命令:ant smartbuild。
4. 编译成功之后,刷新在eclipse里面的openbravo项目,可以在modules文件夹下面看到smartclient module。今后直接从这里查看smartclient的源码。(可以使用Ctrl+Shift+r命令快速打开某一个源文件,比如FormItem.js)
三. 客户端获取没有压缩和模糊的JS代码
openbravo会自动压缩javascript代码,为了减轻客户端的加载压力。但是,这回让客户端调试代码更加困难,那么如何获取没有压缩的javascript代码。
openbravo如果发现这个模块不是开发状态,就会压缩javascript代码。但是,如果是开发态就不会了。通常我们将如下几个模块设置成处于开发状态:org.openbravo.client.kernel,org.openbravo.client.application,org.openbravo.userinterface.selector
smartclient源码在加载到客户端的时候,通常会被压缩。但是,客户端调试的时候,非常需要看得见smartclient的源码。为了能够看到,需要安装smartclient模块,也就是第二步所说的。第二步做完之后,启动服务,浏览器进入模块管理页签,将smartclient模块修改成处于开发状态,然后重启服务。
客户端如何调试代码,通过chrome浏览器打开某一个页面之后,打开chrome开发人员工具,点击scripts查看javascript代码,下拉框找到一个名词很长的javascript代码,比如:27c45aef548fedad34ife42.js. 这个js代码包含了整个压缩了的js代码。需要注意几点:
1. 这个javascript名称是动态生成的,内容变化,名称就会变化,浏览器就会重新加载。
2. 如果这个文件是被压缩的,请查看如上说的那三个通常说要设置成开发态的模块是否设置了。
3. 这个文件不包含smartclient的源码。
找到这个js文件之后,在上面代码搜索里面输入this.messageBar = isc.OBMessageBar.create ,定位之后,在左边数据行号的地方点击右键就可以加断点了,然后随便打开一个窗口,就会触发这个断点。
四. 添加javascript到openbravo系统
javascript加入到openbravo系统可以通过如下方式:
1. 静态的javascript文件必须放在它所在模块的如下目录:web/[modulepackage]/js
2. javascript必须要注册通过java语言,比如:
globalResources.add(createStaticResource( "web/org.openbravo.client.application.examples/js/example-view-component.js", true));
五. openbravo客户端javascriptAPI介绍
当添加新的实例或者类的时候,需要遵守如下协议:
1. 所有的全局数据必须加载全局对象OB里面。
2. 所有CSS样式命名必须以OB打头。
3. 所有的smartclient类命名必须以OB打头。
在这一部分,我们将探讨OB对象里面的功能函数。
1. OB.Application
它包含服务器端的一些基本信息,比如采用的是那种语言,基本访问路径是什么,系统版本之类的。见下图:
2. OB.User
包含当前登录用户的相关信息
3. OB.Constants
包含了在整个系统运作过程中会用到的常量。
4. OB.Datasource
提供标准和定制的数据源,它提供2个方法,create和get。
get方法在获取数据源的时候,会先判断在客户端是否已经缓存了,如果缓存了直接返回。如果没有,则发生一个请求到服务端,要求服务端生成一个数据源返回。需要注意的是,这个get方法是异步的:
// ** {{{ OB.Datasource.get(dataSourceId, target, dsFieldName) }}} ** // // Retrieves a datasource from the server. The return from the server is a // javascript string which is evaluated. This string creates a datasource. The // datasource // object is set in a field of the target (if the target parameter is set). This // is done asynchronously. // // The method returns the datasourceid. // // Parameters: // * {{{dataSourceId}}}: the id or name of the datasource // * {{{target}}}: the target object which needs the datasource // * {{{dsFieldName}}}: the field name to set in the target object. // * {{{doNew}}}: if set to true then a new datasource is created // If not set then setDataSource or optionDataSource are used. // OB.Datasource.get = function(/* String */dataSourceId, /* Object */ target, /* String */dsFieldName, /*Boolean*/ doNew) { ... }
create方法不会调动服务器端来生成数据源,而是在客户端自己生成,利用传过来的参数
// ** {{{ OB.Datasource.create}}} ** // Performs a last check if the datasource was already registered before // actually creating it, prevents re-creating datasources when multiple // async requests are done for the same datasource. // Parameters: // * {{{dsProperties}}}: the properties of the datasource which needs to be // created. OB.Datasource.create = function(/* Object */dsProperties) {
OB.Datasource通过isc.OBRestDataSource来创建数据源,isc.OBRestDataSource继承自SmartClient RestDatasource方法。
5. OB.Format
负责当前用户全局日期,数字的格式设置, 特殊字段的设置在format.xml里面设置,
6. OB.I18N
改对象提供一个getLabel方法,用于获取一个翻译过的提示信息,当用户加载一个窗口的时候,系统会自动调用这个方法将提示信息下载下来。方便今后使用。
7. OB.PropertyStore
负责获取和设置一些属性值。
get方法,可以返回一个特定窗口的某一个属性值。
dataPageSizeaux = OB.PropertyStore.get('dataPageSize',this.view.windowId);
set方法, function(propertyName, value, windowId, noSetInServer, setAsSystem):设置某一个属性值。如果不需要设置服务器端这个属性的值,noSetInServer为true. 如果要在系统中都设置,setAsSystem为true.
OB.PropertyStore.set('OBUIAPP_GridConfiguration', result, this.windowId);
OB.PropertyStore可以加监听, 值改变的时候会通知监听对象。
8. OB.RemoteCallManager
负责调用服务端的方法,提供一个Call方法,有如下参数:
actionName:接收请求处理的类名。
data:请求的表体数据
requestParams:请求的参数
callback:请求返回时,调用的方法
callContext
9. OB.ViewManager
管理我们打开的所有页签,像回退,刷新页面也属于它的管辖范围。它有一个比较重要的方法是打开一个页签,openView(viewName, params), viewName: 将要创建“视图”的名称。params: 创建“视图”需要的一些数据。页签也就是视图,有一个属性showItSelf,如果设置成true,那么就是弹出窗口。如果false,那么就会在页签里面打开视图。
10.OB.Utilities.Action
用来定义一系列动作执行方法,定义方法如下:
OB.Utilities.Action.set('showAlert', function (paramObj) { alert(paramObj.text); });
执行方法如下:
OB.Utilities.Action.execute('showAlert', {'text': 'This is just an example'});
executeJSON方法可以顺序执行多个方法,如下:
OB.Utilities.Action.executeJSON([{'showAlert': {'text': 'This is the first alert'}}, {'showAlert': {'text': 'This is the second alert'}}])
当调用executeJSON方法的时候,会生成一个线程,全程监控执行过程。这个线程可以中止执行,暂停执行和继续执行。比如:
OB.Utilities.Action.set('confirmDialog', function(paramObj) { var text = 'Hello ' + paramObj.name + ', do you want to continue with the thread?'; if (!confirm(text)) { OB.Utilities.Action.cancelThread(paramObj.threadId); } }); OB.Utilities.Action.set('promptDialog', function(paramObj) { var text = ''; if (paramObj.value) { text += 'You have introduced: ' + paramObj.value + '\n'; } text += 'Please, introduce here a 0 in order to continue' paramObj.value = prompt(text); if (paramObj.value === '0') { OB.Utilities.Action.resumeThread(paramObj.threadId); } else { OB.Utilities.Action.pauseThread(paramObj.threadId); OB.Utilities.Action.execute('promptDialog', paramObj, 100); } }); OB.Utilities.Action.set('alertDialog', function(paramObj) { var text = 'You have finished the thread!\nBye ' + paramObj.name; alert(text); }); OB.Utilities.Action.executeJSON([ { 'confirmDialog': { name: 'John Smith' } },{ 'promptDialog': { } },{ 'alertDialog': { name: 'John Smith' } } ]);
11. OB.Utilities.Number
提供几个方法用来格式化数字,比如:
OB.Utilities.Number.roundJSNumber(num, dec)将数字num按照dec设置的精度处理。
OB.Utilities.Number.OBMaskedToJS(numberStr, decSeparator, groupSeparator):将OB中格式的数字转换成JS中的格式。
OB.Utilities.Number.JSToOBMasked(number, maskNumeric, decSeparator, groupSeparator, groupInterval):将JS格式的数字转换成OB中的格式。
12. OB.Utilities.Date
格式化日期,比如:
OB.Utilities.Date.OBToJS(OBDate, dateFormat):将OB中date的格式转换成JS中的格式
OB.Utilities.Date.JSToOB(SDate, dateFormat): 反之。
13. OBGrid
OBGrid是openbravo中的表格定义类,如果你要实现自己的表格类,必须继承它,以保证你的表格跟系统中的表格风格一样。
14. Openbravo Window Components
Openbravo里面的一个窗口是由多个页签组成,每一个页签有编辑模式和表格模式,另外,还有工具栏和消息框。下面具体介绍一下这些信息。
OBStandardWindow:窗口对象
Openbravo里面的窗口是通过实例化窗口对象创建的,窗口对象里面的页签是通过实例化OBStandardView创建的。每一个页签对象里面包含了多个子页签,每一个页签通过实例化OBViewGrid来实现表格模式和实例化OBViewForm来实现编辑模式。窗口对象一般包含以下属性:
1. WindowId:窗口存储在数据库中对应的id
2. view:根页签
3. views:窗口中所有的页签
OBStandardView:页签对象
页签对象包含以下一些信息:
a form(一个编辑页面),a grid(一个表格页面),a tab set with tabs(一个包含页签的页签集合),a message bar(消息显示条),a toolbar(工具栏)
OBStandardView有如下属性:
tabId:tab ID
tabTitle:页签的标题
StandardWindow:一个返回所属窗口的链接
childTabSet:所有子页签集合
parentView:一个返回父页签的链接,如果是子页签
parentTabSet:一个返回父页签所有子页签集合的链接
toolBar:本页签OBToolBar实例化对象
messageBar:消息框
viewForm:编辑页面
viewGrid:列表页面
dataSource:为编辑页面和列表页面提供数据
isActiveView:一个方法,如果页签是活动的返回true
OBViewGrid:表格页面
OBViewGrid是smartclient ListGrid的子类,除开listGrid的属性外,它还有额外的属性:
setItemValue(item,value)方法:为item设值,并触发onChange事件。
getSelectedRecord:得到当前选中行
getEditForm:当编辑表格某一行的时候,返回当前编辑的一行信息
getEditRow:得到当前编辑的行
setValue(item,value),设置item的值,不触发onChange事件
OBViewForm:编辑页面
OBViewForm是DynamicForm的一个子类,有如下重要属性:
view:指向所属页签
gird:
hasChanged:如果至少有一个字段的值改变,则为ture
isNew:the form是否是为了新增一条记录而打开
OBMessageBar:提示信息框
给予用户一些提示信息,比如警告,错误等等。它有如下方法:
setType(type):设置消息的类型,不同类型的消息颜色和图标不同,type有如下几种: isc.OBMessageBar.TYPE_SUCCESS,TYPE_ERROR,TYPE_WARNING,TYPE_INFO.
setText(title,text):设置提示信息框的内容,和标题,如果标题为空,则设置为默认的
setMessage(type,title,text):上述两方法结合,同时会显示消息框
hide/show:隐藏或者显示消息框。
OBToolBar:工具栏
窗口中的每一个页签都有一个工具栏,但是窗口只显示一个工具栏。当前活动的页签,的工具栏才会显示,如果不是活动页签,它所属的工具栏就会隐藏。