开源工作流引擎web设计器Activiti Modeler 5.17.0 与IE11的兼容性探究

一、源码下载

  Activiti官网:http://activiti.org/

  github:https://github.com/Activiti/Activiti 

  官网上下载的是lib库文件、文档和网站样例,推荐使用maven管理项目,可以不用下载库文件,直接下载源码,github上源码已经是5.18.0,但是官方还没有发布,从以下网址找到5.17.0的source code下载链接下载即可:https://github.com/Activiti/Activiti/releases,大小为20.1M。解压后目录如下:

二、导入eclipse

  官方提供了一个名为activiti-explorer.war的web演示项目,可以直接部署到tomcat里运行,在源码文件夹的moudules下,有一个activiti-webapps-explorer2文件夹,这就是activiti-explorer.war的项目目录,项目采用maven管理,不熟悉maven的建议先学习一下。

  在eclipse中选择 import->exit maven projects,选择activiti-wepapps-explorer2目录,导入pom.xml,等待工程自动构建,完成后会有几个错误,都是xml格式错误,不影响运行。我是在jdk1.8,tomcat8中部署的web项目。

  在chrome下,使用kermit:kermit登陆系统,选择流程-->流程设计工作区-->新建模型,创建一个新的model,发现web设计器打不开,发现可能是代码中路径设置问题,这不是我们要解决的问题,简单处理,eclipse中右键工程,Properties--web project setting--context root , 名称改为activiti-explorer,重新部署工程(在server--tomcat8中删除工程,重新运行部署),登陆,新建model,打开模型设计器:

三、IE测试

  在ie11中测试web流程设计器,初步发现以下几个bug:

1. 网页出现internal error错误

  后期要移植到自己的项目中,不会使用这些网页源码,这不是主要矛盾,打开ie兼容性设置,把localhost加入即可。

2.使用路径path后model保存错误

  modeler作图使用svg(可缩放矢量图形),相关教程:http://www.w3school.com.cn/svg/,在ie中如果使用了箭头(即svg中的path元素),则model保存不成功,提示错误”Unexpected error: could not save model”,eclipse中提示:元素类型 "path" 必须后跟属性规范 ">" 或 "/>"。。在ie  F12开启调试模式,与chrome对比发现是因为modeler.html中的path的marker-start和marker-end属性值多了引号,导致在保存时path出错。

IE:

url("#sid-7278F570-B74E-4EE6-A21A-52A3B3BF3C26end")  url("#sid-7278F570-B74E-4EE6-A21A-52A3B3BF3C26start")

<path xmlns="http://www.w3.org/2000/svg" id="sid-7278F570-B74E-4EE6-A21A-52A3B3BF3C26_1" fill="none" marker-end="url(&quot;#sid-7278F570-B74E-4EE6-A21A-52A3B3BF3C26end&quot;)" marker-start="url(&quot;#sid-7278F570-B74E-4EE6-A21A-52A3B3BF3C26start&quot;)" stroke="#585858" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M 355.391 135 L 399.375 135" />

chrome:

