備忘錄_20160105(定位) 修改 回首頁

程式 2023-03-12 08:51:44 1678582304 100
JavaScript常用類別參考

JavaScript常用類別參考
  1. gebi(strId)
  2. getStrUUID()
  3. location_href_by_form(strUrl, oParameters, strMethod)
  4. open_new_window_by_form(strUrl, oParameters, strMethod)
  5. showOrHide(strId)
  6. showOrHideByObj(obj1)
  7. toast(strMessage, iInterval)
  8. async msgbox(strMsg, straBtn)
  9. async inputbox(strPrompt, strDefaultValue, booPassword)
  10. async makeAFetchSync(oParameters)
  11. async getOFetchSync(strUrl='', oInputData={})
  12. makeAnXhrSync(oParameters)
  13. makeAnXhr(oParameters)
  14. makeAnXhr_form_post(oParameters)
  15. searchAndSelect(oTxt, aryOrFunc, strSearchMethod, strClassName, funcCallback, iWaitForMilliSeconds=1000)
  16. floatingSelect(oTargetElement, straOption, strClassName, funcCallback)
  17. getBoo純粹阿拉伯數字(str1)
  18. getStr盡量變成簡易日期(str1)
  19. getStr盡量變成完整日期(str1, strDelimiter="/")
  20. getStrTrimSpecial(str1)
  21. getStrToValue(str1)
  22. getStrToInnerHTML(str1)
  23. getStrFromInnerHTML(str1)
  24. getOResponse(strResponseText) // 讀取從 php 回來的資料集

// ver 20230629_001 - 20250208_001
//
// usage:
//
// <script src="lib_common.js"></script>
//

class c_liujiaje_com_common
{
  gebi(strId)
  {
    return document.getElementById(strId);
  }
  
  getStrUUID()
  {
    var d = Date.now();
    if (typeof performance !== 'undefined' 
    && typeof performance.now === 'function')
    {
      d += performance.now(); //use high-precision timer if available
    }
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace
    (
      /[xy]/g, 
      function (c) 
      {
        var r = (d + Math.random() * 16) % 16 | 0;
        d = Math.floor(d / 16);
        return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
      }
    );
  }
  
  location_href_by_form(strUrl, oParameters, strMethod)
  {
    // 範例
    // location_href_by_form("http://something.com.tw/", {"name":"John", "age":"18", "sex":"male"}, "post");
    
    var strAcceptCharset="utf-8";
  
    // "application/x-www-form-urlencoded" (預設,空白變成+,特殊字元用16進位編碼)
    // "multipart/form-data" (檔案上傳)
    // "text/plain" (空白變成+,其餘不變)
    var strEnctype="application/x-www-form-urlencoded";
  
    strMethod = strMethod || "post";
    var strAction=strUrl;
    var strTarget="_self";
  
    var oForm = document.createElement("form");
  
    oForm.setAttribute("accept-charset", strAcceptCharset);
    oForm.setAttribute("enctype", strEnctype);
    oForm.setAttribute("method", strMethod);
    oForm.setAttribute("action", strAction);
    oForm.setAttribute("target", strTarget);
  
    for(var strPropertyName in oParameters)
    {
      var strPropertyValue=oParameters[strPropertyName];
      
      var oHiddenField = document.createElement("input");
      oHiddenField.setAttribute("type", "hidden");
      oHiddenField.setAttribute("name", strPropertyName);
      oHiddenField.setAttribute("value", strPropertyValue);
      
      oForm.appendChild(oHiddenField);
    }
    
    document.body.appendChild(oForm);
    oForm.submit();
  }
  
  open_new_window_by_form(strUrl, oParameters, strMethod)
  {
    // 範例
    // open_new_window_by_form("http://something.com.tw/", {"name":"John", "age":"18", "sex":"male"}, "post");
    
    var strAcceptCharset="utf-8";
  
    // "application/x-www-form-urlencoded" (預設,空白變成+,特殊字元用16進位編碼)
    // "multipart/form-data" (檔案上傳)
    // "text/plain" (空白變成+,其餘不變)
    var strEnctype="application/x-www-form-urlencoded";
  
    strMethod = strMethod || "post";
    var strAction=strUrl;
    var strTarget="_blank";
  
    var oForm = document.createElement("form");
  
    oForm.setAttribute("accept-charset", strAcceptCharset);
    oForm.setAttribute("enctype", strEnctype);
    oForm.setAttribute("method", strMethod);
    oForm.setAttribute("action", strAction);
    oForm.setAttribute("target", strTarget);
  
    for(var strPropertyName in oParameters)
    {
      var strPropertyValue=oParameters[strPropertyName];
      
      var oHiddenField = document.createElement("input");
      oHiddenField.setAttribute("type", "hidden");
      oHiddenField.setAttribute("name", strPropertyName);
      oHiddenField.setAttribute("value", strPropertyValue);
      
      oForm.appendChild(oHiddenField);
    }
    
    document.body.appendChild(oForm);
    oForm.submit();
    
    window.setTimeout(function(){ oForm.remove(); }, 5000); // 5秒後,自動移除表單元素
  }
  
