顯示具有 工作 標籤的文章。 顯示所有文章
顯示具有 工作 標籤的文章。 顯示所有文章

2024年8月1日 星期四

大阪 1990

姊姊上周颱風天跟同學去日本新潟縣苗場滑雪場參加 FUJI ROCK FESTIVAL ’24 音樂祭 (聽說草東也有去表演), 水某說明年也想去參加, 我想那就順便留一天去大阪尋訪我在 1990 年第一次出國到日本出差的地方唄! 那時出社會第一個工作是 IC 設計, 因為太菜功夫淺, 負責的 IC 樣品出來有問題 (樣品插上板子上電的那瞬間心臟可說極速跳動), 因此跑日本出差了三趟, 前後待了數月之久, 那時專案壓力下的苦悶心情至今仍印象深刻. 

多年來赴日旅遊時曾想抽空去尋訪一下當年工作的地方, 不過我已經忘記那時出差的確切地點, 只記得離大阪蠻近的. 凱米颱風走後的周末回鄉下時, 特地到鄉下老家樓上書房翻找, 終於在第一本護照的護套夾層中找到當時住過的商務旅館的名片與票根等資料, 原來當時出差的地點是位於大阪郊區的吹田市豐津町, 今日得空便將這些資訊掃描為圖檔紀錄如下 : 




這是第一次赴日時居住的 Parkside 商務旅館資訊上的三菱半導體 (MSC) 地址 :

MSC : 1-18 Toyotsu-Cho, Suita City. Osaka, 564 Japan (06) 3386088

這是當時副總的秘書 Lisa 影印給我, 然後叫我我手抄 MSC 地址, 不知 MSC 是否仍未於該棟大樓. 印象中旅館就在北大阪急行電鐵御堂津線江坂站附近, 而三菱半導體則是在地鐵的另一側, 每天都要從旅館拉著迷你電腦爬上天橋走到另一側的 MSC 大樓上班. 下面是 Parkside 旅館的名片 : 




間隔月餘第二次赴日時秘書改訂江坂中央旅館, 當時的名片也有留下 :



開第二版 IC 時三度赴日, 這時改住新大阪的 SEN-I CITY 旅館 :




週日 MSC 休假, 當時陪同我們去日本的菱華 (三菱電機台灣分公司) 工程師帶我們逛附近景點, 例如大阪城與姬路城, 京都與奈良等地, 找到當時的票根如下 : 





護照護套內還有一張出境證, 當時出國除了護照還要有這張, 不知道為啥 (內政部境管局發的, 當時部長還是許水德哩) :





護照內頁用訂書針訂了一張日本駐香港領事館發的渡航證明書 (因日本與台灣無邦交, 日本政府不願直接在台灣護照內頁上蓋簽證章, 可悲啊) : 





三十年前的護照封面 : 




內頁還存有當時所搭日亞航機票票根 :




還記得那時陪同赴日的菱華工程師毅光兄是香港僑生, 不僅會講廣東話, 而且英日語流利, 在他們的台北辦公室跑晶片模擬時常聽他接電話, 一會兒講粵語, 一會兒講日語, 一會兒又改講英語, 實在令我極為佩服. 


2025-08-23 補充 :

9 月中將與水某赴大阪京都旅遊, 想抽空去尋訪 30 多年前出差的日本三菱半導體, 根據地址查詢 Google 地圖位置在大阪府吹田市豊津町1-18 江坂大樓 (江坂公園對面, 隔著新御堂筋線) :





我問 ChatGPT 從梅田到江坂交通線, 答覆如下 :

搭地鐵路線建議 :
起點:梅田站(大阪市北區)
搭乘:地下鐵御堂筋線(赤色線)
方向:北行(往江坂 / 千里中央方向)
下車站:江坂站(Esaka Station)
大約 10 站,車程約 15 分鐘
出口:江坂站出口後步行
從江坂站 8 號或 9 號出口出站
步行至 豊津町1-18 エクラート江坂ビル,大約 5 分鐘
地鐵御堂筋線:大阪市中心到江坂最直接的路線
票價:大約 280〜310 日圓
時間:車程 15 分鐘 + 步行 5 分鐘

對, 沒錯, 那時搭地鐵聽到廣播千里中央, 就要準備下車了. 



2023年12月25日 星期一

同事的退休歡送會

今天老同事鄭老大屆齡退休, 咱辦公室在 Team 會議後舉辦線上歡送會, 中午上司提供豐富的便當, 每次有人退休規格都不同, 有人到了靜靜的退休, 有時又擴大舉辦聚會, 十幾年前還在大禮堂舉辦, 載歌載舞, 現在是今非昔比啊! 

看到有人退休我是既羨慕又畏懼, 羨慕的是不用每天刷卡, 畏懼的是老之將至 (老大說他已收到市政府寄來的老人卡). 查了一下我的 GitHub 網站首頁, 我還要七年半左右 : 




七年其實很快就過去了, 我得好好規劃第二人生了. 最近想到一個不錯的工作 : 水電工, 應該趁退休前去職訓局參加水電工培訓班, 雖然是學電機本科出身, 家中的電工問題難不倒我, 但此門分科分很細, 要做水電還是得跟師傅學一學, 特別是水的部分我不熟. 


2023-12-26 補充 :

今天找到高雄市勞工局職訓的水電工培訓班招生公告 (已過期), 似乎是平日全天上課 : 


職訓中心招生網頁如下 :




2022年5月18日 星期三

在家上班 0+7

週日晚上回到高雄看到菁菁做快篩, 原來她的接睫毛老師快篩陽, 她週六有去上課, 所以通知她也要快篩, 結果是陰性, 鬆了一口氣. 但過了兩天昨晚再驗居然兩條線! 我也做了快篩結果是陰, 我先跟上司通報家人快篩陽, 上司表示明日會幫我申請居家上班, 並將工作電腦送到住宅大樓. 

早上載菁菁去同盟路採檢回來後, 在公務電腦到達之前, 就用筆電收信先處理例行工作. 近 11 點時電腦送來後馬上安裝, 但這台老電腦居然又開不起來了, 重開機會進入 BIOS 不斷循環. 吃過午飯後與同事在 Line 討論了很久, 終於找到問題點, 原來 boot 不起來是啟動設定的 Boot Option 底下沒抓到硬碟 : 




正確設定如下 : 




點 "安全啟動選單" 進去在 "作業系統類型" 要選 "其他作業系統" 而不是 "Windows UEFI 模式" : 




最重要的是設好後要儲存設定重開機才會抓到啟動硬碟. 經過這番折騰後到了下午兩點多終於能順利開機, 可連線到公司的各個系統進行遠端維運作業了. 

四月底疫情開始往上爬升時公司就要求須有部分人力居家辦公, 那時因為還要接送菁菁上下學, 居家往返接送反而更麻煩, 而且要搬公務電腦回家進行設定也很麻煩, 所以我當時沒申請. 但今天實際操作連線發現並沒有那麼麻煩, 加上菁菁已經不用去學校, 所以解隔離後乾脆就繼續居家上班唄. 

2020年9月5日 星期六

辦公室電腦椅到貨

9/1 去家樂福花了 3280 元買了一張克斯電腦椅, 等了三天昨日下午終於送到公司警衛室, 搬上來後立刻拆封使用, 真的比公司買的好座多了, 而且它的背可調成後傾 (不會倒), 可以當午休椅用 :




我七月去家樂福就試坐了全部電腦椅, 覺得這台最好坐, 但直到前天才去訂購, 滿 1500 免費配送 (廠商直送, 此為寄售品). 公司的辦公椅太硬, 坐久了屁股與大腿會痛, 想說還要很久才退休, 花點錢買張好椅子是值得的.

2020年8月22日 星期六

jQuery UI SPA 應用程式 (五) : 字串處理函式庫

今天進入 jQuery UI 應用程式重頭戲 : 字串處理函式庫, 因為從遠端機台擷取到的純文字資料有其特定格式, 必須利用文字處理函數進行清洗, 再餵給 DataTables 表格呈現與篩選, 或者用來產生要下給遠端機台的指令, 所以字串處理可說是整個自動化專案中的關鍵工具.

這個函式庫的來源有兩個, 一是以前用 PHP 寫爬蟲程式時找到的一本好書 :

# 網路機器人, 網路蜘蛛與網路爬蟲-PHP/CURL 程式設計指南 (第二版, 碁峰出版)


Source : 金石堂


其範例程式下載網址如下 :

http://webbotsspidersscreenscrapers.com/
http://webbotsspidersscreenscrapers.com/DSP_download.php

我參考了其中的字串剖析函式庫 LIB_parse.php 進行改寫, 裡面的兩個函數 return_between() 與 parse_array() 是此函式庫的主角, 也是進行文本剖析的利器. 另外一個參考來源是網路上的 Python 字串處理函式庫:

http://docs.python.org/release/2.5.2/lib/string-methods.html

我將這些 PHP 與 Python 字串處理函式改寫為如下之 Javascript 版, 每一個函數都指派為 String 物件的 prototype 屬性以擴充 String 物件的功能, 這樣用法就與 Javascript 字串物件的函數完全一樣了 :

