顯示具有 event 標籤的文章。 顯示所有文章
顯示具有 event 標籤的文章。 顯示所有文章

2022年12月7日 星期三

V80201 – [編審狀態]異動時, 依目前編審狀態改變 radioGroup選項

目的: V80201 – [編審狀態]異動時, 依目前編審狀態改變 radioGroup選項

處理說明: 1>[編審狀態]欄位的 EditPick 的 isSuspendevent 必需設為 false,
                      當[編審狀態]欄位異動時, change event 才會觸發
                  2>設定 radio1.setCheck(true);



2>*.js
{xtype: "fieldcontainer", fieldLabel: "編審狀態", labelWidth: 70, layout: "hbox", flex: 2,
             items: [
          { xtype: "textfield", id: "s_STAT", name: "s_STAT", width: 30, padding: "0 4 0 0", value: "C" },
          { xtype: "textfield", id: "s_STAT_NM_", name: "s_STAT_NM_", width: 80, padding: "0 4 0 0", readOnly: true, fieldCls: "readonly", value: "已核准" },
          {
             xtype: "button", id: "s_btn_STAT", name: "s_btn_STAT", text: "...",
             handler: function () {
                  //isSupendevent=false; 才會觸發 event 
                      var win = EditPickx('編審狀態', '../api/V80201API/get_s_STATPick', ['STAT', 'DESCPT'], ['s_STAT', 's_STAT_NM_'], J_pickstore_s_STAT, J_pickcolumns_s_STAT,
                                                true, false);
                                            win.show();
                                        }
                                    },
                                ]
                            },// end of s_編審狀態                    



Ext.getCmp("s_STAT").on("change", function (me, newValue, oldValue, eopts) {
    //Ext.getCmp("s_STAT").on("blur", function () {
        console.log("狀態 s_STAT change !!");
        var Tmp_STAT = Ext.getCmp('s_STAT').getValue();
        if (Tmp_STAT == "C") {  //已核准 - 處理完成日期
            Ext.getCmp("s_radio1").setValue(true);
            Ext.getCmp("s_radio2").setValue(false);
        }
        else {  //未核准 - 預計編審完成日期
            Ext.getCmp("s_radio1").setValue(false);
            Ext.getCmp("s_radio2").setValue(true);
        }
    });

2022年10月26日 星期三

V20107 – 編輯畫面 – [件號]欄位離開時 , 自動取得件號名稱 - listeners - blur - event

 目的: V20107 – 編輯畫面 – [件號]欄位離開時 , 自動取得件號名稱  - listeners - blur