  showOrHide(strId)
  {
    var obj1=this.gebi(strId);
    if(obj1)
    {
      if(obj1.style.display=="none") { obj1.style.display=""; }
      else                           { obj1.style.display="none"; }
    }
  }
  
  showOrHideByObj(obj1)
  {
    if(obj1)
    {
      if(obj1.style.display=="none") { obj1.style.display=""; }
      else                           { obj1.style.display="none"; }
    }
  }
  
  toast(strMessage, iInterval)
  {
    if(!iInterval) { iInterval=3000; }
    
    var oToast=document.createElement("div");
    oToast.style.display="block";
    oToast.style.position="fixed";
    oToast.style.zIndex="1";
    oToast.style.visibility="visible";
    oToast.style.width="100%";
    oToast.style.textAlign="center";
    oToast.style.bottom="30px";
    oToast.style.fontSize="17px";
    
    var straStyle=[];
    straStyle.push("display: inline-block");
    straStyle.push("color: #ffffff");
    straStyle.push("background-color: #333");
    straStyle.push("margin: 0 auto");
    straStyle.push("border-radius: 2px");
    straStyle.push("padding: 16px");
    oToast.innerHTML
      ="<div style='"+straStyle.join("; ")+"'>"
      +strMessage
      +"</div>";
    document.body.appendChild(oToast);
    
    setTimeout(function() { oToast.parentNode.removeChild(oToast); }, iInterval);
  }
  
  async msgbox(strMsg, straBtn)
  {
    // // 呼叫範例
    //
    // async function main()
    // {
    //   var strRtn=await msgbox("對話框測試!<br>第二行在這裡!", ["確定", "取消"]);
    //   console.log(strRtn);
    // }
          
    if(Array.isArray(straBtn)==false || straBtn.length<1)
    {
      straBtn=["確定"];
      // straBtn=["確定", "取消"];
    }
    
    var strRtn="";
    
    await new Promise
    (
      (成功, 失敗)=>
      {
        // 背景
        var oBG=document.createElement("div");
        oBG.style.display="block";
        oBG.style.position="fixed";
        oBG.style.zIndex="1";
        oBG.style.left="0";
        oBG.style.top="0";
        oBG.style.width="100%";
        oBG.style.height="100%";
        oBG.style.overflow="auto";
        oBG.style.backgroundColor="rgb(0,0,0)";
        oBG.style.backgroundColor="rgba(0,0,0,0.4)";
        oBG.style.textAlign="center";
      
        // 前景
        var oFG=document.createElement("div");
        oFG.style.display="inline-block";
        oFG.style.backgroundColor="rgb(240,240,240)";
        oFG.style.margin="0 auto";
        oFG.style.padding="1em";
        oFG.style.borderStyle="solid";
        oFG.style.borderWidth="1px";
        oFG.style.borderColor="#888888";
        oFG.style.borderRadius="12px";
        oFG.style.textAlign="center";
      
        // 內文
        var oContent=document.createElement("div");
        oContent.style.margin="4px";
        oContent.innerHTML=strMsg;
        oFG.appendChild(oContent);
        
        // 產生按鈕
        for(var i=0; i<straBtn.length; i++)
        {
          var oTmpBtn=document.createElement("button");
          oTmpBtn.setAttribute("type","button");
          oTmpBtn.innerHTML=straBtn[i];
          oTmpBtn.setAttribute("returnString",straBtn[i]);
          oTmpBtn.style.margin="4px";
          oTmpBtn.onclick=function()
          {
            strRtn=this.getAttribute("returnString");
            成功(oBG);
          }
          oFG.appendChild(oTmpBtn);
        }
        
        // 把前景加入到背景裡頭
        oBG.appendChild(oFG);
        
        // 把背景加入到 body 中
        document.body.appendChild(oBG);
        
        // 點到背景灰黑的部分,等同按下取消。
        window.addEventListener("click",function(event)
        {
          if(event.target==oBG)
          {
            strRtn=straBtn[straBtn.length-1];
            成功(oBG);
          }
        },false);
        
        // oBG.style.display="block";
        
        // 垂直置中
        oFG.style.marginTop=((window.innerHeight-oFG.offsetHeight)/2)+"px";
        
        oTmpBtn.focus();
      }
    )
    .then(  (oBG)=>{ oBG.parentNode.removeChild(oBG); } )
    .catch( (err)=>{ strRtn="err:"+err; console.log(strRtn); } );
    
    return strRtn;
  }
  