<path id="sid-CB6F9DD4-D150-4072-8EF6-75B5AE54E9BF_1" d="M210.609375 135L254.15625 135 " stroke="#585858" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" marker-start="url(#sid-CB6F9DD4-D150-4072-8EF6-75B5AE54E9BFstart)" marker-end="url(#sid-CB6F9DD4-D150-4072-8EF6-75B5AE54E9BFend)"></path>

  进一步跟踪发现,在oryx.debug.js中有如下代码:

                    markerUrl = markerUrl.strip();
                    markerUrl = markerUrl.replace(/^url\(#/, '');
                    
                    var markerStartId = this.getValidMarkerId(markerUrl);
                    path.setAttributeNS(null, "marker-start", "url(#" + markerStartId + ")");
                    
                    markersByThisPath.push(this._markers[markerStartId]);

chrome中的setAttributeNS函数不会对url()做特殊处理,而IE中会对url()中的字符用引号包裹,y!在此设置断点重新画一个path后,发现引号删不掉(nodevalue无法修改为无引号),把值设置为url(AAAA)会自动变为url("AAAA")!setAttributeNS地址:http://www.w3school.com.cn/xmldom/met_element_setattributens.asp

     

而且这个js显然也有考虑到了这种情况,replace考虑到了ie,但是保存为什么不考虑啊。

    getValidMarkerId: function(markerUrl) {
        if(markerUrl.indexOf("url(\"#") >= 0) {
            // Fix for IE9, additional quotes are added to the <id
            var rawId = markerUrl.replace(/^url\(\"#/, "").replace(/\"\)$/, '');
            return this.id + rawId;
          } else {
            markerUrl = markerUrl.replace(/^url\(#/, '');
            return this.id.concat(markerUrl.replace(/\)$/, ''));
          }
    },

最简单的做法,我们也来字符串替换,在toolbar-default-actions.js中有如下函数:

$scope.save = function (successCallback) {

        if (!$scope.saveDialog.name || $scope.saveDialog.name.length == 0) {
            return;
        }

        // Indicator spinner image
        $scope.status = {
            loading: true
        };
        
        modelMetaData.name = $scope.saveDialog.name;
        modelMetaData.description = $scope.saveDialog.description;

        var json = $scope.editor.getJSON();
        json = JSON.stringify(json);
        
        var selection = $scope.editor.getSelection();
        $scope.editor.setSelection([]);
        
        // Get the serialized svg image source
        var svgClone = $scope.editor.getCanvas().getSVGRepresentation(true);
        $scope.editor.setSelection(selection);
        if ($scope.editor.getCanvas().properties["oryx-showstripableelements"] === false) {
            var stripOutArray = jQuery(svgClone).find(".stripable-element");
            for (var i = stripOutArray.length - 1; i >= 0; i--) {
                stripOutArray[i].remove();
            }
        }

        // Remove all forced stripable elements
        var stripOutArray = jQuery(svgClone).find(".stripable-element-force");
        for (var i = stripOutArray.length - 1; i >= 0; i--) {
            stripOutArray[i].remove();
        }

        // Parse dom to string
        var svgDOM = DataManager.serialize(svgClone);

        var params = {
            json_xml: json,
            svg_xml: svgDOM,
            name: $scope.saveDialog.name,
            description: $scope.saveDialog.description
        };

        // Update
        $http({    method: 'PUT',
            data: params,
            ignoreErrors: true,
            headers: {'Accept': 'application/json',
                      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
            transformRequest: function (obj) {
                var str = [];
                for (var p in obj) {
                    str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                }
                return str.join("&");
            },
            url: KISBPM.URL.putModel(modelMetaData.modelId)})

            .success(function (data, status, headers, config) {
                $scope.editor.handleEvents({
                    type: ORYX.CONFIG.EVENT_SAVED
                });
                $scope.modelData.name = $scope.saveDialog.name;
                $scope.modelData.lastUpdated = data.lastUpdated;
                
                $scope.status.loading = false;
                $scope.$hide();

                // Fire event to all who is listening
                var saveEvent = {
                    type: KISBPM.eventBus.EVENT_TYPE_MODEL_SAVED,
                    model: params,
                    modelId: modelMetaData.modelId,
                    eventType: 'update-model'
                };
                KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_MODEL_SAVED, saveEvent);

                // Reset state
                $scope.error = undefined;
                $scope.status.loading = false;

                // Execute any callback
                if (successCallback) {
                    successCallback();
                }

            })
            .error(function (data, status, headers, config) {
                $scope.error = {};
                console.log('Something went wrong when updating the process model:' + JSON.stringify(data));
                $scope.status.loading = false;
            });
    };

  我们将svgDOM中的引号删除掉,然后ie清除缓存(重启?),maven清理工程(alt+F5),tomcat删除项目,重新部署运行,保存成功!

  // Parse dom to string
        var svgDOM = DataManager.serialize(svgClone);
        svgDOM = svgDOM.replace(/marker-start="url\("#/g,"marker-start=\"url(#").replace(/start"\)"/g,"start\)\"");
        svgDOM = svgDOM.replace(/marker-mid="url\("#/g,"marker-mid=\"url(#").replace(/mid"\)"/g,"mid\)\"");
        svgDOM = svgDOM.replace(/marker-end="url\("#/g,"marker-end=\"url(#").replace(/end"\)"/g,"end\)\"");
        

3. 保存后再点击编辑模型,仍然显示保存前的模型图

  初步诊断为IE对json做了缓存,可以在目录C:\Users\{Your name}\AppData\Local\Microsoft\Windows\Temporary Internet Files下看到json的缓存,只需在以后的项目移植过程中调用json时设置不取缓存即可。对app.js中的AngularJS方法添加html头信息即可:

 1             /* Helper method to fetch model from server (always needed) */
 2             function fetchModel(modelId) {
 3 
 4                 var modelUrl = KISBPM.URL.getModel(modelId);
 5 
 6                 $http({method: 'GET', url: modelUrl, headers: {'Pragma': 'no-cache','Cache-Control':'no-cache'}}).
 7                     success(function (data, status, headers, config) {
 8                         $rootScope.editor = new ORYX.Editor(data);
 9                         $rootScope.modelData = angular.fromJson(data);
10                         $rootScope.editorFactory.resolve();
11                     }).
12                     error(function (data, status, headers, config) {
13                       console.log('Error loading model with id ' + modelId + ' ' + data);
14                     });
15             }

4.某些情况下path的箭头消失

情况一:编辑模型,在未做任何操作时点击作图面板空白处;

情况二:完全使用快捷方式生成model后(即除start使用拖拽外,其他组件通过父组件的右下角点击生成),在未做任何操作时点击作图面板空白处;

  这只是显示的问题,若拖动任意组件或者点击path后,箭头会恢复显现。这是ui的渲染问题,可能由于渲染顺序或者透明度吧,这个问题想要解决需要十分熟悉svg作图,可是我不太懂啊。还有一个思路就是移动某个节点,让页面重新渲染,比如把start左移10再右移10。

 

  我..我..我找了一年!终于让我找到了,oryx.debug.js的21684行,在MouseDown事件处理中,有设置鼠标指针样式的代码,在IE下设置会导致path显示bug,不知道为什么,而且删掉后也没什么影响啊貌似。。。大概吧。。。总之添加个判断,在IE下不执行。

1         if (!(!!window.ActiveXObject || "ActiveXObject" in window))
2             document.body.style.cursor = 'default';

 

 

 

  研究不深,主要解决方法都是治标不治本、治皮不治肉,欢迎探讨!

posted @ 2015-06-10 23:00  華胥亡靈  阅读(23856)  评论(3编辑  收藏  举报