//parse.js
String.prototype.split_string=split_string;
String.prototype.return_between=return_between;
String.prototype.parse_array=parse_array;
String.prototype.remove=remove;
String.prototype.get_attribute=get_attribute;
String.prototype.trim=trim;
String.prototype.ltrim=ltrim;
String.prototype.rtrim=rtrim;
String.prototype.isdigit=isdigit;
String.prototype.startswith=startswith;
String.prototype.endswith=endswith;
String.prototype.title=title;
String.prototype.swapcase=swapcase;
String.prototype.zfill=zfill;
String.prototype.ljust=ljust;
String.prototype.rjust=rjust;
String.prototype.encode=encode;
String.prototype.decode=decode;
/*-----------------------------------------------------------------------------
split_string(delineator, desired, type)
功能 :
  此函數會在一個待剖析字串中搜尋指定之界定字串 delineator, 依據所需要的位置
  desired, 傳回在該界定字串之前或之後的子字串, 型態 type 用來設定傳回值中是否
  要包含界定字串. 此函數所處理之字串與大小寫無關 (包括參數).
參數 :                                   
  delineator : 界定字串 
  desired    : "before" : 傳回界定字串前之子字串
               "after"  : 傳回界定字串後之子字串     
  type       : "incl"   : 包含界定字串 
               "excl"   : 不包含界定字串
-----------------------------------------------------------------------------*/
function split_string(delineator, desired, type) {
  //處理預設值
  var desired = String(desired).toLowerCase() || "before";
  var type = String(type).toLowerCase() || "excl";
  //為與大小寫無關, 全部轉為小寫處理
  var lc_str = String(this).toLowerCase();
  var marker = delineator.toLowerCase();
  if (lc_str.indexOf(marker, 0) == -1) { //沒找到分割字串:傳回 ""
     return "";
     }
  else { //有找到分割字串
     if (desired == "before") {  //傳回分割字串前的部分
        if (type == "excl") { //不包含分割字串:不必加分割字串本身     
           var split_here = lc_str.indexOf(marker, 0);
           }
        else { //包含分割字串:要加計分割字串本身
           var split_here = lc_str.indexOf(marker, 0) + marker.length;
           } 
        var parsed_string = this.substring(0, split_here);
        }
     else { //傳回界定字串後的部分 "after"
        if (type == "excl") { //不包含分割字串:要扣除分割字串本身
           var split_here = lc_str.indexOf(marker, 0) + marker.length;
           }
        else { //包含分割字串:要加計分割字串本身
           var split_here = lc_str.indexOf(marker, 0);
           }     
        var parsed_string = this.substring(split_here, lc_str.length + 1);
        }
     }
  return parsed_string;
  }
/*-----------------------------------------------------------------------------
return_between(start, stop, type)
功能 :
  此函數會在待剖析字串字串中搜尋指定之起始字串 start 與結束字串 stop, 傳回在該組
  界定字串之間的子字串, 型態 type 用來設定傳回值中是否要包含組界定字串.
  此函數所處理之字串與大小寫無關 (包括參數).
參數 :                                 
  start : 起始字串 
  stop  : 結束字串     
  type  : "incl"   : 包含界定字串 
          "excl"   : 不包含界定字串
-----------------------------------------------------------------------------*/
function return_between(start, stop, type) {
  //傳回起始字串後面的部分
  var temp = this.split_string(start, "AFTER", type);
  //傳回結束字串前面的部分
  return temp.split_string(stop, "BEFORE", type);
  }
/*-----------------------------------------------------------------------------
parse_array(start, stop)
功能 :
  此函數會在待剖析字串字串中重複搜尋指定之起始字串 start 與結束字串 stop 間的
  子字串, 並把每次符合的子字串放入陣列中傳回. 傳回值為陣列, 元素中包含界定字串.
  此函數所處理之字串與大小寫無關 (包括參數).
參數 :                                 
  start : 起始字串 
  stop  : 結束字串
-----------------------------------------------------------------------------*/
function parse_array(start, stop) {
  var reg=new RegExp("(" + start + "([\\s\\S]*?)" + stop + ")","ig");
  return this.match(reg);  //傳回符合之陣列
  }
/*-----------------------------------------------------------------------------
remove(start, stop)
功能 :
  此函數會在待剖析字串中重複搜尋指定之起始字串 start 與結束字串 stop 間的
  子字串, 並把每次符合的子字串從待剖析字串中刪除. 傳回值為刪除後之字串.
  注意, 刪除子字串時會連同界定字串一起刪除.
  此函數所處理之字串與大小寫無關 (包括參數).
參數 :                                 
  start : 起始字串 
  stop  : 結束字串
-----------------------------------------------------------------------------*/
function remove(start, stop) {
  var remove_array = this.parse_array(start, stop);  //傳回要移除的子字串陣列
  var string = this;
  if (remove_array != null) { //有找到子字串:執行刪除
    for (var i = 0; i < remove_array.length; i++) {    //依序移除
      var reg = new RegExp(remove_array[i],"ig");    //要刪除之子字串 reg 物件
      var string = string.replace(reg, "");
      }
    return string;
    }
  else {return this;}  //沒有找到子字串:傳回待剖析字串本身
  }
/*-----------------------------------------------------------------------------
get_attribute(attribute)
功能 :
  此函數會在待剖析 HTML 字串中搜尋指定之屬性值.
參數 :       
  attribute : HTML 元素之屬性, 例如 style, class 等
-----------------------------------------------------------------------------*/
function get_attribute(attribute) {
  var cleaned_html = this.tidy_html();             //整理 tag 元素
  cleaned_html = cleaned_html.replace("\r", "");   //去除 CR
  cleaned_html = cleaned_html.replace("\n", "");   //去除 LF
  var start=attribute.toLowerCase() + "=\"";       //屬性開頭 (全小寫)
  return cleaned_html.return_between(start, "\"", "EXCL");   //回傳屬性值
  }
//=====以下函數來自 VBscript=====//
/*-----------------------------------------------------------------------------
trim()
  此函數會刪除字串開頭與結尾處之空白字元後傳回 (與 VBscript 之 Trim 同).
  空白字元, 包括空格(space),水平定位(tab),跳頁(form-feed)與換列(linefeed),
  相當於 [ \f\n\r\t\v\u00A0\u2028\u2029]
參數 :                                   
  無
-----------------------------------------------------------------------------*/
function trim() {
  return this.replace(/(^\s*)|(\s*$)/g,"");
  }
/*-----------------------------------------------------------------------------
ltrim()
  此函數會刪除字串開頭處之空白字元後傳回 (與 VBscript 之 Ltrim 同).
參數 :                                   
  無
-----------------------------------------------------------------------------*/
function ltrim() {
  return this.replace(/(^\s*)/g, "");
  }
/*-----------------------------------------------------------------------------
rtrim()
  此函數會刪除字串結尾處之空白字元後傳回 (與 VBscript 之 Rtrim 同).
參數 :                                   
  無
-----------------------------------------------------------------------------*/
function rtrim() {
  return this.replace(/(\s*$)/g, "");
  }
//======以下函數改寫自 Python=====//
//參考 : http://docs.python.org/release/2.5.2/lib/string-methods.html
/*-----------------------------------------------------------------------------
isdigit()
  此函數會判斷字串內容是否全為數字 (與 Python 之 isdigit 同).
參數 :                                   
  無
-----------------------------------------------------------------------------*/
function isdigit() {
  return str.match(/D/)==null;
  }
/*-----------------------------------------------------------------------------
startswith(prefix[,start[, end]])
  此函數會判斷字串內容是否以 prefix 開頭 (與 Python 之 startwith 同).
  備選參數 start 與 end 可指定比對之起訖位置, 預設為從頭 (0) 比到尾 (length-1).
參數 :                                   
  無
-----------------------------------------------------------------------------*/
function startswith(prefix, start, end) {
  var start=start || 0;          //預設值
  var end=end || this.length-1;  //預設值
  var haystack=this.substring(start,end+1);
  var needle=new RegExp("^" + prefix,"ig");  //是否以 prefix 結尾 (不分大小寫)
  WScript.Echo(haystack);
  return needle.test(haystack);
  }
/*-----------------------------------------------------------------------------
endswith(prefix[,start[, end]])
  此函數會判斷字串內容是否以 prefix 開頭 (與 Python 之 startwith 同).
  備選參數 start 與 end 可指定比對之起訖位置, 預設為從頭 (0) 比到尾 (length-1).
參數 :                                   
  無
-----------------------------------------------------------------------------*/
function endswith(prefix, start, end) {
  var start=start || 0;          //預設值
  var end=end || this.length-1;  //預設值
  var haystack=this.substring(start,end+1);
  var needle=new RegExp(prefix + "$","ig");  //是否以 prefix 結尾 (不分大小寫)
  WScript.Echo(haystack);
  return needle.test(haystack);
  }
/*-----------------------------------------------------------------------------
title()
  此函數會將字串 (英文) 中每一個字的第一個字元改成大寫, 其餘字元改為小寫後傳回
  (與 Python 之 title 同).
參數 :                                   
  無
-----------------------------------------------------------------------------*/
function title() {
  var words=this.replace(/[ ]{2,}/g," ").split(" ");  //兩個以上連續空格改為1個
  for (var i=0; i<words.length; i++) {
    var first=words[i].charAt(0).toUpperCase();  //每字首字元大寫
    var others=words[i].substr(1).toLowerCase();  //第2字元至最後小寫
    words[i]=first + others;  //重組回字
    }
  return words.join(" ");  //重組回字串傳回
  };