  async inputbox(strPrompt, strDefaultValue, booPassword)
  {
    // // 呼叫範例
    //
    // async function main()
    // {
    //   var strRtn=await inputbox("請您輸入資料", "預設值", false);
    //   console.log(strRtn);
    // }
    
    if(!strDefaultValue) { strDefaultValue=''; }
    
    var strType="text";
    if(booPassword==true) { strType="password"; }
    
    var strRtn="";
    
    await new Promise
    (
      (成功, 失敗)=>
      {
        // 背景
        var oBG=document.createElement("div");
        oBG.style.display="block";
        oBG.style.position="fixed";
        oBG.style.zIndex="1";
        oBG.style.left="0";
        oBG.style.top="0";
        oBG.style.width="100%";
        oBG.style.height="100%";
        oBG.style.overflow="auto";
        oBG.style.backgroundColor="rgb(0,0,0)";
        oBG.style.backgroundColor="rgba(0,0,0,0.4)";
        oBG.style.textAlign="center";
      
        // 前景
        var oFG=document.createElement("div");
        oFG.style.display="inline-block";
        oFG.style.backgroundColor="rgb(240,240,240)";
        oFG.style.margin="0 auto";
        oFG.style.padding="1em";
        oFG.style.borderStyle="solid";
        oFG.style.borderWidth="1px";
        oFG.style.borderColor="#888888";
        oFG.style.borderRadius="12px";
        oFG.style.textAlign="center";
      
        // 提示
        var oPrompt=document.createElement("div");
        oPrompt.style.margin="4px";
        oPrompt.innerHTML=strPrompt;
        oFG.appendChild(oPrompt);
        
        // 輸入方框
        var oInput=document.createElement("input");
        oInput.setAttribute("type", strType);
        oInput.setAttribute("value", strDefaultValue);
        // 若是用 onkeyup, onkeydown 則注音輸入法的 Enter 會被攔截到
        oInput.onkeypress=function(keyboardEvent)
        {
          if(keyboardEvent.keyCode==13 || keyboardEvent.key=="Enter")
          {
            strRtn=oInput.value;
            成功(oBG);
          }
        }
        
        var oContent=document.createElement("div");
        oContent.style.margin="4px";
        oContent.appendChild(oInput);
        
        oFG.appendChild(oContent);
        
        // 產生按鈕
        var straBtn=["確定", "取消"];
        for(var i=0; i<straBtn.length; i++)
        {
          var oTmpBtn=document.createElement("button");
          oTmpBtn.setAttribute("type","button");
          oTmpBtn.innerHTML=straBtn[i];
          oTmpBtn.setAttribute("returnString",straBtn[i]);
          oTmpBtn.style.margin="4px";
          
          if(i==0)
          {
            oTmpBtn.onclick=function()
            {
              strRtn=oInput.value;
              成功(oBG);
            }
          }
          else
          {
            oTmpBtn.onclick=function()
            {
              strRtn="";
              成功(oBG);
            }
          }
          oFG.appendChild(oTmpBtn);
        }
        
        // 把前景加入到背景裡頭
        oBG.appendChild(oFG);
        
        // 把背景加入到 body 中
        document.body.appendChild(oBG);
        
        // 點到背景灰黑的部分,等同按下取消。
        window.addEventListener("click",function(event)
        {
          if(event.target==oBG)
          {
            strRtn="";
            成功(oBG);
          }
        },false);
        
        // oBG.style.display="block";
        
        // 垂直置中
        oFG.style.marginTop=((window.innerHeight-oFG.offsetHeight)/2)+"px";
        
        oInput.focus();
      }
    )
    .then(  (oBG)=>{ oBG.parentNode.removeChild(oBG); } )
    .catch( (err)=>{ strRtn="err:"+err; console.log(strRtn); } );
    
    return strRtn;
  }
  
  async makeAFetchSync(oParameters)
  {
    // // 範例參考
    // 
    // async function xyz()
    // {
    // 
    //   var oP={};
    //   oP.strMethod="post"; // get 或 post
    //   oP.strAction="a.php";
    //   oP.straPairs=[
    //     ["name","John"],
    //     ["age","18"],
    //     ["salary","28000"],
    //     ["special","'\"=&?甚麼都來!"]
    //   ];
    //   
    //   await oCom.makeAFetchSync(oP);
    //   
    //   if(oP.booSuccess==false) { console.log("error:"+oP.strStatusText); }
    //   else                     { console.log(oP.strResponseText); }
    //   
    // }
    //   
    
    // 檢驗 method 參數
    oParameters.strMethod=oParameters.strMethod.toUpperCase(); // GET, POST
    if(oParameters.strMethod!="GET" && oParameters.strMethod!="POST")
    {
      oParameters.booSuccess=false;
      oParameters.strStatusText='參數錯誤,本函數只接受 get 或 post!';
      oParameters.strResponseText="";
      return;
    }
    
    // method=GET
    var strAttachParameters4Get="";
    var straTmp=[];
    if(oParameters.hasOwnProperty("straPairs")==true)
    {
      for(var i=0; i<oParameters.straPairs.length; i++)
      { 
        straTmp.push
        (
          encodeURIComponent(oParameters.straPairs[i][0])
          + "=" 
          + encodeURIComponent(oParameters.straPairs[i][1])
        );
      }
    }
    var strEncodedParameters=straTmp.join("&");
    if(oParameters.strMethod=="GET")  { strAttachParameters4Get="?"+strEncodedParameters; }
    
    // method=POST
    var oFormData=new FormData();
    if(oParameters.hasOwnProperty("straPairs")==true)
    {
      for(var i=0; i<oParameters.straPairs.length; i++)
      {
        oFormData.append(oParameters.straPairs[i][0], oParameters.straPairs[i][1]);
      }
    }
    
    var strUrl="";
    if(oParameters.strMethod=="GET")
    {
      strUrl=oParameters.strAction+strAttachParameters4Get;
      var obj1={ method: oParameters.strMethod };
    }
    else
    {
      strUrl=oParameters.strAction;
      var obj1={ method: oParameters.strMethod, body: oFormData };
    }
    
    try
    {
      var oResponse=await fetch(strUrl, obj1);
      var strResponseText=await oResponse.text();
      oParameters.booSuccess=true;
      oParameters.strStatusText='';
      oParameters.strResponseText=strResponseText;
    }
    catch(oError)
    {
      oParameters.booSuccess=false;
      oParameters.strStatusText=oError.message;
      oParameters.strResponseText='';
    }
    
    console.log(oParameters);
  }
  
  async getOFetchSync(strUrl='', oInputData={})
  {
    // 使用範例
    //
    // var oFetchResult=await getOFetchSync(strUrl, oInputData);
    //
    // oFetchResult.booSuccess (true/false)
    // oFetchResult.oError 
    // oFetchResult.strResponseText
    // oFetchResult.oOutputData
    //
    // PHP 部分範例參考
    //
    // <?php
    //   
    //   $strJson=file_get_contents('php://input'); // 讀入 json 資料
    //   $oInpData=json_decode($strJson);
    //   
    //   $oOutData=array("words"=>"hello, world!");
    //   echo json_encode($oOutData, true); // 輸出 json 資料
    //   
    // ?>
    
    try
    {
      var oResponse=await fetch(
        strUrl,
        {
          method: 'POST', // *GET, POST, PUT, DELETE, etc.
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify(oInputData)
        }
      );
    }
    catch(oError)
    {
      return { booSuccess: false, oError: oError, strResponseText: "", oOutputData: {} };
    }
    
    try
    {
      var strText=await oResponse.text();
      var oOutputData=JSON.parse(strText);
    }
    catch(oError)
    {
      return { booSuccess: false, oError: oError, strResponseText: strText, oOutputData: {} };
    }
    
    return { booSuccess: true, oError: {}, strResponseText: strText, oOutputData: oOutputData };
  }  
  
  makeAnXhrSync(oParameters)
  {
    // // 範例參考
    // 
    // var oP={};
    // oP.strMethod="post"; // get 或 post
    // oP.strAction="a.php";
    // oP.strContentType="application/x-www-form-urlencoded; charset=UTF-8";
    // oP.straPairs=[
    //   ["name","John"],
    //   ["age","18"],
    //   ["salary","28000"],
    //   ["special","'\"=&?甚麼都來!"]
    // ];
    //
    // oCom.makeAnXhrSync(oP);
    //
    // if(oP.booSuccess==false) { console.log("error:"+oP.strStatusText); }
    // else                     { console.log(oP.strResponseText); }
    //   
    
    // 傳遞參數
    var straTmp=[];
    if(oParameters.hasOwnProperty("straPairs")==true)
    {
      for(var i=0; i<oParameters.straPairs.length; i++)
      { 
        straTmp.push
        (
          encodeURIComponent(oParameters.straPairs[i][0])
          + "=" 
          + encodeURIComponent(oParameters.straPairs[i][1])
        );
      }
    }
    var strEncodedParameters=straTmp.join("&");
    
    var strAttachParameters4Get="";
    var strAttachParameters4Post="";
    if(oParameters.strMethod=="get")  { strAttachParameters4Get="?"+strEncodedParameters; }
    if(oParameters.strMethod=="post") { strAttachParameters4Post=strEncodedParameters; }
    
    // 內容型態
    if(oParameters.hasOwnProperty('strContentType')==false)
      { oParameters.strContentType="application/x-www-form-urlencoded; charset=UTF-8"; }
    
    // 準備 XMLHttpRequest
    oParameters.booSuccess=false;
    oParameters.strStatusText='';
    oParameters.strResponseText='';
    try
    {
      const oXhr=new XMLHttpRequest();
      
      oXhr.open(
        oParameters.strMethod.toUpperCase(), 
        oParameters.strAction+strAttachParameters4Get, 
        false); // true:async, false;sync
      oXhr.setRequestHeader("Content-Type", oParameters.strContentType);
      oXhr.send(strAttachParameters4Post);
        
      if(oXhr.readyState===XMLHttpRequest.DONE)
      {
        oParameters.strStatusText=oXhr.statusText;
        oParameters.strResponseText=oXhr.responseText;
        
        var status=oXhr.status;
        if(status===0 || (status>=200 && status<400))
        { oParameters.booSuccess=true; }
      }
    }
    catch(e)
    {
      oParameters.strStatusText='Encountered an error!'+e;
    }
    
  }
  
  makeAnXhr(oParameters)
  {
    // // 範例參考
    // 
    // var oP={};
    // oP.strMethod="post"; // get 或 post
    // oP.strAction="a.php";
    // oP.strContentType="application/x-www-form-urlencoded; charset=UTF-8";
    // oP.straPairs=[
    //   ["name","John"],
    //   ["age","18"],
    //   ["salary","28000"],
    //   ["special","'\"=&?甚麼都來!"]
    // ];
    // oP.callbackSuccess=function(oXhr) { console.log(oXhr.responseText); };
    // oP.callbackFailure=function(oXhr) { console.log("error"+oXhr.status); };
    // oCom.makeAnXhr(oP);
    
    // 傳遞參數
    var straTmp=[];
    if(oParameters.hasOwnProperty("straPairs")==true)
    {
      for(var i=0; i<oParameters.straPairs.length; i++)
      { 
        straTmp.push
        (
          encodeURIComponent(oParameters.straPairs[i][0])
          + "=" 
          + encodeURIComponent(oParameters.straPairs[i][1])
        );
      }
    }
    var strEncodedParameters=straTmp.join("&");
    
    var strAttachParameters4Get="";
    var strAttachParameters4Post="";
    if(oParameters.strMethod=="get")  { strAttachParameters4Get="?"+strEncodedParameters; }
    if(oParameters.strMethod=="post") { strAttachParameters4Post=strEncodedParameters; }
    
    // 內容型態
    if(oParameters.hasOwnProperty('strContentType')==false)
      { oParameters.strContentType="application/x-www-form-urlencoded; charset=UTF-8"; }
    
    // 準備 XMLHttpRequest
    const oXhr=new XMLHttpRequest();
    
    oXhr.open(
      oParameters.strMethod.toUpperCase(), 
      oParameters.strAction+strAttachParameters4Get, 
      true); // true:async, false;sync
      
    oXhr.setRequestHeader("Content-Type", oParameters.strContentType);
    oXhr.onreadystatechange=function()
    {
      if(oXhr.readyState===XMLHttpRequest.DONE)
      {
        var status=oXhr.status;
        if(status===0 || (status>=200 && status<400))
        {
          oParameters.callbackSuccess(oXhr);
        }
        else
        {
          oParameters.callbackFailure(oXhr);
        }
      }
    }
    
    oXhr.send(strAttachParameters4Post);
  }
  
  makeAnXhr_form_post(oParameters)
  {
    // // 若有要上傳檔案,則此方法就很好用!
    // 
    // // 範例參考
    // 
    // var oP={};
    // oP.strAction="a.php";
    // oP.oFormElement=document.getElementById('myForm');
    // oP.callbackSuccess=function(oXhr) { console.log(oXhr.responseText); };
    // oP.callbackFailure=function(oXhr) { console.log("error"+oXhr.status); };
    // oCom.makeAnXhr_form_post(oP);
    
    // 準備 XMLHttpRequest
    const oXhr=new XMLHttpRequest();
    
    oXhr.open("POST", oParameters.strAction, true); // true:async, false;sync
      
    oXhr.onreadystatechange=function()
    {
      if(oXhr.readyState===XMLHttpRequest.DONE)
      {
        var status=oXhr.status;
        if(status===0 || (status>=200 && status<400))
          { oParameters.callbackSuccess(oXhr); }
        else
          { oParameters.callbackFailure(oXhr); }
      }
    }
    
    oXhr.send(new FormData(oParameters.oFormElement));
  }
  
  searchAndSelect(oTxt, aryOrFunc, strSearchMethod, strClassName, funcCallback, iWaitForMilliSeconds=1000)
  {
    // 使用方法
    // <input type="txt" value="" placedholder="" oninput="oCom.searchAndSelect(......);">
    
    // 
    // oTxt -- input type='txt' 的物件
    //
    // aryOrFunc -- 陣列時,程式會從中去找出符合條件的資料,組成新的一維陣列
    // aryOrFunc -- 函數時,內部會呼叫 aryOrFunc(strWord, strSearchMethod),請傳回符合條件的一維陣列
    //
    // strSearchMethod -- (byKeywordCS,byLeftCS,byRightCS,byKeywordCI,byLeftCI,byRightCI) 
    //                    CS is Case Sensitive. CI is Case Insensitive.
    //
    // funcCallback(strValue) -- 有選取才會呼叫
    //
    // iWaitForMilliSeconds -- 輸入完多久之後會列出選單
    //
    
    var oDate=new Date();
    window.setTimeout(
      function(o1, oParent) 
      {
        if(o1==oDate)
        {
          // 可能之前已有選單,只要有新的輸入,就把之前選單的清掉
          if(oTxt.hasAttribute("floatingSelect")==true)
          {
            var strTmpId=oTxt.getAttribute("floatingSelect");
            var oTmp=document.getElementById(strTmpId);
            if(oTmp) { oTmp.remove(); }
            oTxt.removeAttribute("floatingSelect");
          }
          
          var straFound=[];
          var strWord=oTxt.value;
          if(strWord!='')
          {
            if(Array.isArray(aryOrFunc)==true)
            {
              var straSource=aryOrFunc;
              for(var i=0; i<straSource.length; i++)
              {
                var iIdxCS=straSource[i].indexOf(strWord);
                var iIdxCI=straSource[i].toUpperCase().indexOf(strWord.toUpperCase());
                
                if((strSearchMethod=='byKeywordCS' && iIdxCS!=-1)
                || (strSearchMethod=='byKeywordCI' && iIdxCI!=-1)
                || (strSearchMethod=='byLeftCS' && iIdxCS==0)
                || (strSearchMethod=='byLeftCI' && iIdxCI==0)
                || (strSearchMethod=='byRightCS' && iIdxCS==(straSource[i].length-strWord.length))
                || (strSearchMethod=='byRightCI' && iIdxCI==(straSource[i].length-strWord.length)))
                {
                  straFound.push(straSource[i]);
                }
              }
            }
            else
            {
              straFound=aryOrFunc(strWord, strSearchMethod);
            }
          }
          
          oParent.floatingSelect(oTxt, straFound, strClassName, function(booSuccess, strValue){ if(booSuccess==true) { funcCallback(strValue); } });
        }
      }, iWaitForMilliSeconds, oDate, this);
      
  }
  
  floatingSelect(oTargetElement, straOption, strClassName, funcCallback)
  {
    // 正常情形↓
    //
    // straOption.length<1      回傳 fasle, "無資料可以選取"
    // double-click or [enter]  回傳 true,  strValue
    // [esc]                    回傳 false, "使用者取消選取"
    // focus-out                回傳 false, "失去焦點"
    //
    
    // 特殊情形↓
    //
    // 被 remove 掉
    
    // funcCallback(booSuccess, strValue)
    //
    
    if(straOption.length<1)
    {
      funcCallback(false, "無資料可以選取");
    }
    else
    {
      var oSelect=document.createElement('select');
      oSelect.setAttribute('size', '10');
      if(strClassName!='') { oSelect.setAttribute('class', strClassName); }
      oSelect.addEventListener(
        "dblclick",
        function()
        {
          if(oSelect.value=='exit20230601153930')
          {
            funcCallback(false, "使用者選取關閉"); 
            oSelect.remove();
          }
          else
          {
            funcCallback(true, oSelect.value);
            oSelect.remove();
          }
        }
      );
      
      oSelect.addEventListener(
        "keydown",
        function()
        {
          if(event.keyCode==13) // Enter
          {
            if(oSelect.value=='exit20230601153930')
            {
              funcCallback(false, "使用者選取關閉"); 
              oSelect.remove();
            }
            else
            {
              funcCallback(true, oSelect.value);
              oSelect.remove();
            }
          }
          else if(event.keyCode==27) // ESC
          {
            funcCallback(false, "使用者取消選取"); 
            oSelect.remove();
          }
        }
      );
      
      // 設定選項
      var oOption=document.createElement("option");
      oOption.innerHTML='[關閉]';
      oOption.value='exit20230601153930';
      oOption.setAttribute('selected',true);
      oSelect.appendChild(oOption);
      
      for(var i=0; i<straOption.length; i++)
      {
        var oOption=document.createElement("option");
        oOption.innerHTML=straOption[i];
        oOption.value=straOption[i];
        if(i==0) { oOption.setAttribute('selected',true); }
        oSelect.appendChild(oOption);
      }
      
      // 調整位置
      var iLeft=oTargetElement.offsetLeft+oTargetElement.clientLeft;
      var iTop=oTargetElement.offsetTop+oTargetElement.clientTop+oTargetElement.offsetHeight;
      var strLeft="left: "+iLeft+"px; ";
      var strTop="top: "+iTop+"px; ";
      oSelect.setAttribute('style', 'position: absolute; '+strLeft+strTop);
      
      // 理論上,在單一網頁的操作中,id 應該不會重複。
      var strId='id4FloatingSelect'+(new Date()).getTime()+Math.random();
      oSelect.setAttribute('id', strId);
      
      if(oTargetElement.hasAttribute("floatingSelect")==true)
      {
        var strTmpId=oTargetElement.getAttribute("floatingSelect");
        var oTmp=document.getElementById(strTmpId);
        if(oTmp) { oTmp.remove(); }
        oTargetElement.removeAttribute("floatingSelect")
      }
      oTargetElement.setAttribute("floatingSelect", strId);
      
      oTargetElement.insertAdjacentElement('afterend', oSelect);
    }
  }
  
  getBoo純粹阿拉伯數字(str1)
  {
    for(var i=0; i<str1.length; i++)
    {
      var strDigit=str1.substring(i,i+1);
      if(strDigit>="0" && strDigit<="9")
      {
      }
      else
      {
        return false;
      }
    }
    return true;
  }
  
  getStr盡量變成簡易日期(str1)
  {
    // 將日期變成八位數,也就是 "YYYYMMDD"
    
    str1=str1.split(" ").join(""); // 去掉所有空白
    str1=str1.split("/").join("-"); // 將 / 換成 -
    
    // 第零站:若原本是空白,就傳回空白
    if(str1=="") return str1;
    
    var stra=str1.split("-");
    
    // 第一站,有包含 / 或是 - 的日期
    if(stra.length==3)
    {
      if(this.getBoo純粹阿拉伯數字(stra[0])==true
      && this.getBoo純粹阿拉伯數字(stra[1])==true
      && this.getBoo純粹阿拉伯數字(stra[2])==true)
      {
        // 可能是 099-4-5 或是 2010-3-12
        if(stra[0].length>=2 && stra[0].length<=3)
        {
          // 民國年
          return ("0000"+(1911+parseInt(stra[0])).toString()).slice(-4)
            +("00"+parseInt(stra[1]).toString()).slice(-2)
            +("00"+parseInt(stra[2]).toString()).slice(-2);
        }
        else if(stra[0].length==4)
        {
          // 西元年
          return ("0000"+parseInt(stra[0]).toString()).slice(-4)
            +("00"+parseInt(stra[1]).toString()).slice(-2)
            +("00"+parseInt(stra[2]).toString()).slice(-2);
        }
      }
    }
    
    // 去掉多餘的 -
    str1=str1.split("-").join("");
    
    // 第二站,若非純阿拉伯數字的話,直接結束掉
    if(this.getBoo純粹阿拉伯數字(str1)==false) { return str1; }
    
    // 第三站,判斷民國 or 西元 or 其他
    if(str1.length==6)
    {
      // 例如 990214
      return ("0000"+(1911+parseInt(str1.substring(0,2))).toString()).slice(-4)
        +("00"+parseInt(str1.substring(2,4)).toString()).slice(-2)
        +("00"+parseInt(str1.substring(4,6)).toString()).slice(-2);
    }
    else if(str1.length==7)
    {
      // 例如 0981231
      return ("0000"+(1911+parseInt(str1.substring(0,3))).toString()).slice(-4)
        +("00"+parseInt(str1.substring(3,5)).toString()).slice(-2)
        +("00"+parseInt(str1.substring(5,7)).toString()).slice(-2);
    }
    else if(str1.length==8)
    {
      // 例如 20100314
      return str1;
    }
    else
    {
      // 未知的數字,不做修改囉!
      return str1;
    }
  }
  
  getStr盡量變成完整日期(str1, strDelimiter="/")
  {
    // 將日期變成十位數,也就是 "YYYY/MM/DD",分隔符號可以自訂。
    
    str1=this.getStr盡量變成簡易日期(str1);
    
    if(str1.length==8) // 可以正規化的,就進行,不行的就算了!
    {
      return str1.substring(0,4)
        +strDelimiter
        +str1.substring(4,6)
        +strDelimiter
        +str1.substring(6,8);
    }
    else
    {
      return str1;
    }
  }
  
  getStrTrimSpecial(str1)
  {
    return str1.split("\t").join("").split("\r").join("").split("\n").join("").split(String.fromCharCode(160)).join(" ").trim();
  }
  
  getStrToValue(str1)
  {
    // 特殊空白變成半型空白
    return str1.split(String.fromCharCode(160)).join(" ");
  }
  
  getStrToInnerHTML(str1)
  {
    return str1.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;").split(" ").join("&nbsp;").split("'").join("&#039;").split('"').join("&quot;");
  }
  
  getStrFromInnerHTML(str1)
  {
    return str1.split("&quot;").join('"').split("&#039;").join("'").split("&nbsp;").join(" ").split("&gt;").join(">").split("&lt;").join("<").split("&amp;").join("&");
  }
  
  getOResponse(strResponseText) // 讀取從 php 回來的資料集
  {
    var straResponseText=strResponseText.split("\r\n");

    if(straResponseText.length<2) { straResponseText.push(""); }
    if(straResponseText.length<3) { straResponseText.push(0); }
    if(straResponseText.length<4) { straResponseText.push(""); }
    if(straResponseText.length<5) { straResponseText.push(""); }
    if(straResponseText.length<6) { straResponseText.push(""); }
    
    var oR={
      str成功失敗:   straResponseText[0],
      str訊息:       straResponseText[1],
      iRows:         parseInt(straResponseText[2]),
      straFieldName: straResponseText[3].split("\t"),
      straTextType:  straResponseText[4].split("\t"), // "1"-文字, ""-其他
      straLine:      straResponseText.slice(5)
    }; 
    
    return oR;
  }

  getOResponseV2(strResponseText) // 讀取從 php 回來的資料集
  {
    var straResponseText=strResponseText.split("\r\n");

    if(straResponseText.length<2) { straResponseText.push(""); }
    if(straResponseText.length<3) { straResponseText.push(0); }
    if(straResponseText.length<4) { straResponseText.push(""); }
    if(straResponseText.length<5) { straResponseText.push(""); }
    if(straResponseText.length<6) { straResponseText.push(""); }
    
    var iRows=parseInt(straResponseText[2]);
    var straFieldName=straResponseText[3].split("\t");
    var straLine=straResponseText.slice(5);
    
    var oFieldNameMapping={};
    for(var iC=0; iC<straFieldName.length; iC++)
    {
      oFieldNameMapping[straFieldName[iC]]=iC;
    }
    
    var straRC=[];
    for(var iR=0; iR<iRows; iR++)
    {
      var straItem=straLine[iR].split("\t");
      straRC.push(straItem);
    }
    
    var oR={
      str成功失敗:        straResponseText[0],
      str訊息:            straResponseText[1],
      iRows:              iRows,
      straFieldName:      straFieldName,
      straTextType:       straResponseText[4].split("\t"), // "1"-文字, ""-其他
      straRC:             straRC,
      oFieldNameMapping:  oFieldNameMapping,
      getStrByIndex(iR,iC) 
      {
        if(iR<0 || iR>=this.iRows) { return ''; }
        if(iC<0 || iC>=this.straFieldName.length) { return ''; }
        return this.straRC[iR][iC];
      },
      getStrByName(iR,strCName) 
      {
        if(iR<0 || iR>=this.iRows) { return ''; }
        var iC=this.oFieldNameMapping[strCName];
        if(iC===undefined) { return "欄位名稱["+strCName+"]找不到"; }
        return this.straRC[iR][iC];
      }
    }; 
    
    return oR;
  }
  
  getStrNumberWithCommas(strNumber, iDigits)
  {
    var str1=Math.round(parseFloat(strNumber),iDigits);
    return str1.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
  }
  
  strChr27=String.fromCharCode(27);
}

var oCom=new c_liujiaje_com_common();