處理說明:   1>直接在[PN]宣告時,加入觸發 event blur
     {id: "PN", name: "PN", xtype: "textfield", width: 320, padding: "0 4 0 0", maxLength: 32,
                     listeners: {
       blur: function () {  //件號離開時,自動取得件號中文名稱 & 英文名稱
                           console.log("call PN on blur 2");
                         }

                    2> 於程式加入 eventhandler .on("blur", function(){});
                          Ext.getCmp('PN').on("blur", function (me, event, eOpts) {

                          });  // end of Ext.getCmp("PN").on("blur", function (me, event, eOpts) {  


1>*.js

id: "PN", name: "PN", xtype: "textfield", width: 320, padding: "0 4 0 0", maxLength: 32,
listeners: {
blur: function () {  //件號離開時,自動取得件號中文名稱 & 英文名稱
//public HttpResponseMessage get_PNNM(string PN)
      console.log("call PN on blur 2");
var Tmp_PN = Ext.getCmp('PN').getValue();
console.log("Tmp_PN:", Tmp_PN);
var Tmp_Sql;
if (checkisnull(Tmp_PN)) {
return;
}
var np = {};
Ext.Ajax.request({
     url: '../../api/V20107API/get_PNNM?PN=' + Tmp_PN,
method: 'POST',
            async: false,
//standardSubmit: true, // 非 Ajax 的方式  //若要傳送檔案至前端, standardSubmit必需設為 true 
      params: np,
success: function (response, opts) {
console.log("success response.responseText:", response.responseText);
var obj = Ext.decode(response.responseText);
console.log("obj:", obj);
if (obj["success"]) {
console.log(' 取得件號名稱 !!');
var Tmp_CNM = obj["CNM"];
var Tmp_ENM = obj["ENM"];
//mysuccessalert(Tmp_Str);
console.log("success=true , Tmp_CNM=", Tmp_CNM);
console.log("success=true , Tmp_ENM=", Tmp_ENM);
Ext.getCmp("CNM").setValue(Tmp_CNM);
Ext.getCmp("ENM").setValue(Tmp_ENM);
}
else {
Tmp_Str = "取得件號名稱失敗!! <br>"
+ obj["Rtn_Msg"];
mywarnalert(Tmp_Str);
}
},
failure: function (response, opts) {
var obj = Ext.decode(response.responseText);
console.log("obj:", obj);
Tmp_Str = "取得件號名稱失敗!! < br > "
+ obj["Rtn_Msg"];
mywarnalert(Tmp_Str);
} // end of failure 
});  // end of Ext.Ajax
}  //end  of blur
*/
}  // end of listeners


Ext.getCmp('PN').on("blur", function (me, event, eOpts) {
        console.log("call PN on blur 1");
        var Tmp_PN = Ext.getCmp('PN').getValue();
        console.log("Tmp_PN:", Tmp_PN);
        var Tmp_Sql;
        if (checkisnull(Tmp_PN)) {
            return;
        }
        var np = {};
        Ext.Ajax.request({
            url: '../../api/V20107API/get_PNNM?PN=' + Tmp_PN,
            method: 'POST',
            async: false,
            //standardSubmit: true, // 非 Ajax 的方式  //若要傳送檔案至前端, standardSubmit必需設為 true 
            params: np,
            success: function (response, opts) {
                console.log("success response.responseText:", response.responseText);
                var obj = Ext.decode(response.responseText);
                console.log("obj:", obj);
                if (obj["success"]) {
                    console.log(' 取得件號名稱 !!');
                    var Tmp_CNM = obj["CNM"];
                    var Tmp_ENM = obj["ENM"];
                    //mysuccessalert(Tmp_Str);
                    console.log("success=true , Tmp_CNM=", Tmp_CNM);
                    console.log("success=true , Tmp_ENM=", Tmp_ENM);
                    Ext.getCmp("CNM").setValue(Tmp_CNM);
                    Ext.getCmp("ENM").setValue(Tmp_ENM);
                }
                else {
                    Tmp_Str = "取得件號名稱失敗!! <br>"
                        + obj["Rtn_Msg"];
                    mywarnalert(Tmp_Str);
                }
            },
            failure: function (response, opts) {
                var obj = Ext.decode(response.responseText);
                console.log("obj:", obj);
                Tmp_Str = "取得件號名稱失敗!! < br > "
                    + obj["Rtn_Msg"];
                mywarnalert(Tmp_Str);
            } // end of failure 
        });  // end of submit
    });  // end of Ext.getCmp("PN").on("blur", function (me, event, eOpts) {



V20107 – Master[存檔]完成, 自動重新顯示 Detail資料 - fireEvent

 目的: V20107 – Master[存檔]完成,自動新增 4 Detail資料並重新顯示 Detail資料

處理說明: 1>fireEvent("eventName", event_param1,event_param2,event_param3,...);

Ex: selectionchange( this, selected, eOpts )
       傳入參數如下: 
         this : Ext.selection.Model
         selected : Ext.data.Model[]  ,          The selected records
         eOpts : Object

       --> fireEvent("selectionchange",this,selected,eOpts);0

  Ex:  Ext.getCmp('grid_M').fireEvent("selectionchange", Ext.getCmp("grid_M").getSelectionModel(),cur_recs);


1>*.js

 //先執行 Template 的 onClick , 再執行 V20107 的 onClick

    Ext.getCmp('btn_save').on('click', function () {

        //若 checkFormValue 有問題,則 is_Keepgoing=false , 不往下執行

        if (is_keepgoing==false)

            return ;

        console.log('step 1 click_btn_save of V20107');

        if (!check_AMM_WKSTPD_isnull()) {

            console.log("if !check_AMM_WKSTPD_isnull() , return ");

            return ;   // AMM_WKSTPD 已有資料,不新增 4筆資料

        }

        //若 AMM_WKSTPD 為空值,則詢問是否為系統件維修,

        //若是,則  INSERT_AMM_WKSTPD4  ,寫入 4筆資料

        console.log("3 詢問是否為系統件維修嗎?");

        var Tmp_Msg = "本交修件為系統件維修嗎 ?";

        Ext.Msg.confirm('確認', Tmp_Msg, callBackFunc);

        function callBackFunc(id) {

            console.log("1 callBackFunc : 本交修件為系統件維修嗎 ?");

            if (id == 'no')

                return;

            //insert 四筆資料   AMM_WKSTPD

            var np = {};

            np["MITM"] = Ext.getCmp("MITM").getValue();

            np["PN"] = Ext.getCmp("PN").getValue();

            np["DEPID"] = Ext.getCmp("DEPID").getValue();

            np["WC"] = Ext.getCmp("WC").getValue();

            var is_Ok = true;

            Ext.Ajax.request({

                method: "POST",

                url: '../../api/V20107API/DO_Ins_AMM_WKSTPD4',

                params: np,

                async: false,

                success: function (response, opts) {

                    console.log("0 response.responseText=", response.responseText);

                    var Tmp_Obj = Ext.decode(response.responseText);

                    console.log("1  Tmp_Obj=", Tmp_Obj);

                    if (Tmp_Obj["success"] == true) {

                        var Tmp_Rtn_Msg = "自動新增4筆工作步序說明資料(AMM_WKSTPD)<br>"

                            + "- 進廠檢測,拆檢,組裝,完工測試<br>";

                        + Tmp_Obj["Rtn_Msg"];

                        mysuccessalert(Tmp_Rtn_Msg);

                        is_Ok = true;

                        console.log(" 5 Ext.getCmp('grid_M').fireEvent(selectionchange) ");

                        //Ext.getCmp('grid_M').fireEvent("selectionchange",);

                            //("selectionchange", function (view, selections, options) {

                        var cur_recs = Ext.getCmp("grid_M").getSelectionModel().getSelection();    

                    Ext.getCmp('grid_M').fireEvent("selectionchange", Ext.getCmp("grid_M").getSelectionModel(),cur_recs);

                    }

                    else {

                        var Tmp_Rtn_Msg = "自動新增4筆工作步序說明資料(AMM_WKSTPD)失敗<br>"

                            + "- 進廠檢測,拆檢,組裝,完工測試<br>"

                            + "請檢核!! <br>"

                            + Tmp_Obj["Rtn_Msg"];

                        mywarnalert(Tmp_Rtn_Msg);

                        is_Ok= false;

                    }

                },  //end of success                

                failure: function (response, opts) {

                    var Tmp_Obj = Ext.decode(response.responseText);

                    var Tmp_Rtn_Msg = "新增4筆工作步序說明資料(AMM_WKSTPD)失敗<br>"

                        + "請檢核<br>"

                        + Tmp_Obj["Rtn_Msg"];

                    mywarnalert(Tmp_Rtn_Msg);

                    is_Ok= false;

                }

            })  //end of Ext.Ajax.Request       

            return is_OK;

        };  // end of callBackFunc(id)

    })  //Ext.getCmp('btn_save').on('click', function () {


2022年9月21日 星期三

V20301 –[複製] – 複製多筆資料 – CheckboxModel – 覆蓋原本 parent.[複製處理]

 目的: V20301 –[複製] – 複製多筆資料 – CheckboxModel – 覆蓋原本 parent.[複製]鈕.處理

處理說明:  1>覆蓋原本 parent.[複製]鈕.處理 un('click', Handlerfn);
                   2>一筆一筆複製,呼叫後端函式 CopyFMNO (par_FMNO) ,於後端新增資料
                   3>重新顯示資料,btn_show.fireHandler()


1>*.js
//覆蓋原本 parent 的 [複製]鈕處理
Ext.getCmp('btn_copy').un("click", Ext.getCmp('btn_copy').events.click.listeners[0].fn);

//新的  [複製]鈕處理,
    var buttonModel = Ext.create('G_buttonModel');   //取得 目前的畫面狀態(1,2,3 : 新增/編輯/瀏覽)
    Ext.getCmp("btn_copy").on('click', function (me, e, eOpts) {        
       var cur_recs = Ext.getCmp('grid_Single').getSelectionModel().getSelection();
        var cur_rec;
        console.log("before copy_rec");
        var copy_rec;  //?? 如何產生另一 copy_rec 不和 cur_rec 相同
        var np = {};
        if (cur_recs.length == 0) {
            buttonModel.modelType = 0;
            mywarnalert('請先勾選要複製的資料!!');
        }
        else {
            var gridstore = Ext.getCmp('grid_Single').store;
            me.delMessage = "確定複製勾選的資料嗎?";
            Ext.Msg.confirm('提醒', me.delMessage, callBackFunc);
            function callBackFunc(id) {
                if (id == 'yes') {
                    console.log("cur_recs.length:", cur_recs.length);                    
                    for (let i = 0; i <= cur_recs.length - 1; i++) {
                        console.log("i:", i);                        
                        cur_rec = cur_recs[i];                        
                        copy_rec = cur_rec;
                        console.log("0 cur_rec: ", cur_rec);
                        var Tmp_NEXT_FMNO = get_NEXT_FMNO();
                        var Tmp_cur_DT = DatetoStr(now, "Y/m/d");
                        var Tmp_MDDT = DatetoStr(copy_rec.data["MDDT"], "Y/m/d");
                        console.log("Tmp_NEXT_FMNO:", Tmp_NEXT_FMNO);
                        copy_rec.data["FMNO"]=Tmp_NEXT_FMNO;                        
                        copy_rec.data["BTDT"] = Tmp_cur_DT;        
                        copy_rec.data["MDDT"] = Tmp_cur_DT;        
                        copy_rec.data["STATFM"] = "A";        
                        copy_rec.data["DTSOR"] = "A";        
                        copy_rec.data["OSM"] = "";                    
                        console.log("1 cur_rec: ", cur_rec);
                        console.log("copy_rec: ", copy_rec);
                        //新增資料庫資料
                        Copy_FMNO(copy_rec);
                    } //  end of for (let i=0,)
                    //複製完成後,重新顯示資料  
                    Ext.getCmp('btn_Show').fireHandler();
                    buttonModel.modelType = 0;
                }  // end    if (id == 'yes')             
            }  // end of callbackfunc
        }  //end of else {}       
    }
    );

function Copy_FMNO(par_copy_rec)
{
    var np = {};
    np = par_copy_rec.data;
    Ext.Ajax.request({
        method: "POST",
        url: '../../api/V20301API/Copy_FMNO',
        params: np,
        async: false,
        success: function (response, opts) {
            var Tmp_Obj = Ext.decode(response.responseText);
            if (Tmp_Obj["success"]) {
                Tmp_Rtn_Msg = Tmp_Obj['Rtn_Msg'].toString();       
                //"複製成功 !! <br>" 
                mywarnalert(Tmp_Rtn_Msg);
                //gridstore.add(copy_rec);
            }
            else {
                Tmp_Rtn_Msg = Tmp_Obj['Rtn_Msg'].toString();       
                //"複製失敗 !!"
                mywarnalert(Tmp_Rtn_Msg);
            }
        }, // end of  success 
        failure: function (response, opts) {
            isOk = false;
        }
    });  // end of Ext.Ajax                   
}  // end of  function string  Copy_FMNO(Tmp_FMNO)



    //取得   FMNO 的下一編號
    function get_NEXT_FMNO() {
        var isOk = true;
        var Tmp_NEXT_FMNO = "";        
        var np = {};
        Ext.Ajax.request({
            method: "POST",
            url: '../../api/V20301API/get_NEXT_FMNO',
            params: np,
            async: false,
            success: function (response, opts) {
                var Tmp_Obj = Ext.decode(response.responseText);
                //console.log("Tmp_Obj[success]=", Tmp_Obj["success"]);
                if (Tmp_Obj["success"]) {
                    Tmp_NEXT_FMNO = Tmp_Obj['NEXT_FMNO'].toString();
                    if (Tmp_NEXT_FMNO.length == 0)
                        Tmp_NEXT_FMNO = '001';
                    console.log("Tmp_NEXT_FMNO=", Tmp_NEXT_FMNO);
                    return Tmp_NEXT_FMNO;
                    //mywarnalert(Tmp_Str);
                    //console.log(" 1 success return false");                    
                }
                else {
                    mywarnalert("取得下一系統件單號(FMNO)失敗 !!");
                }
            }, // end of  success 
            failure: function (response, opts) {
                isOk = false;
            }
        });  // end of Ext.Ajax               
        return Tmp_NEXT_FMNO;
    }  // end of  function string  get_NEXT_FMNO(Tmp_FMNO)


V20301 – [刪除]鈕, - checkboxModel -刪除勾選的多筆資料 - 覆蓋原本event的處理 - 移除目前 store 資料

 目的:  [刪除]鈕,  -刪除勾選的多筆資料 - checkboxModel 

處理說明:  1>將 grid_Single 換成 checkboxModel class

                   2> 重寫 btn_del.onclick 處理 , 即  beforedel() 傳回 false, 不處理 parent.del 函式

                   3> 依勾選的資料, 一筆一筆從資料庫刪除 , 資料庫刪除後, 再刪除畫面的資料


1>*.js
 1>>置換成 CheckboxModel  class
    //加入 checkbox Model 
    Ext.getCmp('grid_Single').destroy(); //20220905
    var grid_Single = Ext.create('grid_Single', {
        id: 'grid_Single',
        resizable: true,
        selModel: Ext.create('Ext.selection.CheckboxModel', {
            selectionMode: 'SIMPLE',
            listeners: {
                /*selectionchange: function (cb, selected, eOpts) {
                    //view.selModel.getSelection()
                },*/
                RowMouseDown: function (view, record, item, index, e) {
                    var me = this;
                    if (index !== -1) {

                        if (!me.allowRightMouseSelection(e)) {
                            return;
                        }

                        if (e.shiftKey && me.lastFocused) {
                            me.selectRange(me.lastFocused, record, e.ctrlKey);
                            me.processSelection(view, record, item, index, e);
                        }

                        if (!me.isSelected(record)) {
                            me.mousedownAction = true;
                            me.processSelection(view, record, item, index, e);
                        } else {
                            me.mousedownAction = false;
                        }
                    }

                }
            }
        })
    });
    Ext.getCmp('tab2').add(grid_Single); //將grid加入到tab裡面
    Ext.getCmp('tab2').updateLayout();

 2>>重寫 btn_del.onclick 處理 , 即  beforedel() 傳回 false, 不處理 parent.del 函式

//20220922  覆蓋原本的 [刪除]鈕 處理,  自行處理
    //不執行 paretn.delete , beforeDel 傳回 false
    Ext.getCmp('btn_del').beforeDel = function () {
        return false;
    }

    var buttonModel = Ext.create('G_buttonModel');   //取得 目前的畫面狀態(1,2,3 : 新增/編輯/瀏覽)

    Ext.getCmp("btn_del").on('click', function (me,e,eOpts) {    
      //已置換 grid_store , 不需 .getView().
     //var cur_recs = Ext.getCmp('grid_Single').getView().getSelectionModel().getSelection(); 
        var cur_recs = Ext.getCmp('grid_Single').getSelectionModel().getSelection();
        var cur_rec;
        if (cur_recs.length == 0)
        {
            buttonModel.modelType = 0;
            mywarnalert('請先勾選要刪除的資料!!');
        }
        else {
            me.delMessage = "確定刪除勾選的資料嗎?";
            Ext.Msg.confirm('提醒', me.delMessage, callBackFunc);
            function callBackFunc(id) {
                if (id == 'yes') {
                    console.log("cur_recs.length:", cur_recs.length);
                    var gridstore = Ext.getCmp('grid_Single').store;                        
                    for (let i = 0; i <= cur_recs.length - 1; i++) {
                        console.log("i:", i);
           Ext.getCmp('grid_Single').getSelectionModel().select(cur_recs[i]); //grid select指向所選的資料
                        if (Ext.getCmp('btn_del').afterDel() == false) {
                            return;
                        }                                                
                    } //  end of for (let i=0,)
                    //資料庫均刪除完成後, 才由 gridstore 移除資料
                    for (let i = 0; i <= cur_recs.length - 1; i++) {
                        gridstore.remove(cur_recs[i]); //畫面上隱藏刪除列                     
                    } //  end of for (let i=0,)
                    Ext.getCmp('grid_Single').getView().refresh();
                    buttonModel.modelType = 0;
                }  // end    if (id == 'yes')             
            }  // end of callbackfunc
        }  //else { of if length>0            
    } ) // end of click function 

V20301 – [刪除]鈕, 覆蓋原本 parent.[刪除]鈕的處理,

 目的: 覆蓋原本 parent class  event 的處理, Ex: [刪除]鈕, 覆蓋原本 parent.[刪除]鈕的處理

處理說明: 
     1>方法1:
          1>>btn_del 的 parent 函式中, 有一 beforeDel() 函式傳回 true 時, 才會往下執行
                所以將  beforeDel() 函式 傳回 false , 則不會往下執行, 即不執行 parent.btn_del 處理
    
     2>方法2:           
           1>>利用 元件.un("event名稱", event handler) , 解除 parent 的 event handler
           2>>重新 元件.on("event名稱", function (){})  ;
        


1>*.js

1>>方法1: 利用 parent.beforeDel 函式 , 傳回 false , 不會執行原本 parent.del處理

    Ext.getCmp('btn_del').beforeDel = function () {
        return false;
    }

    Ext.getCmp("btn_del").on('click', function () {
        mysuccessalert("btn_del click");
    });
    

2>>方法2:  利用 元件.un("event名稱", event handler) , 解除 parent 的 event handler  

    Ext.getCmp('btn_del').un("click", Ext.getCmp('btn_del').events.click.listeners[0].fn);
    console.log("2 after un Ext.getCmp('btn_del') : ", Ext.getCmp('btn_del'));    
    console.log("1 Ext.getCmp('btn_del') : ", Ext.getCmp('btn_del'));
 console.log("1 before   Ext.getCmp('btn_del').events.click.listeners[0].fn : ", Ext.getCmp('btn_del').events.click.listeners[0].fn);
    Ext.getCmp("btn_del").on('click', function () {
        mysuccessalert("btn_del click");
    });




2022年8月31日 星期三

DOM - 2 Event 的特殊處理 - 停止event預設動作 - 停止往上冒泡 -bubble,catch

目的: 停止event預設動作 - 停止往上冒泡處理說明:1> Label 的event flow 為 bubble 方式時

            2> 觸發 lbl.onclick event後 , console 顯示 "lbl click"

                 瀏覽器將 click event  自動往下傳, 即傳給 checkbox.click event

            3> 因 checkbox event 為 bubble 方式,所以又往上傳給 lbl 

                即觸發 lbl.onclick event , concole 又顯示 "lbl click"

--> 即 lbl.onclick event 被觸發兩次


一.要阻擋事件向上冒泡傳遞:

--> event.stopPropagation()



<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="src/style.css" />
  </head>
  <body>
    <h1>Hi friend, try edit me!</h1>
    <label class="lbl">
      Label <input type="checkbox" name="chkbox" id="chkbox" />
    </label>
    // label

    <script>
      var lbl = document.querySelector('.lbl');
      var chkbox = document.querySelector('#chkbox');

      lbl.addEventListener('click', function (e) {
        console.log('lbl click');
      }, false);

      chkbox.addEventListener('click', function (e) {
        console.log('chkbox click');
      }, false);

    </script>

    <script src="src/script.js"></script>
  </body>
</html>

-->

     chkbox.addEventListener('click', function (e) {
        console.log('chkbox click');
         e.stopPropagation();
      }, false);





二.不執行預設動作, 只執行目前動作( console.log("google") )



<a id="link" href="https://www.google.com">Google</a>

var link = document.querySelector('#link'); 

// 在 evend handler 加上 e.preventDefault(); 
link.addEventListener('click', function (e) { 
e.preventDefault(); 
console.log('Google!'); 
}, false);

2022年8月30日 星期二

DOM -1 Event 的處理機制 - bubble -catch -eventflow

目的: 了解 Web  DOM的 event 處理 機制

處理說明:   1> catch 時, 由上而下 (Document --> html --> body --> table --> tr --> td --> div)

                    2> bubble時, 由下而上(div-->td--> tr--> table --> body --> html --> Document)

-->  DOM 兩種機制 (catch/bubble) 均有, 可分別設定 catch / bubble 的 event handler

參考原始網址: https://ithelp.ithome.com.tw/articles/10191970

- 重新認識 JavaScript: Day 14 事件機制的原理



而事件流程 (Event Flow) 指的就是「網頁元素接收事件的順序」。

事件流程可以分成兩種機制:

  • 事件冒泡 (Event Bubbling)
  • 事件捕獲 (Event Capturing)

假設現在的事件是點擊上圖中藍色的 <td>

那麼當 td 的 click 事件發生時,會先走紅色的 「capture phase」:

  1. Document
  2. <html>
  3. <body>
  4. <table>
  5. <tbody>
  6. <tr>
  7. <td> (實際被點擊的元素)

由上而下依序觸發它們的 click 事件。

然後再繼續執行綠色的 「bubble phase」,反方向由 <td> 一路往上傳至 Document,整個事件流程到此結束。

Ex:  DOM的實作案例

<div>
    <div id="parent">父元素      
          <div id="child">子元素</div>
     </div>
</div>


// 父元素
var parent = document.getElementById('parent');
// 子元素
var child = document.getElementById('child');

// 透過 addEventListener 指定事件的綁定
// 第三個參數 true / false 分別代表捕獲/ 冒泡 機制

parent.addEventListener('click', function () {
  console.log('Parent Capturing');
}, true);  //capture 機制 event hadler

parent.addEventListener('click', function () {
  console.log('Parent Bubbling');
}, false); //bubble 機制 event hadler


child.addEventListener('click', function () {
  console.log('Child Capturing');
}, true);

child.addEventListener('click', function () {
  console.log('Child Bubbling');
}, false);

-->

當我點擊的是「子元素」的時候,透過 console.log 可以觀察到事件觸發的順序為:
       "Parent Capturing"
       "Child Capturing"
       "Child Bubbling"
       "Parent Bubbling"

由此可知,點擊子元素的時候,父層的 Capturing 會先被觸發,然後再到子層內部的 Capturing 或 Bubbling 事件。 最後才又回到父層的 Bubbling 結束。

子層的 Capturing 或 Bubbling 誰先誰後呢?
要看你程式碼的順序而定。

子層若是 Capturing 在 Bubbling 前面:

child.addEventListener('click', function () { console.log('Child Capturing'); }, true); child.addEventListener('click', function () { console.log('Child Bubbling'); }, false);

--> 子層觸發順序
"Child Capturing" "Child Bubbling"

-->
addEventListener() 基本上有三個參數,分別是「事件名稱」、「事件的處理器」(事件觸發時執行的 function),以及一個「Boolean」值,由這個 Boolean 決定事件是以「捕獲」或「冒泡」機制執行,若不指定則預設為「冒泡」。
true/false : catch/bubble


Bubble 及 Catch event flow





2022年8月17日 星期三

V120402D - 子畫面onShow時,顯示目前所在資料的欄位值

 目的: 子畫面onShow時,顯示主畫面grid資料欄位值

處理說明: 1>取得主畫面grid資料欄位值,並存入 - np
                  2>np當參數傳入子畫面呼叫函式
                  3>設定子畫面欄位值



1>*.js

  {
            xtype: 'button', text: '查詢借閱記錄', id: 'LookBtn',
            listeners: {
                click: function () {
                    //console.log(" 1 inside 缺勤記錄維護: ");
                    var cur_recs,cur_rec;
                    var np = {};
                    var Tmp_Str = "";
                    cur_recs = Ext.getCmp("grid_M").selModel.getSelection();
                    if (cur_recs.length == 0) {
                        Tmp_Str = "請先選擇要查詢借閱記錄的資料<br>";
                        mywarnalert(Tmp_Str);
                        return;
                    }
                    cur_rec = cur_recs[0];
                    np["TMNO"] = cur_rec.data["TMNO"];
                    np["TMNOXX"] = cur_rec.data["TMNOXX"];
                    np["DOCNO"] = cur_rec.data["DOCNO"];
                    np["NATIXX"] = cur_rec.data["NATIXX"];
                    np["SHT"] = cur_rec.data["SHT"];
                    np["LGTPXX"] = cur_rec.data["LGTPXX"];
                    LookBtn_click(np);
                }
            }
        },

var win = getMyWindow("查詢借閱記錄", sub_LookFlds, sub_LookFlds_Btns);
    //var win = getMyWindow("查詢借閱記錄", sub_LookFlds);
    win.width = 700;
    win.heigh = 400;    

    win.on("show", function (me, eOpts) {
        console.log("win onshow!!");
        Ext.getCmp('sub_Grid_ptb').hide();
        Ext.getCmp("sub_TMNOXX").setValue(par_np["TMNOXX"]);
        Ext.getCmp("sub_DOCNO").setValue(par_np["DOCNO"]);
        Ext.getCmp("sub_NATIXX").setValue(par_np["NATIXX"]);
        Ext.getCmp("sub_SHT").setValue(par_np["SHT"]);
        Ext.getCmp("sub_LGTPXX").setValue(par_np["LGTPXX"]);
    });

    win.show();      //onShow event handler 必需在 win.show(); 執行前就宣告, 才會觸發 
    
} // end of   function LendBtn_click() {