/*-----------------------------------------------------------------------------
swapcase(prefix[,start[, end]])
  此函數會將字串 (英文) 中每一個小寫字元改成大寫, 大寫字元改成小寫後傳回
  (與 Python 之 swapcase 同).
參數 :                                   
  無
-----------------------------------------------------------------------------*/
function swapcase() {
  var arr=[];  //暫存字元用
  var lower=/[a-z]/;   //小寫字元
  var upper=/[A-Z]/;  //大寫字元
  for (var i=0; i<this.length; i++) {  //走訪每一個字元
    if (lower.test(this.charAt(i))) {  //小寫字母->改成大寫
      arr.push(this.charAt(i).toUpperCase());
      }
    else if (upper.test(this.charAt(i))) {  //大寫字母->改成小寫
      arr.push(this.charAt(i).toLowerCase());
      }
    else {arr.push(this.charAt(i));}
    }
  return arr.join(""); //串接全部字元
  };
/*-----------------------------------------------------------------------------
zfill(width)
  此函數會將數字字串前面填滿 0 使得總長為 width 字元 (與 Python 之 isalnum 同).
  若字串長度小於 width, 則無法填 0 而傳回字串本身.
參數 :                                   
  width : 填補之後字串總長度
傳回值 :
  字串
-----------------------------------------------------------------------------*/
function zfill(width) {
  var zeros="";  //補0字串初始值
  if (width < this.length) {return this;} //width小於字串長度:不用補,傳回本身
  else {  //需要補滿 0
     for (var i=0; i<width-this.length; i++) {zeros += "0";}  //製作補0字串
     return zeros + this;  //前面冠上補0字串
     }
  }
/*-----------------------------------------------------------------------------
ljust(width[, fillchar])
  此函數會在字串前面以 fillchar 字元填滿使得總長為 width 字元 (與 Python 之
  ljust 同). 若字串長度小於 width, 則無法填滿而傳回字串本身. fillchar 預設為
  空格 space=" ".
參數 :                                   
  width    : 填補之後字串總長度
  fillchar : 填補字元
傳回值 :
  字串
-----------------------------------------------------------------------------*/
function ljust(width, fillchar) {
  var fillchar=fillchar || " ";  //填補字元預設值為 " "
  var filler="";                 //填補字串初始值
  if (width < this.length) {return this;} //width小於字串長度:不用補,傳回本身
  else {  //需要補滿
     for (var i=0; i<width-this.length; i++) {filler += fillchar;} //填補字串
     return filler + this;  //前面冠上填補字串
     }
  }
/*-----------------------------------------------------------------------------
rjust(width[, fillchar])
  此函數會在字串後面以 fillchar 字元填滿使得總長為 width 字元 (與 Python 之
  ljust 同). 若字串長度小於 width, 則無法填滿而傳回字串本身. fillchar 預設為
  空格 space=" ".
參數 :                                   
  width    : 填補之後字串總長度
  fillchar : 填補字元
傳回值 :
  字串
-----------------------------------------------------------------------------*/
function rjust(width, fillchar) {
  var fillchar=fillchar || " ";  //填補字元預設值為 " "
  var filler="";                 //填補字串初始值
  if (width < this.length) {return this;} //width小於字串長度:不用補,傳回本身
  else {  //需要補滿
     for (var i=0; i<width-this.length; i++) {filler += fillchar;} //填補字串
     return this + filler;  //後面冠上填補字串
     }
  }
/*-----------------------------------------------------------------------------
encode(key)
  此函數會依據傳入之 key 對字串進行特定編碼. 其相對之解碼函式為 decode(), 必須
  傳入相同 key 才會解出原始字串.
參數 :                                   
  key : 編碼所用之鍵字串.
傳回值 :
  由 key 字串中之字元編碼所組成之加密字串
源碼 : http://www.360doc.com/content/13/0806/13/1073512_305112816.shtml
-----------------------------------------------------------------------------*/
function encode(key) {
  if (!key) {
    var key="8ABC7DLO5MN6Z9EFGdeJfghijkHIVrstuvwWSTUXYabclmnopqKPQRxyz01234";
    }
  var nl=this.length;
  var t=[];
  var a,b,c,x,m=function(y){t[t.length]=key.charAt(y)};
  var N=key.length;
  var N2=N*N,N5=N*5;
  for (x=0;x<nl;x++) {
    a=this.charCodeAt(x);
    if (a<N5) m(Math.floor(a/N)),m(a%N);
    else m(Math.floor(a/N2)+5),m(Math.floor(a/N)%N),m(a%N);
    }
  var s=t.join("");
  return String(s.length).length+String(s.length)+s;
  };
/*-----------------------------------------------------------------------------
decode(key)
  此函數會依據傳入之 key 對字串進行特定解碼. 其相對之編碼函式為 encode(), 必須
  傳入編碼所用之相同 key 才會解出原始字串.
參數 :                                   
  key : 解碼所用之鍵字串.
傳回值 :
  由 key 字串中之字元解碼所組成之還原字串
源碼 : http://www.360doc.com/content/13/0806/13/1073512_305112816.shtml
-----------------------------------------------------------------------------*/
function decode(key) {
  if (!key) {
    var key="8ABC7DLO5MN6Z9EFGdeJfghijkHIVrstuvwWSTUXYabclmnopqKPQRxyz01234";
    }
  var c=this.charAt(0)*1;
  if (isNaN(c)) return "";
  c=this.substr(1,c)*1;
  if (isNaN(c)) return "";
  var nl=this.length;
  var t=[];
  var a,f,b,x=String(c).length+1;
  var enc=this;
  var m=function(y){return key.indexOf(enc.charAt(y))};
  var N=key.length;
  if (nl!=x+c) return "";
  while (x<nl) {
    a=m(x++)
    if (a<5)f=a*N+m(x);
    else f=(a-5)*N*N+m(x)*N+m(x+=1);
    t[t.length]=String.fromCharCode(f);
    x++;
    }
  return t.join("");
  };

其中最重要的函數是 return_between(start, end, type), 它使用正規表達式來取得目標字串, 第一個參數 start 是要擷取之資料前面之起始標記; 第二個參數 end 為結束標記, type 用來指定傳回結果是否要包含起始與結束標記, "incl" 為包含, "excl" 為不包含.

將此函式庫放在專案的 /lib 資料夾下 :




下面是這些函數的測試範例 :


範例 10 : 用 return_between() 擷取子字串 [原始碼]

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>jQuery UI Single Page Application</title>
  <script src="jquery/jquery.js"></script>
  <script src="jquery/jquery-ui.js"></script>
  <script src="jquery/datatables.js"></script>
  <script src="lib/file.js"></script>
  <script src="lib/parse.js"></script>
  <link id="theme" href="jquery/themes/hot-sneaks/jquery-ui.css" rel="stylesheet">
  <link href="jquery/datatables.css" rel="stylesheet">
  <style>
    body {
      font-family: Arial, Helvetica, sans-serif;
      font-size:10px;
      }
  </style>
</head>
<body>
  <!-- 頁嵌面板 -->
  <div id="tabs">
    <ul>
      <li><a href="#tabs-1">tab1</a></li>
      <li><a href="#tabs-2">tab2</a></li>
      <li><a href="#tabs-3">tab3</a></li>
    </ul>
    <div id="tabs-1">
      <div id="data" class="ui-state-highlight ui-corner-all" style="margin-top: 10px; margin-bottom: 10px;padding: 5px;">align="center" height="25"</div>
      <button id="get_align" class="ui-button ui-widget ui-corner-all">擷取 align</button>
      <button id="get_height" class="ui-button ui-widget ui-corner-all">擷取 height</button>
      <script>
        $(function(){
          //監聽按鈕之 click 事件
          $("#get_align").click(function(e) {
            e.preventDefault();
            var data=$("#data").html();
            var str=data.return_between('align="', '"', 'excl');
            $("#msgbox").html(str);
            $("#msgbox").dialog("open");
            });
          //監聽按鈕之 click 事件
          $("#get_height").click(function(e) {
            e.preventDefault();
            var data=$("#data").html();
            var str=data.return_between('height="', '"', 'excl');
            $("#msgbox").html(str);
            $("#msgbox").dialog("open");
            });
          });
      </script>
    </div>
    <div id="tabs-2">
    </div>
    <div id="tabs-3">
    </div>
  </div>
  <script>
    $(function(){
      $("#tabs" ).tabs();
      }); 
  </script>
  <!-- 訊息盒 -->
  <div id="msgbox" title="訊息"></div>
  <script>
    $(function(){
      //建立訊息盒
      $("#msgbox").dialog({
        title: "訊息",
        autoOpen: false,
        buttons: {
          "確定": function() {$(this).dialog("close");}
          }
        });
      });
  </script>
</body>
</html>

此網頁在 id=data 的 div 元素中放置字串內容 align="center" height="25", 按下按鈕後會呼叫 return_between() 分別擷取 align 與 height 之屬性值, 結果如下 : 










可見 return_between() 可以擷取起始與結束標記之間的子字串.

下面的範例則是測試 parse_array() 函數, 此函數會將字串中多組由起始與結束標記包起來子字串都擷取出來, 放在陣列中傳回 :


