開源工作流引擎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';

 

 

 

  研究不深,主要解決方法都是治標不治本、治皮不治肉,歡迎探討!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM