如果引用或轉貼,麻煩註明出處與本網誌連結,否則視為侵權。
顯示具有 Javascript 標籤的文章。 顯示所有文章
顯示具有 Javascript 標籤的文章。 顯示所有文章

2021年9月29日

網頁設計 : 如何設計一個表頭固定但內容可以捲動的表格

作者: Fred F.M. Wang (FW知識瑣記) 日期: 2021-9-29

網頁中如何設計一個表頭固定但內容可以捲動的表格


       要讓表格表頭固定,內容可以捲動,首先,table header(thead)與table body(tbody)必須各

自設定顯示方式為block(CSS設定 display: block;),但是,table header(thead)與table body

(tbody)各自設定為block時,表頭與內容的欄位寬度就無法對齊。因此,必須透過Javascript設定table header欄寬與table body的欄寬一致


==================================================

<style>

thead.fixedHeader {    display: block;    }

thead.fixedHeader tr th { padding: 4px 0px!important;    }

tbody.scrollContent {  

    display: block;    

    overflow: auto;    

}

</style>



<table id="itemtable">

    <thead id="itemheader" class="fixedHeader">

       <tr>

    ..

    </tr>

    </thead>


   <tbody id="itemcontent" class="scrollContent">

       <tr>

    ..

    </tr>

   </tbody>


=============================================

 <script type="text/javascript">

$( document ).ready(function () {

   // 設定捲動區域,區域底部不要超過視窗底部

    var content_y = get_offset_y("itemcontent"); // 取得table body畫面左上角的座標y位置

    var content_height = window.screen.height - content_y - 200;   // 設定table body的高     

    document.getElementById("itemcontent").style.height= content_height + "px"; 

   

  // 設定table header欄寬與table body的欄寬一致 by Fred

  var theader = document.getElementById("itemheader");

  var tbody = document.getElementById("itemcontent");

  row0 = theader.rows[0];  // table header row

  row1 = tbody.rows[0];     // table body 1st row   


  // 逐一設定table header每一欄欄寬等於table body每一欄的實際顯示寬度

  for (var j = 0; j < row1.cells.length; j++) {

      row0.cells[j].style.width = (row1.cells[j].offsetWidth - 1) + "px";  // offsetWidth:實際顯示

寬度,注意要減一,否則無法對齊

  }


/* 取得一個HTML元素在畫面中的位置(左上角的座標y位置) */

function get_offset_y(id) {

    var e = document.getElementById(id);

    var offset = {x:0,y:0};

    while (e)

    {

       offset.x += e.offsetLeft;

       offset.y += e.offsetTop;

       e = e.offsetParent;

    }


    if (document.documentElement && (document.documentElement.scrollTop 

|| document.documentElement.scrollLeft))    {

       offset.x -= document.documentElement.scrollLeft;

       offset.y -= document.documentElement.scrollTop;

    

  } else if (document.body && (document.body.scrollTop || document.body.scrollLeft))   {

       offset.x -= document.body.scrollLeft;

       offset.y -= document.body.scrollTop;

  

  } else if (window.pageXOffset || window.pageYOffset)   {

       offset.x -= window.pageXOffset;

       offset.y -= window.pageYOffset;

    }


    // alert(offset.x + '\n' + offset.y);    

    return offset.y

}

</script>

註: 取得一個HTML元素在畫面中的位置參考來源https://stackoverflow.com/questions/211703/is-it-possible-to-get-the-position-of-div-within-the-browser-viewport-not-withi

2021年7月4日

javascript流程圖繪製技術mxGraph (javascript程式庫)

作者: Fred F.M. Wang (FW知識瑣記) 日期:2021-7-3

前幾周完成的流程圖研究是使用flowcharty.js技術將儲存在資料庫的流程設定轉以流程圖顯示

出來。可以用於流程圖形化顯示與流程進度追蹤。但是,無法用於流程設計。


本周開始研究流程圖形化設計技術。找到一個不錯的程式庫mxGraph,以下是幾點mxGraph

的介紹敘述 : 

 "mxGraph是2005年開始開發,一個互動式的JavaScript HTML 5圖表程式庫。
mxGraph是一個完全客戶端(client side)程式庫,它使用 SVG 和 HTML來呈現您的模型。

例如,該程式庫被使用在 Draw.io。
mxGraph不使用第三方軟體,不需要插件,幾乎可以整合到任何框架中。 "

 

mxGraph包含一般流程圖,UML,BPMN等繪圖元件。

  




 

mxGraph網路資源 : 

1 mxGraph下載一

2 mxGraph下載二

3 mxGraph User Manual – JavaScript Client

4 mxGraph 用戶手冊中文 – JavaScript客戶端

5 mxGraph教程

6 mxGraph 入門例項教程 

7 mxGraph JavaScript範例  

8 mxgraph的艱難入門 

9 mxGraph-PHP - PHP backend model for mxGraph

10 mxGraph進階一 mxGraph教程-開發入門指南 

11 mxgraph進階二 mxgraph的初步介紹與開發入門 

12 mxgraph進階 三 Web繪圖——mxGraph項目實戰 精華篇 

13 mxgraph進階四 mxGraph再啟程

14 mxgraph進階五 搭建mxGraph簡單應用

     

我計畫修改其範例程式,整合進自己開發好的流程系統。

整合的概念如下:

建立新的流程的步驟 :

1 使用mxGraph Flowchart Editor繪製流程圖

2 儲存成xml格式檔案(using mxGraph API)

3 再將xml轉換成流程設定(結構化資料),並儲存在資料庫。


修改舊的流程的步驟 :

1. 讀取儲存在資料庫的流程設定,轉換成xml

2. 讀取xml到mxGraph Flowchart Editor上呈現成流程圖(using mxGraph API)

3. 使用mxGraph Flowchart Editor修改流程圖。

4. 儲存成xml格式檔案(using mxGraph API)

5. 再將xml轉換成流程設定(結構化資料),並儲存在資料庫。



今天有一些突破, 已經可以將流程圖編輯器繪製完的流程圖(如上圖)以xml方式儲存下來, 也可

以讀取儲存好的xml檔, 再以流程圖的方式呈顯在流程圖編輯器, 進行流程圖修改。再下來只

要可以將xml轉換成流程設定(結構化資料), 儲存到資料庫就可以了。

 

圖形範例如下 :


 

2021年6月12日

BPM系統如何使用jQuery動態顯示流程圖之二(含範例) --- 使用flowcharty.js

作者: Fred F.M. Wang (FW知識瑣記) 日期:2021/6/12

前一篇 BPM系統如何使用jQuery動態顯示流程圖含範例 --- 使用flowchart.js

由前一篇文章提出flowchart.js的三個缺點

1 流程圖繪製比較不具彈性,流程線只能選擇向右,向下與向左,不能決定每一條線繪製的

長短與位置,向左方繪製的流程線繪製會有問題,如下圖

   

2 決策節點只能有yes, no兩種選項,不能有更多重的選項。無法解決三種或三種以上條件的流

程,例如: 三種請購單類型分別走三種不同的審核流程。


3 流程線無法個別設定要顯示的文字。

 

由於這幾個缺點,我決定不使用 flowchart.js作為我後續開發使用的程式庫。

嘗試了其他jQuery程式庫,如flowSVG.js 與 flowcharty.js

flowSVG.js似乎沒辦法做到退回流程,也就是如果特定審核關卡如果退回,需要有一條退回到前一關卡的線,怎樣試都畫不出來,因此被我淘汰掉了。下面是flowSVG的範例圖。

 

嘗試了flowcharty.js覺得還不錯,沒有上面flowchart.js與flowSVG.js的缺點,可以提供給大家參考。

下面是flowcharty.js的優點 : 

1 網格方式布局流程元件, 增加dummy節點,讓流程圖繪製更具彈性,流程線可以控制

繪製的方向與位置。

2 決策點可以有超過兩種以上的選項。

3 流程線可以個別設定要顯示的文字。

 

唯一不如 flowchart.js的是flowcharty.js不提供流程圖元件點擊連結與顯示訊息。

flowcharty.js GitHub網址 :https://github.com/atago0129/flowcharty

簡單說明 : https://www.cssscript.com/svg-flowchart-d3-flowcharty/ 

demo : https://www.cssscript.com/demo/svg-flowchart-d3-flowcharty/

我由官方範俐改寫為一個簡單的請購單審核流程 ,如下: 

 

確實可以達到我的需要。

下面是我寫的範例內容 :

 
<svg width="960" height="720"></svg>
<script src="//d3js.org/d3.v5.min.js"></script>
<script type="text/javascript" src="<?= base_url() ?>javascript/flowcharty.js"></script>

<script>
  var data = {
    nodes: [
      {id: 'start', label: {name: '開始'}, style: {fillColor: '#fff'}},      
      {id: 'process1',
            label: {name: '填寫請購單', color: '#fff', dx: 0, dy: 0, textAnchor: 'middle'},
            style: {shape: "rect", width: 150, height: 50, rx: 3, ry: 3, fillColor: '#706CAA', strokeColor: '#7152aa'}
      },
      {id: 'process2', label: {name: '主管審核', color: '#fff', dx: 0, dy: 0, textAnchor: 'middle'}, style: {shape: "rect", width: 150, height: 50, rx: 3, ry: 3, fillColor: '#706CAA', strokeColor: '#7152aa'}},
      {id: 'process3', label: {name: '承辦人審核', color: '#fff', dx: 0, dy: 0, textAnchor: 'middle'}, style: {shape: "rect", width: 150, height: 50, rx: 3, ry: 3, fillColor: '#706CAA', strokeColor: '#7152aa'}},
      {id: 'decision1', label: {name: '作廢?'}},     
      {id: 'decision2', label: {name: '核准?'}},  
      {id: 'decision3', label: {name: '核准?'}},  
      {id: 'dummyNodeP1', label: {name: ''}, style: {shape: 'nothing', strokeWidth: 0, width:0, height:0}},
      {id: 'dummyNodeD1', label: {name: '作廢'}, style: {shape: 'nothing', strokeWidth: 0, width:0, height:0}},
      {id: 'dummyNodeE', label: {name: ''}, style: {shape: 'nothing', strokeWidth: 0, width:0, height:0}},
      {id: 'dummyNodeD2', label: {name: '退回'}, style: {shape: 'nothing', strokeWidth: 0, width:0, height:0}},
      {id: 'dummyNodeD3', label: {name: '退回'}, style: {shape: 'nothing', strokeWidth: 0, width:0, height:0}},
      {id: 'end', label: {name: '結案'}, style: {fillColor: '#fff'}}
   ],
    map: [
      ['', 'start'],
      ['', 'process1', 'dummyNodeP1'],
      ['dummyNodeD1', 'decision1', ''],
      ['', 'process2'],
      ['', 'decision2', 'dummyNodeD2'],
      ['', 'process3'],
      ['', 'decision3', 'dummyNodeD3'],      
      ['dummyNodeE', 'end']      
    ],
    links: [
      {source: 'start', target: 'process1'},
      {source: 'process1', target: 'decision1'},  
      {source: 'decision1', target: 'dummyNodeD1',
            label: {name: 'yes'},
            style: {headType: 'none', color: '#afafaf', curveType: 'stepAfter'}
      },
      {source: 'decision1', target: 'process2', label: {name: 'no'}},      
      {source: 'dummyNodeD1', target: 'dummyNodeE', style: {headType: 'none',color: '#afafaf', curveType: 'stepBefore'}},
      {source: 'dummyNodeE', target: 'end', style: {color: '#afafaf', curveType: 'stepBefore'}},      
      
      {source: 'process2', target: 'decision2'},  
      {source: 'decision2', target: 'dummyNodeD2',
            label: {name: 'no'},
            style: {color: '#afafaf', curveType: 'stepAfter'}
      },
      {source: 'decision2', target: 'process3', label: {name: 'yes'}},        
      {source: 'dummyNodeD2', target: 'dummyNodeP1', style: {headType: 'none',color: '#afafaf', curveType: 'stepBefore'}},
      {source: 'dummyNodeP1', target: 'process1', style: {color: '#afafaf', curveType: 'stepBefore'}},  
      
      {source: 'process3', target: 'decision3'},  
      {source: 'decision3', target: 'dummyNodeD3',
            label: {name: 'no'},
            style: {color: '#afafaf', curveType: 'stepAfter'}
      },
      {source: 'decision3', target: 'end', label: {name: 'yes'}},        
      {source: 'dummyNodeD3', target: 'dummyNodeP1', style: {headType: 'none',color: '#afafaf', curveType: 'stepBefore'}},
    ]
  };

  var flowcharty = new Flowcharty.default();
  flowcharty.nodeRX = 7;
  flowcharty.nodeRY = 7;
  flowcharty.nodeFillColor = "#000";
  flowcharty.render(d3.select("svg"), data);
</script>