範例 11 : 用 parse_array() 擷取子字串陣列

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>jQuery UI Single Page Application</title>
  <script src="jquery/jquery.js"></script>
  <script src="jquery/jquery-ui.js"></script>
  <script src="jquery/datatables.js"></script>
  <script src="lib/file.js"></script>
  <script src="lib/parse.js"></script>
  <link id="theme" href="jquery/themes/hot-sneaks/jquery-ui.css" rel="stylesheet">
  <link href="jquery/datatables.css" rel="stylesheet">
  <style>
    body {
      font-family: Arial, Helvetica, sans-serif;
      font-size:10px;
      }
  </style>
</head>
<body>
  <!-- 頁嵌面板 -->
  <div id="tabs">
    <ul>
      <li><a href="#tabs-1">tab1</a></li>
      <li><a href="#tabs-2">tab2</a></li>
      <li><a href="#tabs-3">tab3</a></li>
    </ul>
    <div id="tabs-1">
      <input id="data" style="width: 100%; margin-top: 10px; margin-bottom: 10px" value="<td>1</td><td>2</td><td>3</td><td>4</td><td>5</td>"><br>
      <input id="out" style="width: 100%; margin-top: 10px; margin-bottom: 10px"<br>
      <button id="get_cell_content" class="ui-button ui-widget ui-corner-all">擷取儲存格中的內容</button>
      <script>
        $(function(){
          //監聽按鈕之 click 事件
          $("#get_cell_content").click(function(e) {
            var data=$("#data").val();
            var arr=data.parse_array('<td>', '</td>');
            $("#out").val(arr.join());
            });
          });
      </script>
    </div>
    <div id="tabs-2">
    </div>
    <div id="tabs-3">
    </div>
  </div>
  <script>
    $(function(){
      $("#tabs" ).tabs();
      }); 
  </script>
</body>
</html>

此例中有兩個 input 文字欄位, id=data 的欄位存放待剖析之字串; 而 id=out 的欄位則用來顯示 parse_array() 傳回來的陣列 (用 join 方法轉成字串), 結果如下 :




可見 parse_array() 在擷取子字串時不會刪除起始與結束標記, 這可以呼叫 replace() 方法處理.

2020年8月21日 星期五

jQuery UI SPA 應用程式 (四) : 檔案處理函式庫

今天繼續幹活, 目標是整理很久之前寫好的 Javascript 函式庫, 我將其中伺服端部分的程式碼刪除以便用在本次專案上. 由於資安限制不能安裝與使用資料庫, 只好用檔案處理方式來協助作業自動化, 因此檔案處理函式庫在整個專案中扮演關鍵角色.

刪減後的函式庫檔案 file.js 如下所示, 此函式庫使用微軟 ActiveX 技術, 因此只能在 IE 瀏覽器上運作 : 


1. 匯入函數 :   

此函數用來讀取 js 程式 (函式) 並執行其中的頂層程式碼.

/*-----------------------------------------------------------------------------
include(filename)
功能 : 
  此函數用來匯入其他外部 Javascript 檔. 僅限於 Client 端之 WSH 應用中.
參數 :                                   
  filename  : 外部 Javascript 檔名 (字串)   
傳回值 :
  無/null
範例 : 
  include("parse.js");    
-----------------------------------------------------------------------------*/
function include(filename) {
  try {
       var FSO=new ActiveXObject ("Scripting.FileSystemObject");
       var TXO=FSO.openTextFile(filename,1);
       var fileData=TXO.readAll();
       eval(fileData);  //執行 JS 檔內容
       TXO.Close();
       TXO = null;
       FSO = null;
      }
  catch (e) {return e.description;}
  }


2. 讀取文字檔案 :     

函式 read_file() 用來讀取文字檔, 傳回整個檔案內容 (字串); read_lines() 則逐行讀取文字檔, 傳回值為檔案中各行依序組成之陣列.

/*-----------------------------------------------------------------------------
read_file(filename)
功能 : 
  此函數用來讀取外部文字檔, 結果以字串傳回.
參數 :                                   
  filename  : 文字檔檔名 (含路徑)   
傳回值 :
  成功傳回檔案內容字串, 失敗傳回原因字串
範例 : 
  var fileData=read_file("test.log");    
-----------------------------------------------------------------------------*/
function read_file(filename) {
  try {
      var FSO=new ActiveXObject("Scripting.FileSystemObject");
      var TXO=FSO.openTextFile(filename,1,false);
      var fileData=TXO.readAll();
      TXO.Close();
      TXO=null;
      FSO=null;
      return fileData;
      }
  catch (e) {return e.description;}
  }
/*-----------------------------------------------------------------------------
read_lines(filename)
功能 : 
  此函數用來讀取外部文字檔, 並以分行符號拆分每列後儲存在陣列中傳回.
參數 :                                   
  filename  : 文字檔檔名 (含路徑)   
傳回值 :
  成功傳回陣列, 失敗傳回原因
範例 : 
  var array_lines=read_lines("test.log");    
-----------------------------------------------------------------------------*/
function read_lines(filename) {
  try {
      var FSO=new ActiveXObject("Scripting.FileSystemObject");
      var TXO=FSO.openTextFile(filename,1,false);
      var array_lines=new Array();
      while (!TXO.atEndOfStream) {
            array_lines.push(TXO.ReadLine());  //讀取每行放入陣列中
            }
      TXO.Close();
      TXO=null;
      FSO=null;
      return array_lines;
      }
  catch (e) {return e.description;}
  }


3. 寫入文字檔 :  

函式 write_file() 將字串以覆蓋或新建方式寫入外部文字檔; append() 是將字串貼附到檔尾; 而prepend() 則是將字串貼附到檔頭. 

/*-----------------------------------------------------------------------------
write_file(filename,text)
功能 : 
  此函數用來將純文字寫入外部文字檔 (覆蓋或新建).
參數 :                                   
  filename  : 文字檔檔名 (含路徑)   
  text      : 檔案內容   
傳回值 :
  成功傳回 1, 失敗傳回原因
範例 : 
  var result=write_file("test.log", "This is a book");    
-----------------------------------------------------------------------------*/  
function write_file(filename,text) {
  try {
      var FSO=new ActiveXObject("Scripting.FileSystemObject");
      var TXO=FSO.openTextFile (filename,2,true); //2=寫入,true=新建
      TXO.Write(text); //寫入檔案
      TXO.Close();
      FSO=null;
      return 1;
      }
  catch(e) {return e.description;}
  }
/*-----------------------------------------------------------------------------
append(filename,text)
功能 : 
  此函數用來將純文字寫入外部文字檔後面(不存在就新建).
參數 :                                   
  filename  : 文字檔檔名 (含路徑)   
  text      : 檔案內容   
傳回值 :
  成功傳回 1, 失敗傳回原因字串
範例 : 
  var result=append("test.log", "This is a book");    
-----------------------------------------------------------------------------*/  
function append(filename,text) {
  try {
      var FSO=new ActiveXObject("Scripting.FileSystemObject");
      var TXO=FSO.openTextFile(filename,8,true); //8=附加,true=新建
      TXO.Write(text); //寫入檔案
      TXO.Close();
      FSO=null;
      return 1;    
      }
  catch(e) {return e.description;}
  }
/*-----------------------------------------------------------------------------
prepend(filename,text)
功能 : 
  此函數用來將純文字寫入外部文字檔前面(不存在就新建).
參數 :                                   
  filename  : 文字檔檔名 (含路徑)   
  text      : 檔案內容   
傳回值 :
  成功傳回 1, 失敗傳回原因字串
範例 : 
  var result=prepend("test.log", "This is a book");    
-----------------------------------------------------------------------------*/  
function prepend(filename,text) {
  var new_text=text + read_file(filename);  //串接
  return write_file(filename,new_text); 
  }


4. 刪除文字檔部分內容 : 

函式 remove_lines() 會刪除文字檔中指定之行數 (0 起始); remove_prelines() 用來刪除文字檔指定之前面幾行; 而 emove_lastlines() 則刪除文字檔指定之最後幾行. 

/*-----------------------------------------------------------------------------
remove_lines(filename,lines_array)
功能 : 
  此函數用來移除文字檔指定之行.
參數 :                                   
  filename     : 文字檔檔名 (含路徑)   
  lines_array  : 要移除之行數陣列 (0 起算)  
傳回值 :
  成功傳回 1, 失敗傳回原因字串
範例 : 
  var result=remove_lines("test.log", [0]);    
  var result=remove_lines("test.log", [2,4,6]);    
-----------------------------------------------------------------------------*/  
function remove_lines(filename,lines_array) {
  var lines_array=lines_array.sort();  //行號排序,以便取出要刪的最後一行行數
  var text=read_lines(filename);  //讀取檔案成陣列
  var break_point=lines_array[lines_array.length-1] + 1;  //斷點
  var pre=text.slice(0, break_point); //前半部 (要處理刪除作業)
  //剩下的後半部陣列不須處理刪除作業
  var left=text.slice(break_point); //選取斷點至陣列尾
  var tmp=new Array();
  var line_str=lines_array.join();  //把欲刪除行號組成字串
  for (var i = 0; i < pre.length; i++) {  //沒在刪除名單的放入 tmp 陣列
      if (line_str.indexOf(i.toString()) == -1 ) {tmp.push(pre[i]);} //不刪除
      else {continue;}  //有在刪除名單的不存入 tmp : 刪除
      }
  tmp=tmp.concat(left);  //串接刪除後的前半部與後半部串接
  return write_file(filename,tmp.join("\r\n")); 
  }
/*-----------------------------------------------------------------------------
remove_prelines(filename,numbers)
功能 : 
  此函數用來移除文字檔最前面指定之行數.
參數 :                                   
  filename  : 文字檔檔名 (含路徑)   
  numbers   : 移除之行數   
傳回值 :
  成功傳回 1, 失敗傳回原因字串
範例 : 
  var result=remove_prelines("test.log", 2);    
-----------------------------------------------------------------------------*/  
function remove_prelines(filename,numbers) {
  var lines=read_lines(filename);  //
  for (var i = 0; i < numbers; i++) {lines.shift();}
  return write_file(filename,lines.join("\r\n")); 
  }
/*-----------------------------------------------------------------------------
remove_lastlines(filename,numbers)
功能 : 
  此函數用來移除文字檔最後面指定之行數.
參數 :                                   
  filename  : 文字檔檔名 (含路徑)   
  numbers   : 移除之行數   
傳回值 :
  成功傳回 1, 失敗傳回原因字串
範例 : 
  var result=remove_lastlines("test.log", 2);    
-----------------------------------------------------------------------------*/  
function remove_lastlines(filename,numbers) {
  var lines=read_lines(filename);  //讀進檔案為陣列
  lines.reverse();  //陣列倒序
  for (var i = 0; i < numbers; i++) {lines.shift();}  //刪除前面幾列
  lines.reverse();  //陣列倒序回去
  return write_file(filename,lines.join("\r\n")); 
  }


5. 檔案目錄資訊 : 

函式 get_files() 會以陣列傳回指定目錄下之檔案列表; file_exist() 用來檢查指定之檔案是否存在 (存在傳回 1); delete_file() 用來刪除指定之檔案 (成功傳回 1), get_folder() 則傳回網頁檔所在之本機路徑. 

/*-----------------------------------------------------------------------------
get_files(folder)
功能 : 
  此函數用來取得指定目錄下的檔案列表, 以陣列傳回.
參數 :                                   
  folder  : 檔案路徑 (注意, 目錄需用兩個倒斜線分隔) 
傳回值 :
  陣列或失敗原因
範例 : 
  var files=get_files("my_doc");    
  var files=get_files("c:\\test\\my_doc");    
-----------------------------------------------------------------------------*/  
function get_files(folder) {
  try {
      var FSO=new ActiveXObject("Scripting.FileSystemObject");
      var folderObj=FSO.GetFolder(folder); 
      var enumObj=new Enumerator(folderObj.Files); 
      var filesArray=new Array();
      for (;!enumObj.atEnd();enumObj.moveNext()) {      
          filesArray.push(enumObj.item().Name);
          }
      folderObj=null;
      enumObj=null;
      FSO=null;
      return filesArray;   
      }
  catch(e) {return e.description;}
  }
/*-----------------------------------------------------------------------------
file_exist(file_name)
功能 : 
  此函數用來檢查檔案是否存在.
參數 :                                   
  file_name : 檔案名稱與路徑 (注意, 目錄需用兩個倒斜線分隔) 
傳回值 :
  成功傳回 1, 失敗傳回原因
範例 :    
  var result=file_exist("c:\\test\\my_doc.txt");    
-----------------------------------------------------------------------------*/  
function file_exist(file_name) {
  try {
      var FSO=new ActiveXObject("Scripting.FileSystemObject");
      if (FSO.FileExists(file_name)) {return 1;}
      else {return 0;}
      FSO=null;    
      }
  catch(e) {return e.description;}
  }
/*-----------------------------------------------------------------------------
delete_file(file_name)
功能 : 
  此函數用來刪除檔案.
參數 :                                   
  file_name : 檔案名稱與路徑 (注意, 目錄需用兩個倒斜線分隔) 
傳回值 :
  成功傳回 1, 失敗傳回原因
範例 :    
  var result=delete_file("c:\\test\\my_doc.txt");    
-----------------------------------------------------------------------------*/  
function delete_file(file_name) {
  try {
      var FSO=new ActiveXObject("Scripting.FileSystemObject");
      if (FSO.FileExists(file_name)) {FSO.DeleteFile(file_name);}
      FSO=null;
      return 1;
      }
  catch(e) {return e.description;}
  }
/*-----------------------------------------------------------------------------
get_folder()
功能 : 
  此函數會傳回網頁檔所在本機路徑, 例如 D:\\project\\pitch\\
參數 :  
  無
傳回值 : 字串 (雙倒斜線格式 D:\\project\\pitch\\)
-----------------------------------------------------------------------------*/
function get_folder() { //傳回目前網頁所在之目錄字串
  //取得目前網頁所在目錄,例如 /D:\project\pitch\pitch.htm
  var browser=window.navigator.appName;
  var b_version=window.navigator.appVersion;
  var version=b_version.split(";"); 
  var trim_Version=version[1].replace(/[ ]/g,""); 
  //取得目前網頁所在目錄,/D:/project/pitch/pitch.htm
  var sys_path=unescape(window.location.pathname);
  //去除檔名,從右邊開始找第一個右斜線 / 索引
  var pos=sys_path.lastIndexOf("\/"); 
  //須去除第一個右斜線,故從 1 開始直到右側第一個右斜線(含)
  var path=sys_path.substring(1,pos+1); 
  //工作目錄路徑演算結果例如 path=D:/project/pitch/
  //製作 FSO 物件運作所需之系統路徑字串 (由單一倒斜線轉成兩個倒斜線)
  var path_arr=path.split("\/"); //先拆成陣列
  var folder=path_arr.join("\\\\"); //再組合為字串 D:\\project\\pitch\\
  return folder;
  }

先在專案根目錄下新增一個 lib 資料夾, 將此 file.js 函式庫檔案存放於 /lib 下 :




完整的 files.js 參考 GitHub :

https://github.com/tony1966/test/blob/master/jqueryui-app/lib/file.js

下面逐一測試這些函數的用法. 



<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>jQuery UI Single Page Application</title>
  <script src="jquery/jquery.js"></script>
  <script src="jquery/jquery-ui.js"></script>
  <script src="jquery/datatables.js"></script>
  <script src="lib/file.js"></script>
  <link id="theme" href="jquery/themes/hot-sneaks/jquery-ui.css" rel="stylesheet">
  <link href="jquery/datatables.css" rel="stylesheet">
  <style>
    body {
      font-family: Arial, Helvetica, sans-serif;
      font-size:10px;
      }
  </style>
</head>
<body>
  <!-- 主題佈景選擇器 -->
  <select id="themes">
    <option value="base">base</option>
    <option value="black-tie">black-tie</option>
    <option value="blitzer">blitzer</option>
    <option value="cupertino">cupertino</option>
    <option value="dark-hive">dark-hive</option>
    <option value="dot-luv">dot-luv</option>
    <option value="eggplant">eggplant</option>
    <option value="excite-bike">excite-bike</option>
    <option value="flick">flick</option>
    <option value="hot-sneaks">hot-sneaks</option>
    <option value="humanity">humanity</option>
    <option value="le-frog">le-frog</option>
    <option value="mint-choc">mint-choc</option>
    <option value="overcast">overcast</option>
    <option value="pepper-grinder">pepper-grinder</option>
    <option value="redmond">redmond</option>
    <option value="smoothness">smoothness</option>
    <option value="south-street">south-street</option>
    <option value="start">start</option>
    <option value="sunny">sunny</option>
    <option value="swanky-purse">swanky-purse</option>
    <option value="trontastic">trontastic</option>
    <option value="ui-darkness">ui-darkness</option>
    <option value="ui-lightness">ui-lightness</option>
    <option value="vader">vader</option>
  </select>
  <script>
    $(function(){
      $("#themes").selectmenu();
      $("#themes").val("hot-sneaks");
      $("#themes").selectmenu("refresh");
      $('#themes').on('selectmenuchange', function() {
        var theme=$(this).val();
        var href="jquery/themes/" + theme + "/jquery-ui.min.css";
        $("#theme").attr("href", href);
        });
      });
  </script>
  <!-- 頁嵌面板 -->
  <div id="tabs">
    <ul>
      <li><a href="#tabs-1">tab1</a></li>
      <li><a href="#tabs-2">tab2</a></li>
      <li><a href="#tabs-3">tab3</a></li>
    </ul>
    <div id="tabs-1">
      <button id="read_file" class="ui-button ui-widget ui-corner-all">讀取檔案</button>
      <div id="out1" class="ui-state-highlight ui-corner-all" style="margin-top: 10px; padding: 5px;"></div>
      <script>
        $(function(){
          //監聽按鈕之 click 事件
          $("#read_file").click(function(e) {
            e.preventDefault();
            var folder=get_folder();     //取得此網頁的本機路徑
            var txt=read_file(folder + "hello-world.txt");      //讀取 .txt 檔
            var htm=read_file(folder + "hello-world.htm");   //讀取 .htm 檔
            $("#out1").html(folder + "<br>" + txt + "<br>" + htm);
            $("#out1").show();
            });
          });
      </script>
    </div>
    <div id="tabs-2">
    </div>
    <div id="tabs-3">
    </div>
  </div>
  <script>
    $(function(){
      $("#tabs" ).tabs();
      $("#out1").hide();
      }); 
  </script>
