- clueTip 並不是呼叫後就會顯示工具提示;跟其它的 tips library(如 Walter Zorn 的 DHTML Tooltips)在使用上的概念有差異。我們不需要將它放在 mouseover 或是滑鼠其它事件中。其會自動的 bind 到指定的 HTML 標籤上。
- clueTip API 中的 onActivate: 的目的是要決定是否要顯示 tip;傳給 onActivate 的是 function 參考,該 function 可以依情況決定要回傳 true(表示顯示工具提示)或 false(不顯示)
- 若是 titleAttribute bind 到的 attribute 是動態決定的,記得要在 bind 到的 attribute 值設定前,將值先設定好,才對該 HTML 標籤呼叫 clueTip();!否則可能會出現滑鼠第一次移動到該 HTML 標籤時,並未正確顯示,第二次移到標籤上,才正常顯示(第一點似乎也可能造成這個問題)
2008年12月10日 星期三
使用 clueTip plugin 的注意事項
2008年12月1日 星期一
移植 Greasemonkey script 到 IE7Pro
- GM_addStyle→PRO_addStyle:IE7Pro 不支援 <><![CDATA[...]]></> 的寫法
- GM_xmlhttpRequest→PRO_xmlhttpRequest
- XML parsing
- Embedded Image:目前支援 Base 64 編碼
jQuery
直接引用即可,不需透過 unsafeWindow。getElementsByClassName
參考 http://www.robertnyman.com/2008/05/27/the-ultimate-getelementsbyclassname-anno-2008/2008年11月28日 星期五
O'REILLY InsideRIA AJAX framework 投票結果
2008年11月27日 星期四
2008年11月20日 星期四
IE7Pro Compatibility Script
- GM_setValue
- GM_getValue
- GM_log
- GM_openInTab
- GM_addStyle
- GM_xmlhttpRequest
// FremyCompany Script // version 0.1 build 4 ALPHA! // 28/03/07 // // -------------------------------------------------------------------- // // This is a Greasemonkey user script. To install it, you need // IE Pro 9.12 or later (see at : http://www.iepro.com) // Then restart Internet Explorer and revisit this script. // // -------------------------------------------------------------------- // // ==UserScript== // @name .FremyCompany Script // @description Scripts made by FremyCompany to make IE Pro more compatbile with GreaseMonkey // @include * // ==/UserScript== (function(w,d) { w.GM_setValue=function(name, value) { return PRO_setValue(name, value); }; w.GM_getValue=function(name, defaultValue) { return PRO_getValue(name, defaultValue); }; w.GM_log=function(text) { return PRO_log(text); }; w.GM_openInTab=function(url) { return PRO_openInTab(url); }; w.GM_addStyle=function(css) { return PRO_addStyle(css); }; w.GM_xmlhttpRequest=function (d) { // url, method, headers, data, onload, onerror, onreadystatechange; if (!d.url) { GM_log("URL is missing in xhr-call"); return false; } if (!d.method) { d.method="POST"; } if (!d.headers) { d.headers=new Array(); } var xhr={"readyState":0,"status":0,"statusText":"not loaded"}; var xhr_value=xhr; try { xhr=GM_xmlhttpRequest._createRequest(); // OPENING of the xhr xhr.open(d.method, d.url, true); for (h in d.headers) { try { xhr.setRequestHeader(h, d.headers[h]); } catch (ex) {} } // CallBack gesture xhr.onreadystatechange=function() { GM_xmlhttpRequest._createValue(xhr,xhr_value); try { d.onreadystatechange(xhr_value); } catch (ex) {} if (xhr.readyState==4) { if (xhr.status==200||xhr.status==0) { try { d.onload(xhr_value); } catch (ex) {} } else { try { d.onerror(xhr_value); } catch (ex) {} } } } // SENDING the data xhr.send(d.data?d.data:null) } catch (ex) { try { d.onerror(xhr_value, ex); } catch (ex2) {} } }; w.GM_xmlhttpRequest._createRequest=PRO_xmlhttpRequest; w.GM_xmlhttpRequest._createValue=function(x,v) { v.abort=function() { x.abort(); } v.getResponseHeader=function(n) { return x.getResponseHeader(n); } v.getAllResponseHeaders=function() { return x.getAllResponseHeaders(); } v.responseText=x.responseText; v.responseHeaders=x.getAllResponseHeaders(); v.responseText=x.responseText; v.responseBody=x.responseBody; v.readyState=x.readyState; v.status=x.status; v.statusText=x.statusText; }; })(window,document);
2008年11月10日 星期一
GM_xmlhttpRequest 和 unsafeWindow 的限制
Greasemonkey access violation: unsafeWindow cannot call GM_xmlhttpRequest.
解決方法如下:
unsafeWindow.someObject.registerCallback(function(asin) { window.setTimeout(function() { // 重點是利用 window.setTimeout GM_xmlhttpRequest({ method: "GET", url: "http://www.amazon.com/asin/" + asin; }); }, 0); // <<< });
實際例子
$("span[name!=NOT_AVAILABLE]").click(function(){ GM_openInTab(entrezGene+$(this).attr("name"),1); }).mouseover(function(){ var url=url+$(this).attr("name")+".htm"; window.setTimeout(function(ref){ GM_xmlhttpRequest({ method: "GET", url: url+"", onload: function(xhr) { ref.attr("title","Information from Entrez Gene|"+xhr.responseText).cluetip( {width:400,splitTitle: '|',arrows: true,dropShadow: false, cluetipClass: 'gene', waitImage: true} ); } }); },0,$(this)); // 用這種方法可以將 $(this) 傳進去 });
2008年11月6日 星期四
Greasemonkey and Internet Explorer
其它 Greasemonkey4IE 工具
2008年11月5日 星期三
2008年10月29日 星期三
利用筆記型電腦的無線網路讓 iPod Touch 上網
首先,啟用撥接 ADSL 的網路連線共用
再來就是設定點對點連線
以下是利用 ThinkPad 的 Access Connections 來設定;視情況看看要不要加上金鑰控制 另外在 IP 上,請指定靜態 IP;比如 192.168.0.1最後在愛碰上,利用「其他...」來設定連線到筆記型電腦的 IP 進行點對點連線即可
2008年10月24日 星期五
第一次覺得看貨品運送過程還挺有趣的...
日期 | 時間 | 地點 | 貨件狀態 |
23 Oct 2008 | 19:02:25 | Pudong International Airport | Shipment Received At Transit Point. |
23 Oct 2008 | 17:39:00 | Suzhou | Shipment In Transit. |
23 Oct 2008 | 17:34:04 | Suzhou | Shipment In Transit. |
23 Oct 2008 | 15:17:27 | Suzhou | Shipment Held In Warehouse. Follow Up Actions Underway. |
2008年10月19日 星期日
2008年10月14日 星期二
免費取得 EBook 的幾個網站
EBook Search Engines
- www.pdfgeni.com
- www.pdf-search-engine.com
- www.data-sheet.net
- www.freecomputerbooks.com
- www.freetechbooks.com
- www.onlinecomputerbooks.com
Scribd
Scribd 被稱為 document 的 YouTube。Project Gutenberg collection
http://www.gutenberg.org/2008年10月8日 星期三
CSS selector
span[class^="ARGM-"]{background:#FFFFCC} span[class="IASL-NEG"]{background:#FFFFCC}
2008年10月7日 星期二
2008年10月3日 星期五
2008年10月2日 星期四
無趣的資格考終於考完了...
考題了無新意;唯一沒看過的題目大概就是 S-R latch 的真值表和 1024 個 processors 要用 network 還是 bus 去連結比較合適。不過了無新意總比考不過要來的好 XD
- 清大計算機組織 1997-2008:基本上都整理在課本上了。這只能當參考
帳號密碼檢視工具
昨天臨時試了幾個之前收著的免費密碼檢視器(其實主要是要抓「撥號連線」的密碼);像是 Dialupass、Dial-up Password Recovery Master,都不能完全抓到電腦上設定的 ADSL 的連線密碼,有的是只有使用者名稱,或是只有撥號連線名。
用一用還是只有對岸同胞的侠客密码查看器才能滿足需求。除了撥號連線密碼外,這工具幾乎是全都包了:- Windows 系統顯示的星號密碼查看
- 撥號密碼查看,包括 ADSL 上網密碼與 LAN 上網密碼
- IE 自動完成密碼、表單內容查看與密碼列表保存
- OutLook Express 郵件帳戶密碼查看
- CMOS 開機密碼清除
2008年9月26日 星期五
Firefox 3.0.2 密碼無法使用的 bug
才剛更新完我的 Firefox 3.0.2 馬上就發現問題:Sxipper、PMOG 失效,導因於大部分既存的密碼都無法使用,也無法除儲存新的密碼。依據官方的說法,這導因於 FF 3.0.2 無法讀取包含有非 ASCII 編碼資訊的密碼。
檢查自己是不是碰到這問題的方法很簡單,就是開啟 FF 的錯誤控制台,然後看看是不是有出現:
this._storage is null ... [Exception... "'Error: Error in getRegisteredUsername: [Exception... "'[JavaScript Error: "this._storage is null" {file: "file:///C:/Program%20Files/Mozilla%20Firefox/components/nsLoginManager.js" line: 425}]' when calling method: ...之類的錯誤。基本上目前 Mozilla 表示會盡快弄出 patch 檔,然後這段期間要請廣大的使用者自己手動輸入帳號密碼(這真的還蠻囧的)。若是對於密碼苦手的人...只好請你自行將 FF 在倒退嚕回去 FF 3.0.1
目前已知的非官方解法:http://forum.moztw.org/viewtopic.php?p=134732
- 到 C:\Users\Your User Name\AppData\Roaming\Mozilla\Firefox\Profiles\XXXXX.default 目錄下(適用於 Vista,XP 應該是 C:\Documents and Settings\Your User Name\Application Data\Mozilla\Firefox\Profiles\XXXXX.default)
- 將 signons3.txt 檔轉換成 UTF-8 格式
- 重新啟動 Firefox 即可
2008年9月25日 星期四
Magical Jelly Bean Keyfinder 檢視作業系統上安裝軟體的序號
2008年9月23日 星期二
2008/09/21 的海角七號...還是爆滿
禮拜天終於去看了「海角七號」...
原本以為已經上檔快一個月的片,熱潮應該已經過了吧;在高雄喜滿客的網路訂票系統看起來也頗多空位(心裡的 OS 是,或許高雄人比較沒那麼瘋),於是就打算到現場再買票,再看看能不能用聯名卡弄點優惠。決定好下午四點四十分的場次,四點便從楠梓開車過去夢時代...事實證明是,我太天真了;四點半到喜滿客售票大廳:「驚!竟然要排隊...」
很久沒看院線片了,我承認我是抱著看二輪片的心態去看的,反正就提早個十分鐘到...買個票進去找個地方做就好了;好吧就給它排吧...囧的是排沒多久就聽到廣播說:「五點五十分的海角七號,只剩下前三排的位置了...請各位觀眾...」啥碗糕...有沒這麼扯
Anyway...最終我還是看到了這部在網路、電視、報章媒體廣告到不行的台灣電影。第一句台詞:「幹,我操你媽的台北!」或許就宣告了這部片的不同吧...
除了已經被討論到爛的劇情之外,最主要的是看到許多很熟悉的街景,新的恆春街跟舊的恆春街道交錯的記憶...每年過年都去慈濟精舍;我真的很久沒回恆春了
2008年9月15日 星期一
在投影片中直接嵌入網頁內容
在使用 Microsoft PowerPoint present 時,有時會需要將網頁嵌入到 slide 中做展示。一般性的方式大概就是插入一個連結,然後滑鼠點擊切換視窗到瀏覽器進行操作,最後再回到投影片 side 接續 present。
藉由使用 LiveWeb macro,我們可以在 present 時,不用經過切換,讓整個 presentation 較為流暢。
2008年9月14日 星期日
2008年9月13日 星期六
Google Chrome 的一些使用 tips
- 在「上一頁」的按鈕上按下滑鼠右鍵即能顯示最近拜訪過的網頁列表
- Crtl+Shift+T 開啟最後一次關閉的分頁
- 直接在 address bar 輸入單位換算;比如 1ns in s,會自動利用 Google 計算機進行單位轉換(FF 也支援,只是不見得會利用 Google 計算機)
- 變大 textarea 如下圖:
寄件者 HJ@Taipei
其它參考
浮點數轉換器
有需要考計算機組織的也有可能會用到...:P
其它的 IEEE-754 Converter:2008年9月12日 星期五
db4o 與結構化的物件;如何處理物件間的關連
儲存結構化的物件
如同儲存一般物件一樣,我們也是呼叫 Set() 方法來儲存 Article 物件。與 Article 物件關連的 Sentence 物件會被自動儲存!string pmid = "123"; string title = "sent0"; Article article = new Article(pmid, title); List上面的程式碼相當於我們手動將各物件存入資料庫:abs=new List (); abs.Add(new Sentence("sent1","METHOD")); abs.Add(new Sentence("sent2","METHOD")); abs.Add(new Sentence("sent3","CONCLUSION")); article.SentencesOfAbstract=abs; db.Set(article);
Listabs=new List (); abs.Add(new Sentence("sent1","METHOD")); abs.Add(new Sentence("sent2","METHOD")); abs.Add(new Sentence("sent3","CONCLUSION")); db.Set(abs); string pmid = "123"; string title = "sent0"; Article article = new Article(pmid, title); article.SentencesOfAbstract=abs; db.Set(article);
取回結構化物件
QBE
要取回所有的 Article 物件,我們跟以前一樣,只要提供一個空的 prototype 即可:Article proto = new Article(null,null); IObjectSet result = db.Get(proto); ListResult(result);當然,我也可以取回所有的 Sentence 物件!
Sentence proto = new Sentence(null,null); IObjectSet result = db.Get(proto); ListResult(result);我們也可以取得所有 Article 物件中滿足 section 為 TITLE 的 Sentence 物件:
Sentence title = new Sentence(null,"TITLE"); Article article = new Article(null,title); IObjectSet result = db.Get(article); ListResult(result);
Native Queries
對結構化物件使用 Native Query 跟一般物件幾乎一模一樣。下面示範如何取回 一群 Article 物件,使其 Title Sentence 滿足指定的參數:/// C# .NET 1.1 public class RetrieveArticlesByTitlePredicate : Predicate { readonly string _title; public RetrieveArticlesByTitlePredicate(string title) { _title = title; } public bool Match(Article candidate) { return candidate.SentenceOfTitle.RawText == _title; } } // 使用方法 string title = "sent0"; IObjectSet results = db.Query(new RetrieveArticlesByTitlePredicate(title)); ListResult(results); /// C# .NET 2.0 string title = "sent0"; Listresults = db.Query (delegate(Article article) { return article.SentenceOfTitle.RawText == title; }); listResults(results);
SODA Query API
使用 SODA 的話,必須 descend 兩次以便取得 rawText:IQuery query = db.Query(); query.Constrain(typeof(Article)); query.Descend("title").Descend("rawText") .Constrain("sent0"); IObjectSet result = query.Execute(); ListResult(result);另外,我們也可以藉由指定 SentenceOfTitle 欄位來達到相同的效果:
IQuery query = db.Query(); query.Constrain(typeof(Sentence)); Sentence proto = new Sentence("sent0", null); query.Descend("title").Constrain(proto); IObjectSet result = query.Execute(); ListResult(result);下面我們示範如何取得所有 PMID 為 123 的 SentencesOfAbstract 欄位:
IQuery artQuery = db.Query(); artQuery.Constrain(typeof(Article)); artQuery.Descend("pmid").Constrain("123"); IQuery sentQuery = artQuery.Descend("_SentencesOfAbs"); IObjectSet result = sentQuery.Execute(); ListResult(result);
更新結構化物件
如同一般物件一般,要更新結構化物件,也是對它們再次呼叫 Set() 方法:IObjectSet result = db.Get(new Article("123",null)); Article found = (Article)result.Next(); found.SentenceOfTitle = new Sentence("sentXYZ",null); db.Set(found);下面我們嘗試直接更新 SentenceOfAbstract 物件內容:
IObjectSet result = db.Get(new Article("123",null)); Article found = (Article)result.Next(); List看起來似乎一切都很簡單、美好?但是實際上,若是我們再度存取資料庫,檢查我們的更新:abs=new List (); abs.Add(new Sentence("sent1","INTRODUCTION")); abs.Add(new Sentence("sent2","METHOD")); abs.Add(new Sentence("sent3","CONCLUSION")); found.SentenceOfAbstract=abs; db.Set(found);
result = db.Get(new Article("123",null)); ListResult(result);我們會發現,更新並未成功!這是因為效能上的考量,db4o 不會自動的更新結構化物件內的所有成員類別!為了兼顧效能與程式碼撰寫的簡潔,db4o 導入了 update depth 的概念,來控制程式在更新時,物件成員樹的更新深度。
update depth
對於所有的物件而言,預設的 update depth 是 1,代表只有 primitive 以及 String 成員會被更新。
db4o 提供了相當精細的方法來控制 update depth。下面我們藉由設定 CascadeOnUpdate 為 true,指定 db4o 完整的更新 Article 物件的內容:
Db4oFactory.Configure().ObjectClass(typeof(Article)) .CascadeOnUpdate(true); // 接下來才去設定 Article 物件內容要注意的地方是,先設定好 update depth 後才去更新才有效。
刪除結構化物件
一樣,用 Delete() 方法即可:IObjectSet result = db.Get(new Article("123",null)); Article found = (Article)result.Next(); db.Delete(found); result = db.Get(new Car(null));我們應該會認為 db4o 應該也會把 Article 物件內一堆的 Sentence 物件也刪除了吧?但是實際上, db4o 並不會幫我們做這件事!
遞迴刪除結構化物件內成員
跟更新時一樣,我們可以設定 db4o,幫我們完成這件事:Db4oFactory.Configure().ObjectClass(typeof(Article)) .CascadeOnDelete(true); // 接下來才去刪掉 // ...另外要注意的一點是,目前的 db4o 版本(6.0)中,就算我們要刪除的資料庫物件,目前仍然被程式內的變數參考到,它們經由遞迴刪除後,一樣會被從資料庫內移除。
2008年9月11日 星期四
db4o 的 query 方法簡述
Query-By-Example;QBE
QBE 使用上相當簡單,只要提供 db4o 一個 template 物件,db4o 會自動回傳符合 template 物件中非預設欄值的所有物件。這是經由 reflecting 機制加以建立一個 query expression,其利用 AND 將所有非預設值欄位加以結合。
這個方式有下列幾點限制:- db4o 必須 reflect template 物件的所有成員
- 我們無法進行更進接的 query expressions(比如 AND、OR、NOT)
- 我們無法建立某些特殊的限制條件,比如值必須是整數 0、空字串或是 null。因為它們會被解譯為非條件。
Native Queries
Native queries 是 db4o 主要的 query 介面。其概念可以參考如下兩篇白皮書:- Cook/Rosenberger, Native Queries for Persistent Objects, A Design White Paper
- Cook/Rai, Safe Query Objects: Statically Typed Objects as Remotely Executable Queries
範例
在 C# 1.1 中,我們必須建立一個繼承自 com.db4o.Predicate 的類別,並且必須實作 Match() 方法,其傳入的參數決定了物件的範圍。bool Match(Sentence candidate);
下面我們看一個更複雜的 query;我們嘗試找出所有的 Sentence 物件,並滿足:section 必須為 TITLE,並且其 sentence 長度不能大於 20 個字:
// C# .NET 2.0 IList <Sentence> result = db.Query%lt;Sentence> (delegate(Sentence sent) { return sent.RawText.Length < 20 && sent.SECTION == "TITLE"; });原則上,我們可以將任意的程式碼轉化為 Native Query,只要我們知道自己在做什麼就好了...我們再看一個例子:
SODA Query API
SODA query API 是 db4o 最底層的 query API,使用它能讓我們直接存取 query graph 上的節點。因為 SODA 使用字串來識別欄位,因此本身缺乏程式語言的支援(比如編譯時期型態檢驗),而且撰寫起來也比較冗長。因此對於大部分的應用而言, Native Query 會是比較好的選擇!然而,因為有一些應用,有動態產生 query 的需求,這時就需要用到 SODA。
範例
下面示範如何利用 SODA 取回全部的 Sentence 物件。我們利用 ObjectContainer 的 Query() 方法建立了 Query 物件,接著我們可以藉由 Constraint 物件加入限制到 Query 物件中:IQuery query = db.Query(); query.Constrain(typeof(Sentence)); IObjectSet result = query.Execute(); ListResult(result);要經由 section 名取得某個 Sentence 物件,我們必須利用 Descend() 方法進一步的加強限定它的 Section 欄位:
IQuery query = db.Query(); query.Constrain(typeof(Sentence)); query.Descend("section").Constrain("TITLE"); IObjectSet result = query.Execute(); ListResult(result);值的一提的是,類別限定其實可以拿掉;假若去掉類別限定,我們將會 query 取得所有包含指定的 section 資料欄位值的物件。再看另一個例子:
IQuery query = db.Query(); query.Constrain(typeof(Sentence)); query.Descend("rawText").Constrain("Pain management: evaluating the effectiveness of an educational programme for surgical nursing staff."); IObjectSet result = query.Execute(); ListResult(result);
進階範例
有時我們並不確定某特定欄位,但是需要去 query 符合特定範圍值的物件,或是不包含特定值的物件,這些都可以經由 Constraint API 辦到。
下面的例子找出,所有 RawText 不是「Pain management: evaluating the effectiveness of an educational programme for surgical nursing staff.」的 Sentence 物件:IQuery query = db.Query(); query.Constrain(typeof(Sentence)); query.Descend("rawText").Constrain("Pain management: evaluating the effectiveness of an educational programme for surgical nursing staff.").Not(); IObjectSet result = query.Execute(); ListResult(result);我們也可以加入其它的邏輯運算:
IQuery query = db.Query(); query.Constrain(typeof(Sentence)); IConstraint constr = query.Descend("rawText") .Constrain("Pain management: evaluating the effectiveness of an educational programme for surgical nursing staff."); // 也可以用 .Or(constr); query.Descend("section") .Constrain("TITLE").And(constr); IObjectSet result = query.Execute(); ListResult(result);我們也利用限制來比較給定的值:
IQuery query = db.Query(); query.Constrain(typeof(Sentence)); // 找到長度大於 50 的 Sentence 物件 query.Descend("length") .Constrain(50).Greater(); IObjectSet result = query.Execute(); ListResult(result);SOAD API 也允許我們去 query 欄位值為資料型態的預設值的物件:
Sentence s = new Sentence("Sentence 1", null); db.Set(s); IQuery query = db.Query(); query.Constrain(typeof(Sentence)); query.Descend("section").Constrain(null); IObjectSet result = query.Execute(); ListResult(result); db.Delete(s);我們也可以請 db40 對 query 結果進行排序:
IQuery query = db.Query(); query.Constrain(typeof(Sentence)); query.Descend("length").OrderAscending(); IObjectSet result = query.Execute(); ListResult(result); query.Descend("length").OrderDescending(); result = query.Execute(); ListResult(result);前述的所有範例都可以任意結合,形成更複雜的 query。最後我們示範如何清除資料庫內所有的 Sentence 物件:
IObjectSet result = db.Get(typeof(Sentence)); foreach (object item in result) { db.Delete(item); }
ASP.NET 的 XSS 攻擊偵測
伺服器出現:
A potentially dangerous Request.Form value was detected from the client (="...it (Omega<<A)> Description: Request Validation has detected a potentially dangerous client input value, and processing of the request has been aborted. ...
的錯誤,起因是因為 ASP.Net 1.1 後導入對提交表單進行自動檢查是否存在 XSS(跨站腳本攻擊)的能力。當 client 端試圖用某些特定符號的輸入影響頁面返回結果時,ASP.NET 引擎會拋出 HttpRequestValidationExceptioin。
最簡單的方式就是加入在 web.confing 中加入 validateRequest="false" 的選項
或是在 @Page 中加入 ValidateRequest="false"...
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" ValidateRequest="false" %>當然若應用程式不會受到此類攻擊的話,這是一個可接受的解決方法。
參考
2008年9月9日 星期二
用 Email 上傳相片到 Picasa Web Albums
現在利用用 Email 就可以在沒安裝 Picasa 的情況下,直接上傳相片到 Picasa Web Albums 上。
首先,必須先到 Setting page中將「使用電子郵件上載相片」(Allow me to upload photos by email.)選項啟用。並在輸入視窗中填入想要使用的 Email 地址:username.secretkey@picasaweb.com。接下來,只要直接寄信到該地址即可。
預設,Picasa 會將收到的相片放置到預設的「上傳投遞箱」相簿中。不過我們可以就由在主旨內指定既存的相簿名稱,即可將相片上傳到該相簿內!
目前支援最多一次上傳 20MB 的圖檔;包含 JPG、PNG 和 GIF。對於使用 Picasas mobile site 的使用者,這可以是另一種方式來分享相片。2008年9月8日 星期一
2008年9月4日 星期四
2008年9月3日 星期三
Google Chrome;Google 瀏覽器!
- 更穩定
- 更快速(尤其是對於應用 JavaScript 的網站而言!)
- 更安全
- 而在操作介面上,應該更簡潔、簡單
Google 瀏覽器本身一如 Google 的其它眾多服務一樣,是免費的;甚至它是 Open Source 的!
另外,跟一般瀏覽器的差異在於 Google 瀏覽器的 process 控制。(看來要複習一下作業系統了 XD)。一般的瀏覽器的實作是 multi-thread on single process。所以,我們若是開了許多分頁,基本上它們都在同一個 process 上,但是一旦某個 thread (如分頁)上的 JavaScript 執行過久把 CPU 吃掉的話,那整個瀏覽器就都掛了。
IE 都是由同一個 PID 4132 的 process 來處理分頁
而 Google 瀏覽器則是把分頁的動作都各自建立一個 Process,如同作業系統的行程管理一般,Google 瀏覽器會管理這些 process。因此若是某個分頁在忙碌的呈現網站內容時,其它分頁仍舊可以正常運作!因為每個分頁都是獨立的 process,若是某個分頁掛掉了,我們也只會遺失該分頁的資訊內容。(不過這也應該會帶來了記憶體使用量會不會因此大增的問題吧)
Google Chrome 則由 PID 4980 來管理產生、刪除 process。如上圖,第一個分頁,4980 產生了 PID=9112 來處理。下圖,我又多開了一個分頁,另一個 process;PID=10232 被產生。
在漫畫裡,有相當簡潔清楚的比較傳統瀏覽器記憶體管理和 Google 以 process 為主的差異(很像在複習作業系統的感覺哈哈)。另外用漫畫呈現也讓人容易瞭解,比如用了許多有趣的小例子,如「無限猴子定理」,一群人坐在一台小汽車上,來描述現有 JavaScript 引擎的窘境。是相當值得一看的介紹!
相關技術
2008年8月31日 星期日
不需安裝 PDF 檢視軟體,線上觀看 PDF 檔
PDFMENOT 提供了線上觀看 PDF 的服務。可讓使用者經過 URL 或是上傳的方式直接線上觀看 PDF 內容。
除此之外,PDFMENOT 還提供了 FF 的擴充套件以及 Blogger 的 script 等工具。詳情參考這裡。
在 ASP.NET 中遇到 Access is denied 錯誤
C# 的 Regex.Replace
在 Perl 中正規表示法的取代,可以簡單的利用 $1、$2 等方式來輕鬆指代記憶的群組;比如:
$text="Hypermethylation of E-cadherin is an independent predictor of improved survival in head and neck squamous cell carcinoma. Shematic illustration of E-cadherin in adherens junction. E-cadherin homodimer on the cytoplasmic membranes of adjacent cells is shown. Moreover, overexpression of E-cadherin, which was found underexpressed in MTX-resistant cells, also sensitized the cells toward the chemotherapeutic agent"; $text=~s/([^>])(\bE-cadherin\b)([^<])/$1$2<\/span>$3/g; print $text; # 輸出: Hypermethylation of E-cadherin is an independent predictor of improved survival in head and neck squamous cell carcinoma. Shematic illustration of E-cadherin in adherens junction. E-cadherin homodimer on the cytoplasmic membranes of adjacent cells is shown. Moreover, overexpression of E-cadherin, which was found underexpressed in MTX-resistant cells, also sensitized the cells toward the chemotherapeutic agent
在 C# 中,也可以辦到:
2008年8月30日 星期六
Windows 快速鍵
F3
在 Windows 系統裡,按下 F3 就可以呼叫出「搜尋」功能,可以輸入關鍵字後搜尋電腦裡的檔案。在 IE 瀏覽器裡,按下 F3 則可以切換到自訂的搜尋引擎網站,不需要再輸入搜尋引擎的網址或點選我的最愛。
Word 便條紙功能 Ctrl+Alt鍵+M
想要在某段文字加上 note,只要 Ctrl+Alt+M,便能呼叫「註解功能」。
「Win+F」搜尋檔案
找檔案時只要「Win+F」再輸入檔名,縮短搜尋時間。
「Win+L」立即登出電腦
暫離座位時,按「Win+L」登出系統畫面,防止竄改文件。
Word 中快速改變字母大小寫,Shift+F3
只要將想要改變的字選取起來,按下 Shift+F3 就可以讓小寫變大寫、大寫變小寫。C# static constructor
class Demo{ private static int i; private static String s; static{ i=24; s="abc" } }在 C# 則可以利用 static constructor 達到同樣的效果:
class Demo{ private static int i; private static String s; static Demo(){ i=24; s="abc" } }
2008年8月28日 星期四
中華電信推出「行動導遊 Lite」基地台定位服務
中華電信新推出的「行動導遊 Lite」服務將個人導航加值服務擴大至一般手機上,就算使用的手機沒有 GPS,也能透過基地台定位而使用這項服務。
這個服務的概念,我最早是在 Common Craft 裡看到;介紹 Google Map 的新服務:
跟中華電信的另一個利用 GPS 服務的「行動導遊」僅支援特定 AGPS 手機的加值服務相比(利用手機基地台輔助衛星定位,讓不論在室內或戶外的使用者均能快速定位並搜尋附近的生活資訊),該服務讓低階手機用戶也能使用。
與行動導遊最大不同之處,在於 Lite 透過基地台以 Cell ID 方式定位所在地,即使手機沒有 GPS 定位功能,也能定位搜尋附近影院、加油站、百貨公司與餐廳等生活資訊,甚至提供路徑規劃。不過因為所有資訊包括圖資系統均仰賴行動網路傳輸,因此較適合以 3G 手機使用。
目前只要月付 50 元,就可以無限使用這項加值服務。不過我上去晃了一下,發現不支援我的手機(囧)...原來我的手機比一般低階手機更低階...
2008年8月27日 星期三
如何做好一個合格的下屬
- 自己崗位職責上的工作,必須要自己來完成,不要什麼事情都去麻煩上司出面,要明白公司設定我們這個崗位的目的就是要完成工作的。
- 不要裝「酷」,在任何時候,面對任何問題的時候都說沒有問題,而在實際工作當中老是就有問題。不懂並不是缺點,用心學習,態度端正才是領導的最愛!
- 要充分瞭解自己的領導,不要忽略領導的感受,在開展工作的時候,要多想想領導想要的結果及欣賞的做事方法。
- 不要把領導當傻瓜。做事腳踏實地,不要表面一套背裡一套;不要油頭滑面,要知道在我們的背後有無數的眼睛。
- 不要吝嗇把功勞推給領導,記住,要想讓自己獲得成功,就必須懂得如何要讓別人先成功。我們的所有成績都應該歸功於領導的正確指導。
- 不要老是犯同樣的錯誤或不該犯的錯誤,人無完人,只要是人都有可能會出錯,但是要學會總結,同樣的問題絕對不能重犯,不該出現的問題絕對不能出現。
- 要勇於承擔責任,但問題發生時,其實損失最大是公司,不可能是個人,最為一個下屬,要勇敢的面對問題,不要推卸責任,領導是最討厭那些整天推卸責任的下屬。
- 要善於幫助領導承擔責任,但問題發生時,不僅僅是下屬的單方面問題,領導就應該付領導責任!面對這個時候,做為一個聰明的下屬,就要學會如何合理的代領導 承擔責任。但是絕對不是要下屬盲目的去承擔,要看是發生了什麼問題,不痛不癢的或者是無關決定工作前程的可以承擔,如果是發生了重大問題時,就不適合了, 作為下屬最好只付自己那些責任就可以了,不能冒然出頭!
- 工作時候要仔細謹慎,不要放棄任何一個環節,不要以為事情太小,就可以不抓。但是更要注意衡量利弊,千萬不要抓了芝麻丟了西瓜。
- 做事情時,不要老是討價還價,要知道任何一個人都是討厭老是討價還價的人。
- 面對額外的工作任務時,要端正態度,適當考慮,服從第一,拒絕時需要十足的理由,千萬別找借口。
- 有事情可以商討解決,千萬不要越過自己的上級,去反映事情,做為管理者要時刻明白,越級上報現象的弊端或容易引發的事情。
- 不要老是提問題,公司用我們是讓我們來解決問題的,不是來提問題的,一般問題的發現是普遍的,而解決問題的是很少的。作為一個合格的下屬,應該懂得反映問題的方法:提問題時,一定要有自己的見解和解決方案,拿出來一同讓領導考慮。千萬不要老是給領導製造麻煩。
- 作為一個合格的下屬,一定要注意自己的言行舉止,一般的領導都比較注重這個方面,任何一個領導不可能喜歡那些吹牛皮的人,也不可能喜歡背後議論他人是非的人,更不可能喜歡作風不良,衛生不講究的下屬。
- 和領導一起時,一定要注意保持距離,不要太近乎,否則會讓領導產生反感,或者會產生那種認為你拍馬屁的想法。和領導在一起時,也要注意千萬在面對大眾時,不要去搶領導的風頭,自己要做好一個跟班。
- 當領導遇到難題時,在自己能力範圍之內的,不管是不是自己的工作,都應該主動的,而且默默無聞的幫助領導度過難關。
- 作為一個下屬,要帶好自己的團隊,要作到自己的團隊與別人比較起來佔有絕對的優勢。在面對工作時,要作到讓領導,省心,放心,開心!
- 作為一個合格的下屬,在面對自己的工作崗位,一定要有創新的理念或事物,保持工作原狀,絕對不是公司招我們的目的,在工作上一定要有不斷的突破,一定要做的比前人好,比別人好,才可能證明自己的價值。
- 作為一個合格的下屬,應該擁有穩定的心態,不要做暴風雨類的人物,也不要什麼問題與不滿都強壓心頭,要時刻調整自己的心態,沒有過不去的坎,沒有辦不好的事情!
- 作為一個管理者,也必須要有著自己的性格,如果都和別人一樣,那在這個世界也不需要有我們的存在。做事情在不能夠違反原則的情況下,要保持著自己良好的個性。
2008年8月26日 星期二
db4o 簡介與初探
db4o object database 引擎主要由一單獨的 DLL 組成。目前版本支援了 Microsoft .NET. framework 1.0/1.1 以及 2.0。
一般 .NET framework 的 DLL 檔位於安裝目錄內的 bin/net/ 目錄底下;.NET Compact Framework 則位於 bin/compact/ 下(我使用的 6.4 版本檔名為 Db4objects.Db4o.dll)。在開發時,必須將這個 DLL 加入到參考中。
Db4objects.Db4o namespace
包含了大部分開發所需要用到的功能。其中最重要的兩個類別是 Db4objects.Db4o.Db4oFactory 和 Db4objects.Db4o.IObjectContainer。
- Db4oFactory:提供的靜態方法讓我們可以開啟資料庫檔案、啟動伺服器或是連線到既存的伺服器。另外,它也允許我們再開啟資料庫前先設定好 db4o 的環境變數。
- IObjectContainer:則是我們最常會使用到,也是最重要的資料庫程式介面。它代表的就是我們的 db4o 資料庫。
- IObjectContainer 可能是處於單一使用者模式的某個資料庫,或是一個連線到某個 db4o 伺服器的客戶端連線。
- 每一個 IObjectContainer 都擁有一個 transaction。每個執行的動作都是處於 transaction 狀態;當我們開啟一個 IObjectContainer,我們就處於一個 transaction 之中;當我們下達 Commit() 或是 Rollback(),將會馬上切換到另一個 transaction。
- 只要我們有在操作 IObjectContainers,它將會持續保持開啟連接的狀態。當我們關閉一個 IObjectContainer,所有存在記憶體中的資料庫參考將會被丟棄。
第一個 db4o 程式
我們首先常是如何儲存、擷取、更新和刪除某個只包含 primitive 以及字串成員的類別 。
public class Sentence { private string rawText; /// raw 參數代表原本的文字內容 /// section 參數則為該文字所屬的 section public Sentence(string raw, string section) { rawText = raw; this.section = section; } public string RawText { get { return rawText; } set { rawText = value; length=value.Length} } private int length; public int Length { get { return length; } set { length = value; } } private string html; public string HTML { get { return html; } set { html = value; } } private string section; public string Section { get { return section; } set { section = value; } } }
開啟資料庫
要存取一個 db4o database 資料檔或是建立一個新的資料庫,我們只要呼叫 Db4oFactory.OpenFile(),並提供我們想要存取的資料庫檔案路徑當作參數及可。該方法會回傳一個 IObjectContainer 實例。
如前述,IObjectContainer 代表的就是一個資料庫,並且扮演了我們跟 db4o 將的主要溝通橋梁。藉由呼叫 Close() 方法,將關閉該 IObjectContainer 資料庫檔,並且是放所有參考到的資訊。
// accessDb4o IObjectContainer db = Db4oFactory.OpenFile(dbfilename); try { // do something with db4o } finally { db.Close(); }
儲存物件
要儲存某個物件,我們只要對我們的資料庫呼叫 Set() 方法,並且存給它某個物件當作參數及可!
// store First Sentence object Sentence s = new Sentence("Pain management: evaluating the effectiveness of an educational programme for surgical nursing staff.", "Title"); db.Set(s); Console.WriteLine("Stored {0}", s);
取回物件
db4o 提供三種不同的 query 系統:
- Query by Example (QBE)
- Native Queries (NQ)
- SODA Query API (SODA)
當使用 QBE 時,我們會提供 db4o 一個原型物件(prototypical object)作為我們想要取得的物件的一個範例,並呼叫 Get() 方法。db4o 將會依據傳給 Get() 方法的物件的內容,從資料庫內取得包含跟我們提供的物件一樣資料值欄位的所有物件(非預設值;一般物件的預設值為 null,int 為 0),並以 ObjectSet 實例回傳(代表所有符合的物件)。
下面我們示範如何從資料庫中取得所有的 Sentence 實例。方法很簡單,我們只要提供一個空的 Sentence 原型即可(所有的資料欄位值都為預設值):
Sentence sents = new Sentence(null, null); ObjectSet result = db.Get(sents); ListResult(result); // ...略 public static void ListResult(IObjectSet result) { Console.WriteLine(result.Size()); while (result.HasNext()) { Console.WriteLine(result.Next()); } }
db4o 另外提供了一個簡便的方法讓我們可以取得某類別的所有實例:
ObjectSet result = db.Get(typeof(Sentence)); ListResult(result);對於泛型物件,可以利用 query() 方法取得:
IList <Sentence> sents = db.query<Sentence>(typeof(Sentence));
下面示範如何依據 section 來查詢:
Sentence sent = new Sentence(null, "BACKGROUND"); ObjectSet result = db.Get(sent); ListResult(sent);
更新物件
更新物件跟儲存物件的動作很類似;我們也是呼叫同樣的 Set() 方法:
ObjectSet result = db.Get(new Sentence(null, "TITLE")); Sentence found = (Sentence)result.Next(); found.Section="BACKGROUND"; db.Set(found); Console.WriteLine("Modified section for" + found);
注意很重要的一點是我們第一個步驟是先去 query 物件。假若,當我們呼叫 Set() 方法去修改一個未知的(但是實際上我們想要修改的是既存的物件)的物件;也就是說我們沒有先去 queyr 物件,那麼 db4o 將會在資料庫內插入一個新的物件。db4o 並不會自動的把我們產生的物件跟資料庫內的物件進行比對;它假設我們實際上要插入一個剛剛好有同樣值的物件到資料庫內。
刪除物件
在資料庫內的物件可經由 DELETE() 方法加以移除。IObjectSet result = db.Get(new Sentence("Pain management: evaluating the effectiveness of an educational programme for surgical nursing staff.", null)); Sentence found = (Sentence)result.Next(); db.Delete(found); Console.WriteLine("Deleted {0}", found);
Object Database 相關連結
依據之前使用 object database 的經驗,查詢速度印象中並不理想,尤其當資料量非常大的時候(不知道是不是錯誤的記憶)。
最近又想要在嘗試一下。下面列出 object database 相關連結:2008年8月24日 星期日
jQuery 筆記:用 jQuery 快速選取元素
完整的文件可以參考官方網站。以下摘錄重點:
$("div").addClass("special");$ 記號是 jQuery 的物件(其實是 jQuery 函數的縮寫),使用 $("div") 就是用 jQuery 來選取元素,這個範例可以選取文件內所有的 <div> 元素。後面接著的 .addClass("special") 就是用來做一些事情,這個範例是將先前所選取到的所有元素都加上一個名為 "special" 的 class。也就是透過 $("div").addClass("special") 的語法,可以一次幫文件上有的 <div> 元素都加入 special 的 class。
這和原本使用 JavaScript 來寫程式有很大的差異,原本自己寫可能會需要用到迴圈之類的語法,而 jQuery 的函數大多具有批次處理的功能! $ 記號 $ 是使用 jQuery 過程中最重要的函數,可以用來用來找元素;使用方式只要把參數帶入即可。下面的範例,結果將會和上面的範例一模一樣:
jQuery("div").addClass("special");如前述,$ 是 jQuery 函數的縮寫。
選取元素
前面的例子使用 $("div") 來選取元素,帶入的參數 div 表示要找的元素,這是 CSS 選擇器(CSS Selector)的語法,如同 CSS 在做排版和外觀所使用的選擇器語法一樣。jQuery 所支援的 CSS Selector 包含了 CSS 1、CSS2 以及仍未正式發佈的 CSS3,透過 plugin 還可支援常用的 XPath 語法。
這是一段原始的 HTML: 以下用一連串的範例,以展示基本的語法與文件中會被選取的元素。
$("#body")
- 選取到:<div id="body">
- 解釋:選取 id 為 body 的元素
$("div#body")
- 選取到:<div id="body">
- 解釋:選取 id 為 body 的 <div>
$("div.contents p")
- 選取到:<p>...</p><p>...</p>
- 解釋:選取 class 為 contents 的 <div> 元素所包住的所有下層的 <p>
$("div > div")
- 選取到:<div class="contents">
- 解釋:選取被 <div> 包住的下一層 <div>
$("div:has(div)")
- 選取到:<div id="body">
- 解釋:選取至少有包住一個 <div> 的 <div>
2008年8月20日 星期三
Songsterr 吉他 tab 撥放器
吉他通常採用簡譜的方式來紀錄如何彈奏歌曲。但是這種方法對於樂曲節奏的呈現上有先天的不足。
Songsterr 服務藉著在每個簡譜中插入音樂檔,來呈現樂曲原有的旋律、節奏。
2008年8月14日 星期四
Windows Vista 更新後,Word 2007 無法開啟
今天中午吃飯前,放著讓 Vista 自動更新,更新完後(應該是有自動重開機),想利用 Word 2007 改 comment,沒想到卻無法使用。症狀是:只要開啟 Word 2007,整個視窗就 hold 住;無回應。
查了一下 Word 2007 解決方案中心在「在 Windows Vista - 架構電腦上安裝自動更新 Word 2007 供您可能會遇到許多問題」一文中找到了解決方案。節錄如下:
自動更新在安裝之後,必須重新啟動電腦。不過,如果在重新啟動電腦時,正在執行 Word 2007,則可能會遇到下列問題:
- 使用 Word 2007 時滑鼠無法運作
- 無法開啟一份 Word 文件
- 嘗試啟動或結束 Word 時當機
- 開啟 [ 開啟 ] 對話方塊時, Word 停止回應
- 儲存文件時,Word 停止回應
- 關閉文件時,Word 停止回應
利用 regedit,刪除 HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Word\Data 登錄子機碼即可解決!
2008年8月13日 星期三
在 blogger 中高亮度顯示程式原始碼
從 JSPWiki 移轉到 Blogger 以來,最大的困擾除了語法不能像 Wiki 那麼簡潔之外,另一個問題就是程式碼在顯示上不能像 JSPWiki 有一些 plug-in 可使用。
一個方式大概就是利用 Format My Source Code For Blogging 的服務,可以產生格式化的語法。然後貼到 Blogger 上。
但是這種方式其實只是把原始碼稍微排版一下而已(近似於原本 Wiki 的 {{{、}}} 語法)。另一種方式就是利用類似 Hightlight Code Coverter: 將排版後的程式碼轉換成 HTML 輸出 的工具輸出 HTML 後再貼上。
不過這些方式都要繞一大圈才能。這裡介紹一種或許比較好的方式(支援高亮度顯示);利用 syntaxhighlighter。
syntaxhighlighter 支援了大部分常見的程式語言,如 C++、Java、C# 等(完整列表見此列表)。
- 首先到 syntaxhighlighter 下載 StyleHighlighter 原始碼
- 將壓縮檔內的 Scripts 和 Styles 目錄解壓到可公開存取的網站目錄內
- 修改您的 Blogger 的範本,加入如下程式碼
<link type="text/css" rel="stylesheet" href="css/SyntaxHighlighter.css"></link> <script language="javascript" src="js/shCore.js"></script> <script language="javascript" src="js/shBrushCSharp.js"></script> <script language="javascript" src="js/shBrushXml.js"></script> <script language="javascript"> window.onload = function(){ dp.SyntaxHighlighter.ClipboardSwf = '/flash/clipboard.swf'; dp.SyntaxHighlighter.HighlightAll('code'); } </script>
- 最後在以下列語法修改包含原始碼的 HTML 片段:
- 利用 <pre> tag,並設定 name 屬性為
code
、class 屬性為對應的程式語言代碼(參考此表)<pre name="code" class="c-sharp"> ... some code here ... </pre>
- 利用 <textarea> tag。
<textarea name="code" class="c#" cols="60" rows="10"> ... some code here ... </textarea>
- 利用 <pre> tag,並設定 name 屬性為
<html>HTML 測試</html>collapse
- 使用 <pre> 來包含程式碼時,中若是程式碼中有 < 符號,則必須將其置換為 <,否則原始碼可能會被截斷。
- 在 class="xxx" 中可以利用「:」指定額外的控制參數。詳細控制參數列表參考此表
2008年8月12日 星期二
2008年8月9日 星期六
2008年8月8日 星期五
2008 Best of Open Source Software Awards
- Git:Version control
- 移植到 Windows 上的版本:Git on MSys
- soapUI:Web Services Testing Tools
2008年8月7日 星期四
Mloovi RSS&Blog 翻譯服務
比如下面是 TechCrunch 的繁體中文 feed
http://mloovi.com/r/00885942775b267049eee20daf09d9d0
2008年8月5日 星期二
由 Greasemonkey script 直接產生 Firefox extension
參考這個線上工具。將 script 檔
// ==UserScript==
之後的所有原始碼直接貼上,即可產生 xpi 檔。==UserScript== 區塊中請把空白欄位去除。比如
// @include http://www.example.idv/* // @exclude ^^^^^^^^^^^^^ 移除此欄
2008年8月2日 星期六
2008年7月31日 星期四
2008年7月29日 星期二
DOM 操作範例
下拉式選單
要在 select 或是 dropdown 元件中加入新的項目:
optionItem = new option(text, value, defaultSelected, selected)
或是
var opt = document.createElement(‘option’); opt.value=value; opt.text=text; select.options.add(opt, index);
下面的程式碼示範如何取得表格目前的列數(row)。
若是表格目前沒有任何一列,則設定為 0。
var lastRow = tbl.rows.length; var row = tbl.insertRow(lastRow); var cellLeft = row.insertCell(0);
接著下面示範如何動態加入表格內容:
var totalRows='1'; //假設要完成的總列數為 1 列 var totalCols='2'; // 總行數為 2 行 var intRow; var intCol; for(intRow=0;intRow<totalRows;intRow++) { var row = tbl.insertRow(intRow); for(intCol=0;intCol<totalCols;intCol++) { var cellLeft = row.insertCell(intCol); } }
下面示範如何動態建立一個文字區塊,並設定列數和行數
var sample=document.getElementById('sample'); var el = document.createElement('textarea'); el.id="sample"; el.rows=20; // 列數 el.cols=20; // 行數 el.style.backgroundColor="#FFFFFF"; el.style.width="120px" ; el.style.height="120px"; sample.appendChild(el);動態加入文字
利用 text node 來加入文字內容:
var textNode = document.createTextNode('hi'); document.appendChild(textNode);
2008年7月27日 星期日
線上影音轉檔服務
現在越來越多的網站提供多元化的服務,也許哪天真的硬碟裡甚麼軟體都不用安裝,只要裝個網路卡驅動,加上瀏覽器就好了。
Movavi Online Video Converter 就提供了免費的線上合併、轉檔的服務,支援相當多的格式,並能直接將轉檔合併好的結果寄送到指定的 EMail 信箱,相當的方便
將排版後的程式碼轉換成 HTML 輸出
一個應用是用來貼在目前不支援程式碼 highlight 的 Blogger 上。
2008年7月26日 星期六
不要在伺服器上儲存圖檔了
var src="<a href="data:image/png,%89PNG%0D%0A%1A%0A%0DIHDR %10%08%06%1F%F3%FFa%02%A4IDAT8%8D%A5RMkSA%14%3Do%E6%E5%7D%A4I %8CIj%954j%2B%ADE%B1-%B8%90%AA%20%A2%B8%90%20%8A%8B%82hWn%0AU %04%C5b%DDt%A5%9B%FE%02%B1%08BtQp%A1%2B7B%09%8A%18%85%12%84BA lMJcb%9A%F7%F2%F1%5E%DE%D7%8C%8B%B4%86%D0%EE%1C%18%98%7B9%9Cs %E6%DE%23p%CE%F1%3FG%DC%B5%BB0%28%C1%2C%9D%E5%9C%F7%0B%02L%10 %FA%197%CB%3Fv%83%0A%1D%0E%DE_%26%CE%EA%C7%7B%96%D5%F3%98%85O F%B8%BC%1F%E0.%88%B1%02Z%FD%B6%A8F%D8%5Dab3%BB%2B%01%7Bw%81%D 8%3F3%AF%EC%E0%A5qq%28%09%A2%86A%A3%87a%D6*%F0%D5%F2%60%D5%02 %BC%EF%CF%1A%FE%60%E9%8Ax%5B%FB%B0M%40%B6%1FN%EE%EB%03%5B%19% 1B%97%8E%9E%83%E4%AFC%8A%8A%F0%25FQ%A6a%C8A%1DRT%01%3D%3E%D1% D5%D4%D4%05w%BE%BB%BB%83%C0%99%EFU%1D%2B0%A3%0C%9D%82%1C%D2%2 1%8A%1A%08%ABoA%18%08%D7%E0%93u%A8%FB%1C8%13q%1B%F6%FD%0E%02% D6%AC%9D%27%D1%81%3D%BE%80%01%C1%D1%5B%03%DCF%0B%C1%19%60i%80 %A5%810%1Dj%7F%02%9E%A7%5C%ED%D8%02s1%E0%8B%86%218U%60%7B%A6% 96%DE%D2w%9B%40%23%0F8%3A%40%7C%A0r%0Fh%28r%04%F5%1C%10Hl%AD% END%AEB%60%82</a>直接利用
var icon=document.createElement('img'); icon.src=src;即可(注意 IE 不支援)
escape、encodeURI、encodeURICompoent 方法的差異
- escape: 採用 ISO Latin 字符集對指定的字符串進行編碼。所有的空格符、標點符號、特殊字符以及其它非 ASCII 字符都將被轉化成 %xx 格式的字符編碼(xx 等於該字符在字符集表裡面的編碼的 16 進制數字)。比如,空格符對應的編碼是 %20。unescape方法與此相反。不會被此方法編碼的字符: @ * / +
- encodeURI: 把 URI 字符串採用 UTF-8 編碼格式轉化成 escape 格式的字符串。不會被此方法編碼的字符: ! @ # $& * ( ) = : / ; ? + '
- encodeURIComponent: 把 URI 字符串採用 UTF-8 編碼格式轉化成 escape 格式的字符串。與 encodeURI 相比,這個方法將對更多的字符進行編碼,比如 / 等字符。所以如果字符串裡面包含了 URI 的幾個部分的話,不能用這個方法來進行編碼,否則 / 字符被編碼之後 URL 將顯示錯誤。不會被此方法編碼的字符: ! * ( )
2008年7月19日 星期六
2008年7月13日 星期日
常用的 FF 套件
- PMOG:將普通的網頁瀏覽的動作變成一種社交性質的遊戲
- IE Tab:從此擺脫 IE 的監牢
- FireGesture:好用的滑鼠手勢
- Adblock Plus:擺脫彈出式的廣告
- Adblock Filterset.G Updater:定期更新的列表;搭配使用
- NoScript:擋掉網站的 script
- Easy DragToGo:拖拉某段文字在新分頁中開啟
- All-in-One Sidebar:整合型的側邊工具列
- Zotero:取代 EndNote 的工具
- TinyPaste Uploader:快速分享大量文字的好方法
- TinyUrl Creator:建立網址縮址的工具
- PCMan Plug-in:上 BBS 用
- 新同文堂:簡繁互轉
- 安裝時遭遇錯誤訊息:「不相容的擴充套件,因為此元件未提供經由加密連線的更新」(Does not provide secure updates)
- 解決方法:
- 網址列輸入「about:config」
- 滑鼠按右鍵,新增「真假(Boolean)值」
- 名稱輸入:extensions.checkUpdateSecurity
- 真假值的值,選擇 false,重新啟動 Firefox 即可順利安裝擴充套件
- Speed Dial:利用快速鍵 1-9 開啟網頁的工具
- Greasemonkey:支援多種加強瀏覽功能的 script 引擎
- Aardvark:修改網頁內容用
- Remove It Permanently:修改網頁內容用
- Evernote Web Clipper:筆記工具
- Tab Catalog:檢視開啟的所有分頁於單一頁面中
- Organize Status Bar:幫助您移除不必要的狀態列圖示
- Download Statusbar:取代預設的下載管理員
- Menu Editor:幫助您移除不必要的右鍵選單項目
- Organize Search Engines:管理您的搜尋引擎
- Add to Search Bar:將搜尋引擎加入到 FF 裡
- Context Search:選取文字後直接選擇要用哪個搜尋引擎搜尋
- PicLens:瀏覽網路上圖片及影像的超炫套件
- Read It Later:記錄以後才想看的網頁
- dragdropupload:支援利用拖拉方式指定上傳檔案的欄位
- View Dependencies:檢視網頁跟哪些網站有相依性
- ColorZilla:網頁取色工具
- DownloadHelper:下載內嵌在網頁中的各種影像、圖片。現在也支援將下載後的檔案,轉換為特定的格式;如將 FLV 轉成 mp4
- Abduction!:將網頁轉存成圖檔
- ScribeFire:離線編輯部落格工具
- Tab Kit:分頁管理
- Wired-Marker:替網頁加上註記
- FoxyTunes:利用 FF 直接控制撥放軟體(支援 Yahoo! Media Player)
- MeasureIt:量測 HTML 的 pixel
- Clipmarks:即刻複製、分享選取的網頁內容
- CustomizedGoogle:客制化 Google 的搜尋結果
- DownThemAll!:批次下載連結
- Fireshot:擷取畫面,並且加以注記
- Gmail Space:把 GMail 當作免費空間使用
- Hide Menubar:隱藏選單列
- iMacros for Firefox:讓 FF 自動化的做某些制式動作
- Image Zoom:隨意放大、縮寫網頁上的圖片
- Stop-or-Reload Button:將停止跟重新整理的按鈕合併
- TableTools:讓我們可以對網頁上的任意表格啟用排序等功能
- Taboo:依據日期將網頁加入稍後再讀的列表
- ViewSourceWith:指定用順手的外部編輯器檢視原始碼
- Delicious Bookmarks:存取在 delicious.com 上的書籤
- Foxmarks Bookmark Synchronizer:利用伺服器分散同步不同電腦上的書籤
- StumbleUpon:隨機您推薦有趣的網站
- DOM Inspector:檢視網頁 DOM tree 的工具
- Firebug:網站開發除錯工具
- YSlow:搭配 Firebug 檢查網站開啟緩慢的原因
- Firecookie:檢視管理網站的 cookie
- HTML Validateor:HTML 標準檢測
- Pencil:協助您快速建立程式的 prototye
- Web Developer:好用的 HTML、CSS、JavaScript 等資訊檢視工具
- Live HTTP headers:檢視送出的 HTTP 標頭資訊
- RefControl:修改送出的 HTTP Referer 標頭資訊
- Poster:直接指定送出的 HTTP POST 方法內容
- InFormEnter:快速填寫表單
- Sxipper:好用的密碼管理工具
- FEBE:FF 設定組態、密碼等備份工具 [參考]
- CLEO:將 FEBE 備份打包成單一安裝檔
2008年7月7日 星期一
網頁時光機
- 1998 年的東海大學首頁:那時候的我才剛進大學。HTML 4.0 才推出不久,還記得暑假的時候拿了一本 HTML 的語法書試著用記事本在章魚網(1998)上製作第一個個人網站;現在連帳號密碼都忘了...
- 奇摩站 kimo:那時候必逛的奇摩...現在已經變成 Yahoo 奇摩了
- 2000 年的史萊姆的第一個家:大學時另一個必逛的軟體下載網站;到現在還持續存活,而且,版面也都維持一樣,真是「很厲害」(2007 年的史萊姆和現在的史萊姆)
- 1997 年的中央研究院
- 1996 年的清華大學
2008年7月2日 星期三
I Can Has Cheezburger?
2008年6月29日 星期日
暗黑破壞神 III!
- 破壞四周的環境也可以造成怪物的損傷,這到是蠻真實的設定
- NPC 跟隨;跟以前雇用的傭兵不同的是,可能不只一個獲救 NPC 會跟著你。NPC 在跟隨的途中還會跟你對話
- 3D 畫面可拉近拉遠。多了一些比較特殊的小動作,如上下樓梯的攀爬
2008年6月28日 星期六
27 PMOG Badges and their corresponding web sites
PMOG
2008年6月20日 星期五
感謝各位鄉民的熱情贊助...恭喜 ryan 榮登今日我最囧
- bow
- sinyuhgs
- 奶油麵
- 捲米
- hongjie
- Hun
- Yu-Chun
- 查李王
- IvErSoN
- onlytaco
- 邱總
由 bow 的「好朋友說再見的時候 會互相摸來摸去嗎」一詞率先發難,接著 sinyu 立即響應,並由 hongjie 由台北總部接力傳續到桃園內壢地區。使用語言從中文、韓文,一直到日文皆有之...
2008年3月21日 星期五
在 eclipse 中撰寫 script,並利用 script 控制 eclipse platform
- 下載 eclipse
- Help→Software Updates→Available Software 中加入 Europa Discovery Site 的下載網址: http://download.eclipse.org/releases/europa/
- 如下圖,在 Other Tools 中選取安裝 Eclipse Monkey
- 安裝完後,重新啟動 eclipse,應該會在選單列中看到一個新的選單:Scripts
參考
2008年1月3日 星期四
JavaScript 的 Hashtable 實作
/******************************************************************************************* * Object: Hashtable * Description: Implementation of hashtable * Author: Uzi Refaeli *******************************************************************************************/ //======================================= Properties ======================================== Hashtable.prototype.hash = null; Hashtable.prototype.keys = null; Hashtable.prototype.location = null; /** * Hashtable - Constructor * Create a new Hashtable object. */ function Hashtable(){ this.hash = new Array(); this.keys = new Array(); this.location = 0; } Hashtable.prototype.keySet = function(){ return this.keys; } /** * put * Add new key * param: key - String, key name * param: value - Object, the object to insert */ Hashtable.prototype.put = function (key, value){ if (value == null) return; if (this.hash[key] == null) this.keys[this.keys.length] = key; this.hash[key] = value; } /** * get * Return an element * param: key - String, key name * Return: object - The requested object */ Hashtable.prototype.get = function (key){ return this.hash[key]; } /** * remove * Remove an element * param: key - String, key name */ Hashtable.prototype.remove = function (key){ for (var i = 0; i < this.keys.length; i++){ //did we found our key? if (key == this.keys[i]){ //remove it from the hash this.hash[this.keys[i]] = null; //and throw away the key... this.keys.splice(i ,1); return; } } } /** * size * Return: Number of elements in the hashtable */ Hashtable.prototype.size = function (){ return this.keys.length; } /** * populateItems * Deprecated */ Hashtable.prototype.populateItems = function (){} /** * next * Return: true if theres more items */ Hashtable.prototype.next = function (){ if (++this.location < this.keys.length) return true; else return false; } /** * moveFirst * Move to the first item. */ Hashtable.prototype.moveFirst = function (){ try { this.location = -1; } catch(e) {/*//do nothing here :-)*/} } /** * moveLast * Move to the last item. */ Hashtable.prototype.moveLast = function (){ try { this.location = this.keys.length - 1; } catch(e) {/*//do nothing here :-)*/} } /** * getKey * Return: The value of item in the hash */ Hashtable.prototype.getKey = function (){ try { return this.keys[this.location]; } catch(e) { return null; } } /** * getValue * Return: The value of item in the hash */ Hashtable.prototype.getValue = function (){ try { return this.hash[this.keys[this.location]]; } catch(e) { return null; } } /** * getKey * Return: The first key contains the given value, or null if not found */ Hashtable.prototype.getKeyOfValue = function (value){ for (var i = 0; i < this.keys.length; i++) if (this.hash[this.keys[i]] == value) return this.keys[i] return null; } /** * toString * Returns a string representation of this Hashtable object in the form of a set of entries, * enclosed in braces and separated by the ASCII characters ", " (comma and space). * Each entry is rendered as the key, an equals sign =, and the associated element, * where the toString method is used to convert the key and element to strings. * Return: a string representation of this hashtable. */ Hashtable.prototype.toString = function (){ try { var s = new Array(this.keys.length); s[s.length] = "{"; for (var i = 0; i < this.keys.length; i++){ s[s.length] = this.keys[i]; s[s.length] = "="; var v = this.hash[this.keys[i]]; if (v) s[s.length] = v.toString(); else s[s.length] = "null"; if (i != this.keys.length-1) s[s.length] = ", "; } } catch(e) { //do nothing here :-) }finally{ s[s.length] = "}"; } return s.join(""); } /** * add * Concatanates hashtable to another hashtable. */ Hashtable.prototype.add = function(ht){ try { ht.moveFirst(); while(ht.next()){ var key = ht.getKey(); //put the new value in both cases (exists or not). this.hash[key] = ht.getValue(); //but if it is a new key also increase the key set if (this.get(key) != null){ this.keys[this.keys.length] = key; } } } catch(e) { //do nothing here :-) } finally { return this; } };