</body>
</html>

此網頁中的 tab1 頁籤中放置了一個按鈕與預設隱藏的 div 元素 (套用 jQuery UI 的 highlight 樣式類別), 當按下按鈕時會先呼叫 files.js 函式庫中的 get_folder() 函數來取得此網頁在本機中的路徑, 然後呼叫 read_file() 分別讀取專案根目錄下的 hello-world.txt 與 hello-world.htm 這兩個存文字檔案, hello-world.txt 內容為 :

Hello!
World! (text)

而 hello-world.htm 內容為 :

<b>Hello!</b>
<b>World! (html)</b>

將檔案路徑與讀取之檔案內容用跳行元素 br 串接後呼叫 html() 輸出到隱藏的 div 高亮度元件, 最後呼叫 show() 顯示此高亮度元素, 結果如下 :




注意, 由於使用了 Active X 技術, 此範例網頁只能在 IE 執行 (Edge 不支援), 且按下按鈕時會出現如下警告, 必須選 '是' 才會正常執行 :





參考 :

[Jquery]讓div能自由的show、hide


2020年8月20日 星期四

jQuery UI SPA 應用程式 (三) : 按鈕與對話盒

網頁應用程式在協助作業自動化上, 主要是透過網頁按鈕觸發事件執行 Javascript 程式來擷取剖析資料, 並自動製作下一步要在維運機器上執行的作業指令, 省卻人工下指令撈資料後用 EXCEL 進行資料處理與人工製作指令的麻煩, 還可避免操作過程中可能發生的錯誤. 本系列之前的測試文章參考 :

jQuery UI SPA 應用程式 (一) : 環境配置與程式架構
jQuery UI SPA 應用程式 (二) : 動態表格 DataTables

本篇是在前面兩篇的基礎上加入按鈕以及所觸發產生的對話盒最元件, 常用的對話盒有三種 : 訊息盒, 輸入盒, 以及確認盒, 其中確認盒最常用, 主要是作為執行指定 Javascript 應用程式前確認之用, 用法參考之前的文章 :

jQuery UI widget 之訊息盒與輸入盒應用範例
jQuery UI 學習筆記 (二) : 按鈕 (Button)
jQuery UI 學習筆記 (三) : 對話盒 (Dialog)


1. 按鈕 : 

只要加上特定的樣式類別 :

class="ui-button ui-widget ui-corner-all"

jQuery UI 就可將下列三種 HTML 元素 (a, button, input) 轉成主題佈景按鈕 :
  • <a href="#" class="ui-button ui-widget ui-corner-all">訊息盒</a>
  • <button class="ui-button ui-widget ui-corner-all">確認盒</button>
  • <input type="button" value="輸入盒" class="ui-button ui-widget ui-corner-all">
注意, input 按鈕的顯示文字是放在 value 屬性中; 而 a 與 button 元素則是放在 DOM 的 innerHTML 中. 其次, 只要套用 class="ui-button ui-widget ui-corner-all" 樣式類別就可以將三者外觀轉成按鈕, 不需要呼叫 jQuery 物件的 button() 函數, 例如 :


範例 6 : jQuery UI 對話盒的容器

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>jQuery UI Single Page Application</title>
  <script src="jquery/jquery.js"></script>
  <script src="jquery/jquery-ui.js"></script>
  <script src="jquery/datatables.js"></script>
  <link id="theme" href="jquery/themes/hot-sneaks/jquery-ui.css" rel="stylesheet">
  <link href="jquery/datatables.css" rel="stylesheet">
  <style>
    body {
      font-family: Arial, Helvetica, sans-serif;
      font-size:10px;
      }
  </style>
</head>
<body>
  <!-- 主題佈景選擇器 -->
  <select id="themes">
    <option value="base">base</option>
    <option value="black-tie">black-tie</option>
    <option value="blitzer">blitzer</option>
    <option value="cupertino">cupertino</option>
    <option value="dark-hive">dark-hive</option>
    <option value="dot-luv">dot-luv</option>
    <option value="eggplant">eggplant</option>
    <option value="excite-bike">excite-bike</option>
    <option value="flick">flick</option>
    <option value="hot-sneaks">hot-sneaks</option>
    <option value="humanity">humanity</option>
    <option value="le-frog">le-frog</option>
    <option value="mint-choc">mint-choc</option>
    <option value="overcast">overcast</option>
    <option value="pepper-grinder">pepper-grinder</option>
    <option value="redmond">redmond</option>
    <option value="smoothness">smoothness</option>
    <option value="south-street">south-street</option>
    <option value="start">start</option>
    <option value="sunny">sunny</option>
    <option value="swanky-purse">swanky-purse</option>
    <option value="trontastic">trontastic</option>
    <option value="ui-darkness">ui-darkness</option>
    <option value="ui-lightness">ui-lightness</option>
    <option value="vader">vader</option>
  </select>
  <script>
    $(function(){
      $("#themes").selectmenu();
      $("#themes").val("hot-sneaks");
      $("#themes").selectmenu("refresh");
      $('#themes').on('selectmenuchange', function() {
        var theme=$(this).val();
        var href="jquery/themes/" + theme + "/jquery-ui.min.css";
        $("#theme").attr("href", href);
        });
      });
  </script>
  <!-- 頁嵌面板 -->
  <div id="tabs">
    <ul>
      <li><a href="#tabs-1">A 元素按鈕</a></li>
      <li><a href="#tabs-2">Button 元素按鈕</a></li>
      <li><a href="#tabs-3">Input 元素按鈕</a></li>
    </ul>
    <div id="tabs-1">
      <a id="open_msgbox" href="#" class="ui-button ui-widget ui-corner-all">開啟訊息盒</a>
    </div>
    <div id="tabs-2">
      <button id="open_confirmbox" class="ui-button ui-widget ui-corner-all">開啟確認盒</button>
    </div>
    <div id="tabs-3">
      <input type="button" id="open_inputbox" class="ui-button ui-widget ui-corner-all" value="開啟輸入盒">
    </div>
  </div>
  <div id="msgbox" title="訊息"></div>
  <div id="confirmbox" title="確認"></div>
  <div id="inputbox" title="輸入"></div>
  <script>
    $(function(){
      $("#tabs" ).tabs();
      }); 
  </script>
</body>
</html>

此網頁中的三個頁籤分別放了標示為 "訊息盒", "確認盒", 以及 "輸入盒" 之按鈕, 只要套用 class="ui-button ui-widget ui-corner-all" 樣式類別就將其變成主題按鈕, 結果如下 :






按此三個按鈕預期要分別開啟  "訊息盒", "確認盒", 以及 "輸入盒" 三個對話盒, 但是目前按此三個按鈕均不會有反應, 因為還沒有為其綁定 click 點擊事件. 在處理 click 事件之前需先將這三個對話盒的 HTML 與 JS 程式碼準備好.


2. 對話盒 : 

jQuery UI 的對話盒內容都是放在 div 元素容器內 :

<div id="msgbox"  title="通知"></div>
<div id="confirmbox" title="確認"></div>
<div id="inputbox" title="輸入"></div>

div 元素的 title 屬性即對話盒標題, 在取得 div 元素之 jQuery 物件後呼叫其 dialog() 方法並傳入一個選項物件即可建立對話盒, 不論是訊息盒, 確認盒, 還是輸入盒作法都一樣 (注意, 對話盒標題也可以在選項物件中設定), 三者的差別只是 div 容器的 HTML 內容與選項物件 opt 中的事件處理方式不同而已, 訊息盒與確認盒的 HTML 內容只是一個字串 (純文字或 HTML) 與按鈕; 輸入盒的內容則是輸入表單與按鈕 :

$("#dialog").dialog(opt);

選項物件的常用屬性如下表 :


 常用設定屬性 說明
 title 對話盒標題 (= div 容器之 title 屬性)
 width 對話盒寬度
 height 對話盒寬度
 modal  是否為強制視窗 (true/false), 預設為 false
 autoOpen 是否自動開啟 (true/false), 預設為 true
 buttons 定義按鈕與其回呼函數等 (陣列或物件)
 beforeClose 定義對話盒關閉前之回呼函數


這些選項中必須注意的是預設為 true 的 autoOpen 屬性, 不論是哪一種對話盒通常都應該設為 false (不顯示), 因為實務上很少有網頁需要一開啟就顯示對話盒, 通常是因為按下按鈕等事件才顯示. 其次, buttons 屬性用來設定對話盒中的按鈕以及其 click 事件處理器

呼叫 dialog(opt) 建立對話盒後, 就可以為按鈕建立 click 事件監聽器, 當發生 click 事件時呼叫對話盒的 open 方法顯示對話盒 :

$("#dialog").dialog("open");

以下分別就三種對話盒說明實際用法 :


(1). 訊息盒 :

三種對話盒中訊息盒最簡單, 就只是一個通知使用者之訊息而已, 這個訊息內容不需要寫在 div 容器的 HTML 內容中, 可以在發生按鈕的 click 事件時利用 jQuery 物件的 html() 方法加以設定, 因此訊息盒容器可以共用, 亦即在網頁中只需要設置一個訊息盒 div 容器即可, 網頁中任何按鈕均可使用, 程式碼如下 :

//建立訊息盒
$("#msgbox").dialog({
  title: "訊息",
  autoOpen: false,
  buttons: {
    "確定": function() {$(this).dialog("close");}
    }
  });
//監聽按鈕之 click 事件
$("#open_msgbox").click(function(e) {
  var msg="<p>Hello World!</p>";
  $("#msgbox").html(msg);
  $("#msgbox").dialog("open");
  e.preventDefault();
  });

此範例首先呼叫訊息盒 div 容器 (id=msgbox) 的 jQuery 物件之 dialog() 方法, 並傳入一個 opt 選項物件來建立訊息盒, 主要就是設置一個 "確定" 按鈕, 並為其指定 click 事件處理器用來關閉訊息盒. 其次是為 id=open_msgbox 的按鈕指派 click 事件處理器, 主要是呼叫訊息盒物件的 html() 方法設定訊息盒容器的 HTML 內容, 以及呼叫 dialog("open") 方法開啟訊息盒.


(2). 確認盒 :

確認盒用來詢問使用者是否確定要執行某項作業, 其 div 容器的 HTML 內容與訊息盒一樣都是字串 (純文字或 HTML), 差別是訊息盒為敘述句 (例如 "檔案不存在"); 而確認盒則是問句 (例如 "確定要刪除此檔案?"), 且確認盒按鈕要有兩個 :  YES/OK/確定/是, 與 NO/CANCEL/取消/否; 而訊息盒則只要一個即可. 程式碼如下 :

//建立確認盒
var do_the_job=function() {
  //do the job
  $(this).dialog("close");
  }
$("#confirmbox").dialog({
  title: "確認",
  autoOpen: false,
  buttons: {
    "確定": do_the_job,
    "取消": function() {$(this).dialog("close");}
    }
  });
//監聽確認盒按鈕之 click 事件
$("#open_confirmbox").click(function(e) {
  var msg="<p>確定要進行這項作業嗎?</p>";
  $("#confirmbox").html(msg);
  $("#confirmbox").dialog("open");
  e.preventDefault();
  });

可見確認盒與訊息盒最大的不同是選項物件中必須對 YES/OK/確定等按鈕指派一個事件處理涮進行特定處理, 此函數可以匿名函數形式直接寫在 YES/OK/確定按鈕後面, 若內容太長也可以寫在一個外部具名函數內, 但必須放在建立確認盒之 dialog() 之前.


(3). 輸入盒 :

輸入盒用來在進行下一步作業之前收集必要的資訊, 例如登入遠端機台所需的帳密等等, 它與訊息盒, 確認盒最大的不同是 div 容器的 HTML 需包含可輸入資料的表單元件, 例如文字欄位 (text input), 選項圓鈕 (radio input), 核取方塊 (checkbox input), 或下拉式選單 (select option) 等等, 其按鈕與確認盒一樣有兩個 :  YES/OK/確定/是, 與 NO/CANCEL/取消/否, 若按 YES/OK/確定/是就執行事件處理函數, 否則就關閉輸入盒, 例如下面的攝氏轉華氏溫度範例 :

//建立輸入盒
var compute=function() {
  var c=parseFloat($("#c").val());
  var f=c*9/5 + 32;
  f=f.toFixed(1);
  $("#msgbox").html("攝氏 " + c + " 度=華氏 " + f + " 度");
  $("#msgbox").dialog("open");
  $(this).dialog("close");
  }
$("#inputbox").dialog({
  title: "輸入",
  autoOpen: false,
  buttons: {
    "確定": compute,
    "取消": function() {$(this).dialog("close");}
    }
  });
//監聽輸入盒按鈕之 click 事件
$("#open_inputbox").click(function(e) {
  var fields="<p>請輸入攝氏溫度</p>" +
             "<p><input id='c' type='text'></p>";
  $("#inputbox").html(fields);
  $("#inputbox").dialog("open");
  e.preventDefault();
  });

可見輸入盒與確認盒不同之處為 div 容器之 HTML 內容. 如果表單元件較多或較長, 使得預設的對話盒尺寸不夠, 可在選項物件中用 width 與 height 屬性設定為適當尺寸.

下面範例是將上述程式碼加到上面範例 6 的結果, 這使三個頁籤中的按鈕都能動作 :


範例 7 : jQuery UI 對話盒測試

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>jQuery UI Single Page Application</title>
  <script src="jquery/jquery.js"></script>
  <script src="jquery/jquery-ui.js"></script>
  <script src="jquery/datatables.js"></script>
  <link id="theme" href="jquery/themes/hot-sneaks/jquery-ui.css" rel="stylesheet">
  <link href="jquery/datatables.css" rel="stylesheet">
  <style>
    body {
      font-family: Arial, Helvetica, sans-serif;
      font-size:10px;
      }
  </style>
</head>
<body>
  <!-- 主題佈景選擇器 -->
  <select id="themes">
    <option value="base">base</option>
    <option value="black-tie">black-tie</option>
    <option value="blitzer">blitzer</option>
    <option value="cupertino">cupertino</option>
    <option value="dark-hive">dark-hive</option>
    <option value="dot-luv">dot-luv</option>
    <option value="eggplant">eggplant</option>
    <option value="excite-bike">excite-bike</option>
    <option value="flick">flick</option>
    <option value="hot-sneaks">hot-sneaks</option>
    <option value="humanity">humanity</option>
    <option value="le-frog">le-frog</option>
    <option value="mint-choc">mint-choc</option>
    <option value="overcast">overcast</option>
    <option value="pepper-grinder">pepper-grinder</option>
    <option value="redmond">redmond</option>
    <option value="smoothness">smoothness</option>
    <option value="south-street">south-street</option>
    <option value="start">start</option>
    <option value="sunny">sunny</option>
    <option value="swanky-purse">swanky-purse</option>
    <option value="trontastic">trontastic</option>
    <option value="ui-darkness">ui-darkness</option>
    <option value="ui-lightness">ui-lightness</option>
    <option value="vader">vader</option>
  </select>
  <script>
    $(function(){
      $("#themes").selectmenu();
      $("#themes").val("hot-sneaks");
      $("#themes").selectmenu("refresh");
      $('#themes').on('selectmenuchange', function() {
        var theme=$(this).val();
        var href="jquery/themes/" + theme + "/jquery-ui.min.css";
        $("#theme").attr("href", href);
        });
      });
  </script>
  <!-- 頁嵌面板 -->
  <div id="tabs">
    <ul>
      <li><a href="#tabs-1">A 元素按鈕</a></li>
      <li><a href="#tabs-2">Button 元素按鈕</a></li>
      <li><a href="#tabs-3">Input 元素按鈕</a></li>
    </ul>
    <div id="tabs-1">
      <a id="open_msgbox" href="#" class="ui-button ui-widget ui-corner-all">開啟訊息盒</a>
    </div>
    <div id="tabs-2">
      <button id="open_confirmbox" class="ui-button ui-widget ui-corner-all">開啟確認盒</button>
    </div>
    <div id="tabs-3">
      <input type="button" id="open_inputbox" class="ui-button ui-widget ui-corner-all" value="開啟輸入盒">
    </div>
  </div>
  <div id="msgbox" title="訊息"></div>
  <div id="confirmbox" title="確認"></div>
  <div id="inputbox" title="輸入"></div>
  <script>
    $(function(){
      $("#tabs" ).tabs();
      //建立訊息盒
      $("#msgbox").dialog({
        title: "訊息",
        autoOpen: false,
        buttons: {
          "確定": function() {$(this).dialog("close");}
          }
        });
      //監聽訊息盒按鈕之 click 事件
      $("#open_msgbox").click(function(e) {
        var msg="<p>Hello World!</p>";
        $("#msgbox").html(msg);
        $("#msgbox").dialog("open");
        e.preventDefault();
        });
      //建立確認盒
      var do_the_job=function() {
        //do the job
        $(this).dialog("close");
        }
      $("#confirmbox").dialog({
        title: "確認",
        autoOpen: false,
        buttons: {
          "確定": do_the_job,
          "取消": function() {$(this).dialog("close");}
          }
        });
      //監聽確認盒按鈕之 click 事件
      $("#open_confirmbox").click(function(e) {
        var msg="<p>確定要進行這項作業嗎?</p>";
        $("#confirmbox").html(msg);
        $("#confirmbox").dialog("open");
        e.preventDefault();
        });
      //建立輸入盒
      var compute=function() {
        var c=parseFloat($("#c").val());
        var f=c*9/5 + 32;
        f=f.toFixed(1);
        $("#msgbox").html("攝氏 " + c + " 度=華氏 " + f + " 度");
        $("#msgbox").dialog("open");
        $(this).dialog("close");
        }
      $("#inputbox").dialog({
        title: "輸入",
        autoOpen: false,
        buttons: {
          "確定": compute,
          "取消": function() {$(this).dialog("close");}
          }
        });
      //監聽輸入盒按鈕之 click 事件
      $("#open_inputbox").click(function(e) {
        var fields="<p>請輸入攝氏溫度</p>" +
                   "<p><input id='c' type='text'></p>";
        $("#inputbox").html(fields);
        $("#inputbox").dialog("open");
        e.preventDefault();
        });
      }); 
  </script>
</body>
</html>

結果如下 :




從上面的測試可知, 其實這三種對話盒差別只在 div 容器的 HTML 內容與確定按鈕之事件處理函數不同而已, 下面範例是將程式與容器放在一起方便模組化的寫法 (雖然準則是要將 HTML 與 Javascript 程式碼分離) :


範例 8 : jQuery UI 對話盒測試 (模組化)

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>jQuery UI Single Page Application</title>
  <script src="jquery/jquery.js"></script>
  <script src="jquery/jquery-ui.js"></script>
  <script src="jquery/datatables.js"></script>
  <link id="theme" href="jquery/themes/hot-sneaks/jquery-ui.css" rel="stylesheet">
  <link href="jquery/datatables.css" rel="stylesheet">
  <style>
    body {
      font-family: Arial, Helvetica, sans-serif;
      font-size:10px;
      }
  </style>
</head>
<body>
  <!-- 主題佈景選擇器 -->
  <select id="themes">
    <option value="base">base</option>
    <option value="black-tie">black-tie</option>
    <option value="blitzer">blitzer</option>
    <option value="cupertino">cupertino</option>
    <option value="dark-hive">dark-hive</option>
    <option value="dot-luv">dot-luv</option>
    <option value="eggplant">eggplant</option>
    <option value="excite-bike">excite-bike</option>
    <option value="flick">flick</option>
    <option value="hot-sneaks">hot-sneaks</option>
    <option value="humanity">humanity</option>
    <option value="le-frog">le-frog</option>
    <option value="mint-choc">mint-choc</option>
    <option value="overcast">overcast</option>
    <option value="pepper-grinder">pepper-grinder</option>
    <option value="redmond">redmond</option>
    <option value="smoothness">smoothness</option>
    <option value="south-street">south-street</option>
    <option value="start">start</option>
    <option value="sunny">sunny</option>
    <option value="swanky-purse">swanky-purse</option>
    <option value="trontastic">trontastic</option>
    <option value="ui-darkness">ui-darkness</option>
    <option value="ui-lightness">ui-lightness</option>
    <option value="vader">vader</option>
  </select>
  <script>
    $(function(){
      $("#themes").selectmenu();
      $("#themes").val("hot-sneaks");
      $("#themes").selectmenu("refresh");
      $('#themes').on('selectmenuchange', function() {
        var theme=$(this).val();
        var href="jquery/themes/" + theme + "/jquery-ui.min.css";
        $("#theme").attr("href", href);
        });
      });
  </script>
  <!-- 頁嵌面板 -->
  <div id="tabs">
    <ul>
      <li><a href="#tabs-1">A 元素按鈕</a></li>
      <li><a href="#tabs-2">Button 元素按鈕</a></li>
      <li><a href="#tabs-3">Input 元素按鈕</a></li>
    </ul>
    <div id="tabs-1">
      <!-- 訊息盒按鈕 -->
      <a id="open_msgbox" href="#" class="ui-button ui-widget ui-corner-all">開啟訊息盒</a>
      <script>
        $(function(){
          //監聽訊息盒按鈕之 click 事件
          $("#open_msgbox").click(function(e) {
            var msg="<p>Hello World!</p>";
            $("#msgbox").html(msg);
            $("#msgbox").dialog("open");
            e.preventDefault();
            });       
          }); 
      </script>
      <!-- 訊息盒 -->
      <div id="msgbox" title="訊息"></div>
      <script>
        $(function(){
          //建立訊息盒
          $("#msgbox").dialog({
            title: "訊息",
            autoOpen: false,
            buttons: {
              "確定": function() {$(this).dialog("close");}
              }
            });
          }); 
      </script>
    </div>
    <div id="tabs-2">
      <!-- 確認盒按鈕 -->
      <button id="open_confirmbox" class="ui-button ui-widget ui-corner-all">開啟確認盒</button>
      <script>
        $(function(){
          //監聽確認盒按鈕之 click 事件
          $("#open_confirmbox").click(function(e) {
            var msg="<p>確定要進行這項作業嗎?</p>";
            $("#confirmbox").html(msg);
            $("#confirmbox").dialog("open");
            e.preventDefault();
            });
          }); 
      </script>
      <!-- 確認盒 -->
      <div id="confirmbox" title="確認"></div>
      <script>
        $(function(){
          //建立確認盒
          var do_the_job=function() {
            //do the job
            $(this).dialog("close");
            }
          $("#confirmbox").dialog({
            title: "確認",
            autoOpen: false,
            buttons: {
              "確定": do_the_job,
              "取消": function() {$(this).dialog("close");}
              }
            });
          }); 
      </script>
    </div>
    <div id="tabs-3">
      <!-- 輸入盒按鈕 -->
      <input type="button" id="open_inputbox" class="ui-button ui-widget ui-corner-all" value="開啟輸入盒">
      <script>
        $(function(){
          //監聽輸入盒按鈕之 click 事件
          $("#open_inputbox").click(function(e) {
            var fields="<p>請輸入攝氏溫度</p>" +
                       "<p><input id='c' type='text'></p>";
            $("#inputbox").html(fields);
            $("#inputbox").dialog("open");
            e.preventDefault();
            });
          }); 
      </script>
      <!-- 輸入盒 -->
      <div id="inputbox" title="輸入"></div>
      <script>
        $(function(){
          //建立輸入盒
          var compute=function() {
            var c=parseFloat($("#c").val());
            var f=c*9/5 + 32;
            f=f.toFixed(1);
            $("#msgbox").html("攝氏 " + c + " 度=華氏 " + f + " 度");
            $("#msgbox").dialog("open");
            $(this).dialog("close");
            }
          $("#inputbox").dialog({
            title: "輸入",
            autoOpen: false,
            buttons: {
              "確定": compute,
              "取消": function() {$(this).dialog("close");}
              }
            });
          }); 
      </script>
    </div>
  </div>
  <script>
    $(function(){
      $("#tabs" ).tabs();
      }); 
  </script>
</body>
</html>

不過這樣看起來好像有點亂啊, 真是有一好沒兩好.


3. 對話盒模組 (含按鈕) : 

茲將此三個對話盒模組列之如下以備複製套用 :


(1). 訊息盒模組 :

<!-- 訊息盒按鈕 -->
<a id="open_msgbox" href="#" class="ui-button ui-widget ui-corner-all">開啟訊息盒</a>
<script>
  $(function(){
    //監聽訊息盒按鈕之 click 事件
    $("#open_msgbox").click(function(e) {
      var msg="<p>Hello World!</p>";
      $("#msgbox").html(msg);
      $("#msgbox").dialog("open");
      e.preventDefault();
      });       
    }); 
</script>
<!-- 訊息盒 -->
<div id="msgbox" title="訊息"></div>
<script>
  $(function(){
    //建立訊息盒
    $("#msgbox").dialog({
      title: "訊息",
      autoOpen: false,
      buttons: {
        "確定": function() {$(this).dialog("close");}
        }
      });
    }); 
</script>


(2). 確認盒模組 :

<!-- 確認盒按鈕 -->
<button id="open_confirmbox" class="ui-button ui-widget ui-corner-all">開啟確認盒</button>
<script>
  $(function(){
    //監聽確認盒按鈕之 click 事件
    $("#open_confirmbox").click(function(e) {
      var msg="<p>確定要進行這項作業嗎?</p>";
      $("#confirmbox").html(msg);
      $("#confirmbox").dialog("open");
      e.preventDefault();
      });
    }); 
</script>
<!-- 確認盒 -->
<div id="confirmbox" title="確認"></div>
<script>
  $(function(){
    //建立確認盒
    var do_the_job=function() {
      //do the job
      $(this).dialog("close");
      }
    $("#confirmbox").dialog({
      title: "確認",
      autoOpen: false,
      buttons: {
        "確定": do_the_job,
        "取消": function() {$(this).dialog("close");}
        }
      });
    }); 
</script>


(3). 輸入盒模組 : 

<!-- 輸入盒按鈕 -->
<input type="button" id="open_inputbox" class="ui-button ui-widget ui-corner-all" value="開啟輸入盒">
<script>
  $(function(){
    //監聽輸入盒按鈕之 click 事件
    $("#open_inputbox").click(function(e) {
      var fields="<p>請輸入攝氏溫度</p>" +
                 "<p><input id='c' type='text'></p>";
      $("#inputbox").html(fields);
      $("#inputbox").dialog("open");
      e.preventDefault();
      });
    }); 
</script>
<!-- 輸入盒 -->
<div id="inputbox" title="輸入"></div>
<script>
  $(function(){
    //建立輸入盒
    var compute=function() {
      var c=parseFloat($("#c").val());
      var f=c*9/5 + 32;
      f=f.toFixed(1);
      $("#msgbox").html("攝氏 " + c + " 度=華氏 " + f + " 度");
      $("#msgbox").dialog("open");
      $(this).dialog("close");
      }
    $("#inputbox").dialog({
      title: "輸入",
      autoOpen: false,
      buttons: {
        "確定": compute,
        "取消": function() {$(this).dialog("close");}
        }
      });
    }); 
</script>

這種模組化設計在 Django 之類有 template 模板功能的框架應用上應該用得上.