套件開發指南 - Googlebar Lite
出自 MozTW Wiki
aceldaralli åæ: Creating a Firefox Toolbar Extension (Firefox 1.5)[å·²ææ¬]
ä½è Born Geek
內容大綱
- 1 åè¨ (Instruction)
- 2 第ä¸ç« ï¼æºåéå§ (Getting Started)
- 3 第äºç« ï¼å»ºç«æ¶æ§(Creating the Framework)
- 4 第ä¸ç« ï¼å»ºæ§å·¥å ·å (Structuring the Toolbar)
- 5 第åç« ï¼åæ éç¼ (Dynamic Development)
- 6 第äºç« ï¼é¢æ¿è£½ä½ (Skinning the Toolbar)
- 7 第å
ç« ï¼ä¸»ç¨å¼ (Scripting the Toolbar)
- 7.1 é£çµ XUL è JavaScript (Tying XUL to JavaScript)
- 7.2 çºæéå ä¸åè½ (Adding Functionality to the Buttons)
- 7.3 æéé¸å®ç注æäºé (A Special Note About Button-Menu Buttons)
- 7.4 çºæå°åå å ¥åè½ (Adding Functionality to the Search Box)
- 7.5 åæ ç½®å ¥é¸å® (Dynamically Populating a Menu)
- 7.6 åæ å å ¥å·¥å ·åæé (Dynamically Adding Toolbar Buttons)
- 7.7 ééèååæé (Disabling and Enabling Buttons)
- 7.8 åæ 顯示èé±èæé (Dynamically Showing and Hiding Buttons)
- 7.9 è®åèå²å使ç¨è è¨å® (Reading and Storing User Preferences)
- 8 第ä¸ç« ï¼å°è£ (Packaging the Toolbar)
- 9 第å
«ç« ï¼æ¸¬è©¦ (Testing Our Extension)
- 9.1 ç¶ Firefox ææ¯æ該æ麼辦 (What to Do if Firefox Breaks)
- 9.2 æç¨çç覽å¨è¨å® (Useful Browser Settings)
- 9.3 JavaScript 主æ§å°ç´é (Logging to the JavaScript Console)
- 9.4 æ¨æºä¸»æ§å°ç´é (Logging to the Standard Console)
- 9.5 æ件ç©ä»¶æ¨¡å檢æ¥å¨ (The DOM Inspector)
åè¨ (Instruction)
é份æåå°èªªæå¦ä½å»ºç« Firefox çå·¥å ·åå¥ä»¶(æ¯æ´ 1.5 ææ´æ°ççæ¬)ã
é份æ件æä¾å¥ä»¶å¦ä½éç¼çæ¦è¦ãå¿ è¦çå·¥å ·ã以å建ç«å·¥å ·åçç´°ç¯ãå¥ä»¶éç¼æ¯ä¸é£çï¼åç®¡å¿ é å ·åæäºåºç¤çç¨å¼è¨è¨ç¥èã
æä¸ç¨®æè¡æ¯æ建è°ä½ å¿ é ç¨å¾®çæçï¼XMLãJavaScriptãCSSãéä¸åæè¡å¸ç¿èµ·ä¾é½ä¸é£ï¼èä¸ç¶²è·¯ä¸æ許å¤ä¸é¯çæå¸ã
Firefox 1.5 çå¨å¥ä»¶éç¼ä¸æå¾å¤§çæ¹åï¼éåçæ¬æ¯å åççæ¬æ´å®¹æ建ç«å¥ä»¶ã é份æåå©ç¨äºæ¹åçé¨ä»½ï¼å¿ è¦æï¼æææåºè®åçé¨ä»½ãå¦æä½ ç¼ç¾é¯èª¤çå°æ¹ï¼ææ¯æä»»ä½å»ºè°ï¼è«è¯çµ¡ä½è ã
第ä¸ç« ï¼æºåéå§ (Getting Started)
éå§ä¹å (Before We Start)
å¨æåéå§è£½ä½ç¬¬ä¸ä»½å·¥å ·åå¥ä»¶ä¹åï¼æä¸äºé常æç¨çæ±è¥¿æ¯ä½ å¿ é è¦å ç¥éçã
ä¸è¼æå (Tutorial Downloads)
å¨é份æåçæå¾ï¼æåå°å»ºç«ä¸å Googlebar Lite çç°¡åçæ¬ãçºäºå°éç¨çå¸ç¿ææ幫å©ï¼ä½ å¯ä»¥ä¸è¼éåå·¥å ·åçéç¼çæ¬ãå ©ä»½å¯å¾å°ççæ¬ï¼
- Example Toolbar XPI : éæ¯æåå°è¦å»ºç«çå¥ä»¶çå®è£çæ¬ã
- Example Toolbar Source Code: é份 zip æªæ¡å å«å»ºç«å·¥å ·åçåå§ç¢¼ã
注æå°é份 xpi æªæ¡ä¹å å«äºåå§ç¢¼ãæè¡ä¸èè¨ï¼ä½ åªè¦ä¸è¼ xpi çæªæ¡ï¼ä¸¦ç¨ zip ç解å£ç¸®ç¨å¼è§£é xpi æªï¼ä»¥åå ¶ä¸ç jar æªã第äºä»½æªæ¡åªæ¯çºäºæ¹ä¾¿èå·²ã
æç¨çåèæç» (Useful References)
æå¼·ç建è°ä½ å°ä¸åç網åå å ¥æ¸ç±¤ï¼å¨æå¸ç¿å¥ä»¶éç¼çéç¨ï¼éäºç¶²é å°æé常çæ幫å©ï¼æç¸ä¿¡å°ä½ ä¾èªªä¹æ¯ã(ååé çºåä½è æä¾)
- XUL Planet Element Reference(è±)
- MozillaZine Extension Development Forum(è±)
- Search the Firefox Source Code(è±)
- roachfiend.com Extension Tutorial(è±)
- Building an Extension - Mozilla Developer Center(è±)
- åææ » Hello Worldââéç¼ä½ ç第ä¸åFirefoxæ´å±(ç°¡)
- limodouçå¸ç¿è¨é - XUL(ç°¡)
- The Art of IT » åºæ¼ Mozilla çæ´å±éç¼(ç°¡)
å¿ éå å¸ç¿ç (Learning the Prerequisites)
å¦æä¹åææå°çï¼Firefox å¥ä»¶éç¼éè¦å ç¥éä¸é»éæ¼ XMLãJavaScriptãåCSS çæè¡ãéä¸å主é¡é½æ¯ç¸ç¶å®¹æäºè§£çï¼æä¹ææä¾äºä¸äºéæ¼éä¸é æè¡ç說æã
ä½ å°æéè¦çå·¥å · (Tools You Will Need)
çºäºè¨è¨å¥ä»¶ï¼ä½ éè¦å¹¾åå·¥å ·è»é«ï¼éäºè»é«é½æ¯å è²»å¯åå¾çãæåè¦è¨è¨çå¹¾åæªæ¡é½æ¯æ¨æºæåæªãå æ¤ï¼ä½ éè¦ä¸åä¸é¯çæå編輯å¨ãæå¼·çåå°ä½¿ç¨é¡ä¼¼ Microsoft Word çç¨å¼ã網路ä¸æä¸äºååºçå è²»ç¨å¼è¨è¨æå編輯å¨ï¼éäºç·¨è¼¯å¨å°ä½ æé常大ç幫å©ï¼ä¾å¦èªå縮æã強調èªæ³ççãå¹¾ååæ¡è¿ç編輯å¨å å« Crimson EditorãTextPadãå JCreatorãEmEditorã
第äºåä½ æç¨å°çå·¥å ·æ¯ zip æªçå£ç¸®è»é«ãéç¶æå ¶ä»éå¤æç¨çå·¥å ·ï¼åæ¯ 7-Zipãå WinRARï¼ä½æå人æ¯ä½¿ç¨ WinZipãç¶å°è£å¥ä»¶æï¼æåæç¨å°éåå·¥å ·ãå¦æä½ æç®åå¾å¤å¥ä»¶çéç¼ï¼æ建è°ä½ æ¾æå½ä»¤åä»é¢çå£ç¸®å·¥å ·ã使ç¨å½ä»¤åå¯ä»¥è¼æå°å°å°è£éç¨èªååï¼ä¹çä¸ä½ 大éçæéã
æªæ¡çµæ§ä½å± (File Structure Layout)
å¥ä»¶éç¼éè¦ç¹å®çå §é¨çµæ§ï¼æ以æåå¿ é 確å®éä¸æ¥æ¯æ£ç¢ºçãå¦åï¼å°ä¸æç¼çä½ç¨ãé¦å ï¼çºæåçå¥ä»¶å»ºç«æä¸å±¤çç®éãå¨é份æåï¼æåæä½¿ç¨ TutToolbar ç¶ä½ç®éå稱(é¿å 使ç¨ç©ºç½æå)ãå¨éåæ°å»ºç«å¥½ç TutToolbar ç®é裡ï¼æåéè¦å建ç«ç¬¬äºåç®éãéåç®éå½åçº chrome (使ç¨å°å¯«) ãæ¢ç¶æåé麼åæ¡å»ºç«ç®éï¼é£å°±åä¾å»ºç«ç¬¬ä¸åå§ï¼éæ¬¡å¨ chrome ç®é裡建ç«ä¸ååç¨±çº content çç®é(使ç¨å°å¯«)ãé裡æ¯æåçç®éçµæ§çèµ·ä¾ç樣åï¼
+- TutToolbar/ +- chrome/ +- content/
æè æ¯
TutToolbar/ TutToolbar/chrome/ TutToolbar/chrome/content/
第äºç« ï¼å»ºç«æ¶æ§(Creating the Framework)
å¥ä»¶çæ¶æ§æ¯ç¨ä¾å訴 Firefox å¥ä»¶æ¯å¦ä½è¢«å»¶ä¼¸çï¼æªæ¡ççµæ§ã被誰建ç«ãææ¯å¥ä»¶çå ¨çå¯ä¸ä»£è(GUID)ãå¨ Firefox 1.5 éåçæ¬ï¼å¥ä»¶éç¼å¨éåé¨ä»½æå¾å¤§çè®åãåæ¬å¨ 1.0.x çæ¯å¾æ²éçæå·§ï¼å¨ 1.5 çå·²ç¶è®å¾æ´æ´æ½ãæ´ç°¡å®ã
å®è£æ¸ å® (Installer Manifest)
éä»½æ¸ å®æ¯ç¨ä¾æä¾ Firefox éæ¼å¥ä»¶çç´°ç¯ãæä¸äºéè¦çé ç®æ¾ç½®å¨éåæªæ¡ï¼æ以æåå¿ é 確å®éé¨ä»½æ¯æ£ç¢ºçãå¨ä½ çæä¸å±¤ç®é裡ï¼å»ºç«ä¸åæªæ¡ install.rdf ãç¶ä½ 建ç«å¥½éåæªæ¡ï¼ä½ æçå°é樣ççµæ§ï¼
+- TutToolbar/ +- install.rdf +- chrome/ +- content/
å¨æåéå·¥åï¼è®æåççéåç¯ä¾ãæææåå¿ é 編輯çé¨ä»½å·²ç¶è¢«çªé¡¯åºä¾äºï¼æ²æ被çªé¡¯çé¨ä»½æ¯ä¸å¯ä»¥ä¿®æ¹çãæ¥èï¼æåä¾çé份æªæ¡çå §å®¹ï¼æå°æ解éæ¯åé¨ä»½çç´°ç¯ï¼èä¸å¯ä»¥éå§ç·¨è¼¯å±¬æ¼èªå·±çå¥ä»¶ã
<?xml version="1.0"?> <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> <!-- Required Items --> <em:id>yourextension@yoursite.com</em:id> <em:name>Your Extension's Name</em:name> <em:version>1.0</em:version> <em:targetApplication> <Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>1.5</em:minVersion> <em:maxVersion>1.5.0.*</em:maxVersion> </Description> </em:targetApplication> <!-- Optional Items --> <em:creator>Your Name</em:creator> <em:description>A description of the extension</em:description> <em:homepageURL>http://www.yoursite.com/</em:homepageURL> </Description> </RDF>
å¨æä¸é¢ç¬¬ä¸è¡è¡¨ç¤ºéæ¯ä¸ä»½ XML æ ¼å¼çæªæ¡ã第äºè¡ï¼ä»¥ <RDF> éé çï¼æ¯é份æ件çåºæ¬å ç´ (root element)ãå®ç責任æ¯è¾¨å¥éé¨ä»½æ¯ RDF (Resource Description Framework) æ ¼å¼ãä¸ä¸åæ¨ç±¤(Tag) <Description> å樣å°æ¯ç¨ä¾è¾¨å¥çºå®è£æ¸ å®ãç¾å¨ï¼ä¹å³çæ±è¥¿é½çµæäºï¼è®æåçç第ä¸é¨ä»½å¿ é è¦ç·¨è¼¯çï¼
<em:id>yourextension@yoursite.com</em:id> <em:name>Your Extension's Name</em:name> <em:version>1.0</em:version>
第ä¸åæåéè¦æå¿çæ¯å¥ä»¶çèå¥è碼ãå¨ Firefox 1.5 ä¹åççæ¬ï¼å¿ é 使ç¨å ¨çå¯ä¸ä»£è(globally unique identifier)ï¼å³ GUIDãå管 GUID éæ¯è¢«æ¯æ´çï¼æ°çæ ¼å¼å»æ´å®¹æ使ç¨ãå å éè¦ä½¿ç¨ä½ çå¥ä»¶å稱ï¼ï¼ 符èï¼åå ä¸ä½ ç網ç«çæä¸å±¤ç¶²åãå¨é份æåä¸ï¼æåçºéåå·¥å ·å使ç¨éåå¼ tuttoolbar@borngeek.com ã
æ¥èæ¯å¥ä»¶çå稱(éæ顯示å¨å¥ä»¶ç®¡çå¡è£¡)ãå¨æåçç¯ä¾è£¡ï¼ä½¿ç¨ Toolbar Tutorial çºéåå¥ä»¶çå稱ã確å®éåå稱ä¸å å«çæ¬ç·¨èï¼å çºçæ¬ç·¨èæå®èªå·±å°å±¬çæ¨ç±¤ãæåè¦ç·¨è¼¯çéåæ¨ç±¤å°±å¨ä¸ä¸è¡ãæ¢ç¶éæ¯æå試åè¦åç第ä¸åå·¥å ·åå¥ä»¶ï¼è®éåå¼çº 1.0 ãè¦æ³¨æå°ï¼å¨ç實çæ æ³è£¡ï¼ç¶ä½ ç¼è¡¨æ°çæ¬çå¥ä»¶æï¼å¿ é æ´æ°éåå¼ï¼æ述解è¯ç¨å¼(Scripter)å¨èªåæ´æ°éç¨æä¸æç¼çåé¡ãå¨æçå¥ä»¶è£¡ï¼æå©ç¨äºæè¿°èªæ³ (以 Perl 寫æ)ãå¨é份æåç第ä¸ç« ï¼æå°æåè¨´ä½ æå¦ä½ä½¿ç¨ã
ä¸ä¸ååå¡ä¹æ¯éåå®è£æ¸ å®éè¦çä¸é¨åï¼æ¥èä¾ççéé¨ä»½ï¼
<em:targetApplication> <Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>1.5</em:minVersion> <em:maxVersion>1.5.0.*</em:maxVersion> </Description> </em:targetApplication>
éååå¡æ¯ç¨ä¾æ示å¥ä»¶è¦ç¨å¨åªåç¨å¼ãå¨éåä¾åï¼æåè¦éç¼ Firefox çå¥ä»¶ãå æ¤ï¼<em:id> éåå ç´ æå®äº Firefox ç GUID ãä½ ä¸æ該æ¹è®éåå¼ï¼å¦åï¼æè®ä½ çå¥ä»¶ç¡æ³è¢«æ£ç¢ºå°å®è£ã
å¯ä¸å ©åæåéè¦è®åçï¼æ¯éå ©åå ç´ ï¼<em:minVersion> ã <em:maxVersion> ãéå ©åå ç´ ææå¥ä»¶é©åç¨å¨ Firefox çåªåçæ¬ ( minVersion æ¯æä½æ¯æ´çæ¬ï¼è maxVersion æ¯æé«æ¯æ´çæ¬) ã å¨æåçç¯ä¾ï¼æåæä½¿ç¨ 1.5 (minVersion) è 1.5.0.* ï¼maxVersion)ãå çºæåå©ç¨ Firefox 1.5 çéç¼ç°å¢ï¼æ以ä¸å¯ä»¥æ minVersion è¨å®çæ¯ 1.5 éå°ã
注æå°ï¼ä½ æ使ç¨ççæ¬ç·¨èå¿ é éµå®æ¨æºåå®ãèåä¾åï¼ã1.5 Release Candidate 1ãæ¯ä¸è¡çãç®å Firefox ççæ¬çµæ§æ¯ç¸ç¶å´è¬¹çï¼å¨ Mozilla Developer Center çæç« Toolkit Version Format æ詳細çæè¿°ãæ建è°ä½ è®éç¯æç« ï¼ä»¥äºè§£æ樣çå串æ¯è¢«å 許çã
å¨å®è£æ¸ å®çæå¾ï¼æ¯ç¨ä¾æè¿°å¥ä»¶çè³æå®ç¾©ï¼æ稱ä¸ç¹¼è³æ(meta-data)ï¼
<!-- Optional Items --> <em:creator>Your Name</em:creator> <em:description>A description of the extension</em:description> <em:homepageURL>http://www.yoursite.com/</em:homepageURL>
å°±å¦è¨»éä¸æ¨£ï¼éäºå ç´ æ¯éå¿ è¦çã<em:creator> å 許å¥ä»¶ä½è ææèªå·±çååï¼é樣å¥äººå°±ç¥éæ¯èª°è£½ä½éåå¥ä»¶ãä¸ä¸åï¼<em:description> å 許æåå°æåçå¥ä»¶åä¸äºèªªæï¼éå說ææ顯示å¨å¥ä»¶ç®¡çå¡ä¸çå¥ä»¶å稱åºä¸ãæå¾ï¼<em:homepageURL> å 許æåææå¥äººå¯ä»¥å¨åªè£¡æ¾å°æåçå¥ä»¶ã
注æå°ï¼éäºä¸æ¯å¯ä¸çè³æå®ç¾©ï¼åæä¹æ許å¤å ¶ä»å¯é¸ç¨çé ç®ãèåä¾åï¼æåå ç´ å¯ä»¥å¨å¥ä»¶ç®¡çå¡ä¸ä½¿ç¨æåèªå·±çå示(icon)ã å¦ä¸åå ç´ å 許æåæå®èªè¨é¸é çä½ç½®ææ¯ãéæ¼ãçå°è©±è¦çªãå ¨é¨å¯ç¨çå ç´ (ä¹å«åå±¬æ§ properties )ï¼å¯ä»¥ççå¨Mozilla Developer Center ä¸çæç« Installer Manifests ãæå¾ä¸é»è¦æ³¨æçï¼ææçå ç´ æ¯ä¸éè¦æç §é åºçãä¹å°±æ¯èªªï¼ä½ å¯ä»¥å°å®åæ¾å¨æªæ¡ä¸ä»»ä½å°æ¹ï¼å å è¦æ³¨æçæ¯ï¼å°å®åæ¾ç½®å¨ <Description> è </Description> ä¹éã
ç¾å¨ï¼æåäºè§£äºå®è£æ¸ å®ï¼è®æåä¾ççæå¾ç樣åï¼éåçæ¬å°è¢«ä½¿ç¨å¨é份æåä¸ãä½ å¯ä»¥ç´æ¥å°ä¸é¢çé¨ä»½ï¼è¤è£½å¨ install.rdf ä¸ã
<?xml version="1.0"?> <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> <!-- Required Items --> <em:id>tuttoolbar@borngeek.com</em:id> <em:name>Tutorial Toolbar</em:name> <em:version>1.0</em:version> <em:targetApplication> <Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>1.5</em:minVersion> <em:maxVersion>1.5.0.*</em:maxVersion> </Description> </em:targetApplication> <!-- Optional Items --> <em:creator>Jonah Bishop</em:creator> <em:description>An example toolbar extension.</em:description> <em:homepageURL>http://www.borngeek.com/firefox/</em:homepageURL> </Description> </RDF>
Chrome æ¸ å® (Chrome Manifest)
Chrome æ¸ å®æ¯ Firefox 1.5 æéå§æçãå¨ä¹åï¼ææçè³æ被è¨å®å¨å ©åå°æ¹ï¼å®è£æ¸ å®(installer manifest)ãå contents.rdf ãèç¾å¨ï¼æ°çæ ¼å¼é¡¯å¾æ´ç°¡å®ãå次å¨æä¸å±¤ç®é建ç«å¦å¤ä¸åæªæ¡ chrome.manifest ãä¸é¢æ¯æªæ¡çµæ§çèµ·ä¾ç樣åï¼
+- TutToolbar/ +- install.rdf +- chrome.manifest +- chrome/ +- content/
Chrome æ¸ å®æ¯ç¨ä¾å訴 Firefox ï¼æåçå¥ä»¶æä¾çå°è£(package)èè¦è¼(overlay)ãå¨æåéå§å»ºç«ä¹åï¼å çåç¯ä¾ï¼
content myextension chrome/content/ overlay chrome://browser/content/browser.xul chrome://myextension/content/overlay.xul locale myextension en-US chrome/locale/en-US/ skin myextension classic/1.0 chrome/skin/
èæ©å 使ç¨ç contents.rdf (éå¸¸è¶ é20è¡) æ¯è¼ï¼ç¾å¨çæ¹å¼è®å¾é常簡å®ï¼ç¬¬ä¸è¡ä½¿ç¨ä½ æå®çå°è£å稱ä¾ç»éï¼ä¸¦æææ¾ç½®å¨ content ç®éãéå°å 許 chrome è³æºèå¥å串(Uniform Resource Identifierï¼ç°¡ç¨± URI) ï¼å¦ chrome://myextension/content/ï¼å¨æåçå¥ä»¶å±¤ç´ä¸æåé©ç¶çå°æ¹ã注æï¼å°è£å稱åªè½ä»¥å°å¯«è¡¨ç¤ºï¼å ¶ä»æ··å大å°å¯«ï¼ææ¯å ¨é¨å¤§å¯«çå稱é½æ¯ä¸å 許çã
注æå°ï¼content ç®éçä½ç½®æ¯ç¸å°æ¼å¥ä»¶çæ ¹ç®éãå¨é份æåï¼æåä½¿ç¨ tuttoolbar ç¶ä½å°è£å稱ã
第äºè¡ç»é chrome://browser/content/browser.xul çè¦è¼(overlay)ï¼éå è¨±ä½ æ°å¢æä¿®æ¹ Firefox 主è¦çªç使ç¨è ä»é¢(user interface)ã
å¨ä¸é¢çç¯ä¾ï¼chrome://myextension/content/overlay.xul æå®äºè¦è¼(overlay)çXUL æªæ¡ã
æå¥è©±èªªï¼ä½æ¼å¥ä»¶ä¸ content ç®éç overlay.xul æªæ¡ï¼æ¯æåå°è¦æ°å¢ç使ç¨è ä»é¢(å·¥å ·å)ãå¨éåé¨ä»½ï¼æåè¦ä½¿ç¨çå¼çº chrome://tuttoolbar/content/tuttoolbar.xul ã ä¸ä¸è¡èªªæå°ååå¦ä½å»ºç«(how a locale can be created)ãå¨é份æåä¸ï¼æåä¸è¨è¨å°åå(éç¶éç¨å¾ç°¡å®)ï¼éå°å¨æªä¾ååè¨è«ã
æå¾ä¸è¡è¨å®äºé¢æ¿(skin)ï¼æåå°ä½¿ç¨éåæå·§ä¾ç¾åæåçå·¥å ·åãç¾å¨ï¼å ç¥éå®ï¼æåå°å¨ç¬¬äºç« ååä¾è¨è«éé»ã ä¸åé½å¾ç°¡å®ï¼ä¸æ¯åï¼ä¸é¢æ¯æåå°æ使ç¨ç chrome æ¸ å®ï¼éåªæ¯åæåï¼ä¹å¾æåå°æå å ¥é¢æ¿çè³è¨ãåä¸æ¬¡ï¼å°ä¸é¢çç¨å¼ç¢¼è¤è£½å°æååå建ç«ç chrome.manifest ã
content tuttoolbar chrome/content/ overlay chrome://browser/content/browser.xul chrome://tuttoolbar/content/tuttoolbar.xul
ç¾å¨æ¶æ§å·²ç¶å¯ä»¥äºï¼æ¥èè®æåä¾åäºæ趣çäºå§ï¼
第ä¸ç« ï¼å»ºæ§å·¥å ·å (Structuring the Toolbar)
Firefox å¥ä»¶ç使ç¨è ä»é¢é¨ä»½æ¯ä½¿ç¨ XUL æè¡ (é³ï¼zool)ï¼éæ¯ä¸ç¨®ç¨ä¾è¨è¨ä½¿ç¨è ä»é¢çæ¨ç¤ºèªè¨ãXUL å¯ä»¥æ³ææ¯ä¸ç¨® XML ç調å³æ(ææ¨æéå åè½ç)ï¼ å®ä¸éæ¯ä½¿ç¨é è¨å ç´ ç XML (ä¹å«å widgets)ãä½¿ç¨ XUL ç好èï¼æ¯å çºå®ä½¿ç¨äºåæ è¦è¼(dynamic overlays)çæè¡ãåæ è¦è¼æè¡å¯ä»¥è®éç¼è ä¸éè¦æ¹è®åæ¬ä»é¢çç¨å¼ç¢¼çæ æ³ä¸ï¼å»ä¿®æ¹è¦çªç使ç¨è ä»é¢ãå¨ä¸éæ´ååå§ç¨å¼ç¢¼çæ æ³ä¸ï¼å¯ä»¥è®æåå°æ³¨æ¼è¨è¨æåçå¥ä»¶ï¼èä¸ç¨æå¿éè¦éè¤éç¼çåé¡ãå¨éåç« ç¯ï¼æåè¦ä¾ççè¨è¨å·¥å ·åç XUL å¿ è¦æ¨ç¤ºãè¨ä½ï¼XUL å å æ¯ç¨ä¾å»ºæ§å·¥å ·åèå·²ãçºäºè®å·¥å ·åå¯ä»¥éä½ï¼æåå¿ é ä½¿ç¨ JavaScript ï¼éé¨ä»½å°å¨ç¬¬å ç« æå°ã
å¨ content ç®é裡ï¼å»ºç«ä¸åæªåçº tuttoolbar.xul çæªæ¡ãå¨ä½ 建ç«å¥½ä¹å¾ï¼ç®éççµæ§ææ¯é樣ï¼
+- TutToolbar/ +- install.rdf +- chrome.manifest +- chrome/ +- content/ +- tuttoolbar.xul
ç¾å¨ï¼æåå·²ç¶å»ºç«å¥½éåæªæ¡ï¼å¯ä»¥éè¡å°éå§è¨è«å §å®¹ãé¨èé²è¡çè ³æ¥ï¼ææå°æªæ¡çææå §å®¹ï¼ä¸æ¥ä¸æ¥å°ä»ç´¹ãéæè®éç¨çèµ·ä¾æ´ç°¡å®ï¼å¨éç« ç¯çæå¾ï¼éåæªæ¡æç¸ç¶å¥å ¨ã
å çº XUL åªæ¯ä¸ç¨® XML ç調å³æï¼æ以第ä¸è¡å¿ é æ¯ä½¿ç¨ XML ç宣åï¼
<?xml version="1.0"?>
ç¾å¨ï¼å®£åéæ¯ä¸å XML çæªæ¡ä¹å¾ï¼æåå°±å¯ä»¥éå§èç± overlay å ç´ è¨è¨è¦è¼äºãéåå ç´ å°ææ¯éæ´ä»½æ件çæ ¹å ç´ ãæå¥è©±èªªï¼ææå ¶ä»çå ç´ å¿ é å¨ <overlay> è </overlay> ä¹éãéæ¯ overlay çèµ·ä¾ç樣åï¼
<overlay id="TutTB-Overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> </overlay>
éåå ç´ æå ©å屬æ§ï¼id è xmlns ãéè· HTML é¡ä¼¼ï¼id çå¼å¿ é æ¯å¯ä¸çãæ´éè¦çæ¯ï¼éä¹å¿ é æ¯æ´åç覽å¨å¯ä¸çå¼ãé裡æä¸åå¯ä»¥è®ä½ 確å®æ使ç¨ç ID æ¯å¯ä¸çæ¹æ³ãä¾å¦ï¼ä¸é¢çç¯ä¾ãä½ å¯ä»¥æ³¨æå°æ使ç¨äº TutTB éé çåç¼ä¾å®ç¾© id 屬æ§çå¼ã使ç¨ç¬¦åä½ çå¥ä»¶å稱éé çåç¼ï¼éæ使 ID æ¯å¯ä¸çå¯è½æ§æé«ã並ä¸æ³¨æå°ï¼å¯¦éçå¼æ¯ä¸éè¦å å« overlay çåç¼ï¼æé麼åæ¯æ¹ä¾¿æ追蹤æ使ç¨çå稱æ¯åä»éº¼ç¨çã
第äºå屬æ§ï¼xmlnsï¼ç¨ä¾æå®ä½¿ç¨æ¼è¦è¼çå½å空éãæ¢ç¶éæ¯ XUL æ件ï¼æåå¿ é å®ç¾© XUL çå½å空éï¼éæ¯ä½ æä¸ç´ç¨å°çå¼ã
å·¥å ·ç®±èå·¥å ·å (The Toolbox and Toolbar)
ææçå·¥å ·åæ該被éä¸å¨å·¥å ·ç®±ä¸ãæåä½¿ç¨ toolbox å ç´ ä¾æå®ä¸åå·¥å ·ç®±(è¨ä½ï¼éåå ç´ å¿ é 被æ¾ç½®å¨ overlay ä¹éã)ï¼
<toolbox id="navigator-toolbox"> </toolbox>
注æå°ï¼éå id 屬æ§æä¸åé è¨å¼ï¼navigator-toolbox ã éåç¹å®çå¼è¡¨ç¤ºçº Firefox è¦çªä¸ä¸»è¦çå·¥å ·ç®±å ç´ ï¼è·çè¦½å·¥å ·åãé¸å®åã網ååï¼ææ¯å ¶ä»é¡ä¼¼çæ§å¶é¸é ä¸æ¨£ãèç±æå®éåç¹å¥çå·¥å ·åï¼æåå¯ä»¥ç¢ºå®éåå·¥å ·åæèå ¶ä»çå·¥å ·åé æå¨ä¸èµ·ãæ建è°ä½ 總æ¯è®ä½ çå·¥å ·åæ¾å¨éåç¹å®çå·¥å ·ç®±ä¸ï¼éä¸åªè®ä½ æçèµ·ä¾ä¸è´çå·¥å ·åï¼ä¹å¯ä»¥è®ä½ å¨ ã檢è¦>å·¥å ·åã ä¸ï¼å¿«éå°å°ä½ çå·¥å ·åé±èææ¯é¡¯ç¤ºã
è®æåå°æ³¨æåæ¾åå° toolbar å ç´ ï¼æåæå°éåå ç´ æ¾å¨ toolbox ä¹ä¸ãççéåç¯ä¾ï¼
<toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T" class="chromeclass-toolbar" context="toolbar-context-menu" hidden="false" persist="hidden"> </toolbar>
è®æåä¾ççéåå ç´ ç屬æ§ï¼
- toolbarname - éåå ç´ æå®å¥ä»¶çå稱(éææ¯ä½ å¨ã檢è¦>å·¥å ·åãçå°çæå)ã
- accesskey - 給éåå·¥å ·åæå®åæ¯ï¼ç¨ä¾ç¶ä½å¿«ééµä½¿ç¨ãå¨éåå·¥å ·åæåä¸ï¼æå使ç¨å¤§å¯«ç T ãéç¶éæ¯éå¿ è¦ç屬æ§ï¼éæ¯å¼·ç建è°ä½ 使ç¨å®ï¼éè½è®ä½¿ç¨è åªè¦ç¨å¿«ééµå°±è½éåæééä½ çå·¥å ·åã
- class - çºå·¥å ·åæå®ç¹å®ç樣å¼é¡å¥ãé è¨å¼ chromeclass-toolbar æ¯ç¨ä¾è¦ç¯å·¥å ·å顯示模å¼çé¡å¥ï¼å樣å°ï¼éæ¯å»ºè°ä½¿ç¨çéå¿ è¦å±¬æ§ã
- context - æå®ç¶å¨å·¥å ·åä¸æå³éµæï¼æ顯示çå·¥å ·åé¸å®(context menu)ãä½ å¯ä»¥æä¾ä½ çé¸å® ID å¼ï¼ææ¯ä½¿ç¨ toolbar-context-menu ä¾å°é¸å®æ¾ç½®å¨ãæª¢è¦ > å·¥å ·åãã
- hidden - æå®å·¥å ·åæ¯å¦é±èãé è¨çæ æ³ä¸ï¼æåè¦è®ä½¿ç¨è çè¦æåçå·¥å ·åï¼æ以è¨å®éåå¼çº false (ç¸åçº ture )ã
- persist - This attribute is a space separated list of attributes that should persist across browser sessions. å¨ä¸é¢çç¯ä¾ï¼æä½¿ç¨ hidden ï¼ç¨ä¾å訴 Firefox å¨ sessions è¨ä½å·¥å ·åçé±èçæ ã注æå°ï¼å¦æä½ çå·¥å ·åæ²æä½¿ç¨ id 屬æ§ï¼å persist 屬æ§ä¸æç¼çä½ç¨ï¼æ以è¦ç¢ºå®ä½ æçºä½ çå·¥å ·åæå® id å ç´ ã
ä½ å¯ä»¥å¨ XUL Planet toolbar element's attributes çå°å®æ´çåèæç»ã
ç¾å¨ï¼è®æåä¾çç建ç«å¥½çè¦è¼æªæ¡[View XUL Overlay Revision 1]ï¼
<?xml version="1.0"?> <overlay id="TutTB-Overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <toolbox id="navigator-toolbox"> <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T" class="chromeclass-toolbar" context="toolbar-context-menu" hidden="false" persist="hidden"> </toolbar> </toolbox> </overlay>
å·¥å ·åæé (Toolbar Buttons)
å¨ Firefox ä¸ï¼å·¥å ·åæéæä¸ç¨®ï¼ä¸è¬ãé¸å®ãæéé¸å®ãéäºé½æ¯ç¨ toolbarbutton ä¾å»ºç«çï¼è®æåä¾åå¥ççãè¨ä½ï¼éäºå ç´ å¿ é æ¾å¨ toolbar å ç´ ä¹ä¸ã
ä¸è¬æé (Normal Buttons)
éæ¯ç¨ä¾å»ºç«ä¸è¬çæéï¼
<toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web" label="Web Search" oncommand="TutTB_Search(event, 'web')" />
å®æä¹å¾ï¼ä¾ççéåå ç´ ç屬æ§ï¼
- tooltiptext - ç¶æ»é¼ 移åå°æéä¸æåºç¾ç說æã
- label - å·¥å ·åæé顯示çæåã
- oncommand - ç¶ oncommand äºä»¶è§¸ç¼æ(æä¸æé)ï¼ä½ ææå®çç¨å¼ç¢¼ãå¨éåç¯ä¾ï¼ä½¿ç¨ TutTB_Search()å½å¼ï¼æåå°å¨ç¬¬å ç« è©³ç´°èªªæã
ä½ å¯ä»¥å¨ XUL Planet toolbarbutton element's attributes æ¾å°å®æ´çåèæç»ã
é¸å®æé (Menu Buttons)
ç¶é»ææéé¸å®æï¼æåºç¾ä¸æå¼é¸å®ã å管éåæéæ¨è¨é¡ä¼¼ä¸è¬æéæ¨è¨ï¼æåéæ¯å¿ é å å ¥ menupopup å ç´ ï¼è®é¸å®ä»¥æåæ³è¦ç樣ååºç¾ãçºäºç°¡æ½é»ï¼ä¸é¢çç¯ä¾åªå å«å ©åé¸å®é ç®ã
<toolbarbutton id="TutTB-MainMenu" type="menu" tooltiptext="Tutorial Toolbar Main Menu"> <menupopup> <menuitem label="Google Home Page" accesskey="G" tooltiptext="Navigate to Google" oncommand="TutTB_LoadURL('http://www.google.com/')" /> <menuseparator /> <menuitem label="Born Geek Website" accesskey="B" tooltiptext="Navigate to Born Geek" oncommand="TutTB_LoadURL('http://www.borngeek.com/')" /> </menupopup> </toolbarbutton>
toolbarbutton æå ©åè¦æ³¨æçè®åã第ä¸ï¼type 屬æ§æå®äº menu çå¼ï¼èªªæäºéæ¯åé¸å®æéï¼èä¸æ¯ä¸è¬æéã第äºï¼ä½ æ注æå°é裡é¢æ²æ oncommand 屬æ§ãå çºé¸å®æéçå¯ä¸ç®çæ¯çºäºé¡¯ç¤ºè·³åºå¼é¸å®ï¼ä¸¦ä¸éè¦å·è¡ä»»ä½ç¨å¼ç¢¼ï¼è顯示é¸å®çåä½æç± Firefox èªåå®æã
ä¹è«æ³¨æå° menupopup ï¼menuitem ï¼menuseparator éä¸åå ç´ ãmenupopup ææé¸å®é ç®ç容å¨ï¼ç¨ä¾å»ºç«è顯示é¸å®ãå¨éåç¯ä¾è£¡ï¼éåå ç´ æ²æ屬æ§ãå樣å°ï¼menuseparator ä¹å¾ç°¡å®ï¼å¨ä¸æå¼é¸å®ä¸æ¾ç½®æ°´å¹³åéç·ï¼ç¨ä¾åéä¸åçé¸å®ã
menuitem ç¨å¾®æé»è¤éãå¨ä¸é¢çç¯ä¾ï¼æåæå®ç屬æ§ï¼
- label - æå®é¸å®é ç®çæåã
- tooltiptext - éå屬æ§å°±åæ¯æåå¨ toolbarbutton çå°çï¼ä½æ¯æä¸é»è¦è¦åçãç±æ¼ Firefox ç bug (bug #147670)ï¼éå屬æ§æ¯å¿ è¦çãå¦æä½ æ±ºå®å¾ menuitem ä¸åªæéå屬æ§ï¼ç¶ä½¿ç¨è å°æ»é¼ 移åå°é¸å®é ç®æï¼æçä¸å°æ示說æãé¸å®ä¸æé¡¯ç¤ºå·¥å ·æ示ï¼éçæ¯å令人ä¸æ»¿æçãç¹è²ãï¼
ä½ å¯ä»¥å¨ XUL Planet menuitem element's attributes æ¾å°å®æ´çåèæç»ã
æéé¸å® (Button-Menu Buttons)
第ä¸ä¹æ¯æå¾çæéé¸å®æ¯ä¸ç¨®ä¹ä¸æè¤éçã實éä¸ï¼çµåäºåå ©ç¨®æéï¼æä¾å¯é»ææéçä¸æå¼é¸å®ã
ãä¸ä¸é ãèãä¸ä¸é ãç覽é¸å®æ¯éåæéé¸å®çç¯ä¾ï¼éæ¯éè¦å»ºç«çæ¨è¨ï¼
<toolbarbutton id="TutTB-Combined-Button" label="Search" type="menu-button" tooltiptext="Combined Search" oncommand="TutTB_Search(event, 'web')"> <menupopup> <menuitem id="TutTB-Combined-Web" label="Web Search" class="menuitem-iconic" tooltiptext="Search the Web" oncommand="TutTB_Search(event, 'web'); event.preventBubble();" /> <menuitem id="TutTB-Combined-Image" label="Image Search" class="menuitem-iconic" tooltiptext="Search Images" oncommand="TutTB_Search(event, 'image'); event.preventBubble();" /> </menupopup> </toolbarbutton>
æå ©åå¼å¾æ³¨æçè®åï¼å¨ toolbarbutton ç type 屬æ§æå®äºå¼ menu-button ï¼èä¸æå¦å¤ä¸è¡ç¨å¼ç¢¼ oncommand ï¼ææå¨ç¬¬å ç« è§£ééé¡å¤çç¨å¼ç¢¼ãæ¥è注æå°ï¼é裡æè·ãä¸è¬æéãä¸æ¨£ç toolbarbutton æ oncommand 屬æ§ï¼ä»¥åå¨ãé¸å®æéã裡çå·¢çå ç´ menupopup è menuitem ã
ç¾å¨ï¼æåè¨è«å®ä¸åçæéï¼ä¾ççç¨å¼ç¢¼ç樣å[View XUL Overlay Revision 2]ï¼
<?xml version="1.0"?> <overlay id="TutTB-Overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <toolbox id="navigator-toolbox"> <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T" class="chromeclass-toolbar" context="toolbar-context-menu" hidden="false" persist="hidden"> <toolbarbutton id="TutTB-MainMenu" type="menu" tooltiptext="Tutorial Toolbar Main Menu"> <menupopup> <menuitem label="Google Home Page" accesskey="G" tooltiptext="Navigate to Google" oncommand="TutTB_LoadURL('http://www.google.com/')" /> <menuseparator /> <menuitem label="Born Geek Website" accesskey="B" tooltiptext="Navigate to Born Geek" oncommand="TutTB_LoadURL('http://www.borngeek.com/')" /> </menupopup> </toolbarbutton> <toolbarbutton id="TutTB-Combined-Button" label="Search" type="menu-button" tooltiptext="Combined Search" oncommand="TutTB_Search(event, 'web')"> <menupopup> <menuitem id="TutTB-Combined-Web" label="Web Search" class="menuitem-iconic" tooltiptext="Search the Web" oncommand="TutTB_Search(event, 'web'); event.preventBubble();" /> <menuitem id="TutTB-Combined-Image" label="Image Search" class="menuitem-iconic" tooltiptext="Search Images" oncommand="TutTB_Search(event, 'image'); event.preventBubble();" /> </menupopup> </toolbarbutton> <toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web" label="Web Search" oncommand="TutTB_Search(event, 'web')" /> </toolbar> </toolbox> </overlay>
ä¸æå¼ç·¨è¼¯å (Drop-Down Edit Box)
ä¸ä¸åæåè¦å¨å·¥å ·åå å ¥çæ¯ä¸æå¼ç·¨è¼¯åãéæ¯ç¨ menulist ä¾å»ºç«çï¼è®æåä¾ççç¨å¼ç¢¼ï¼
<toolbaritem id="TutTB-SearchTerms-TBItem" persist="width"> <menulist id="TutTB-SearchTerms" editable="true" flex="1" minwidth="100" width="250" onkeypress="TutTB_KeyHandler(event);"> <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" /> </menulist> </toolbaritem>
注æå°ï¼æåæ menulist æ¾å¨ toolbaritem ä¹ä¸ãä»»ä½ä¸åå¨ toolbar çé ç®é½ä¸æ¯å·¥å ·åæéï¼å¨ toolbaritem 裡é çææ¯ãä¹è«æ³¨æå°ï¼æåçº toolbaritem æå®äº id ï¼ä¸è¨å®äºå¯¬åº¦(èç±å©ç¨äº persist 屬æ§)ã
menulist ææ¯çæ£ç¨ä¾å»ºç«ä¸æå¼ç·¨è¼¯åçãæå¹¾åå¨éåå ç´ åºç¾çæ°å±¬æ§ï¼
- editable - ç¶è¨å®çº true æï¼ä½¿ç¨è å¯ä»¥å¨ç·¨è¼¯åä¸æåã
- flex - 使éåå ç´ æ¯å¯è®åçãéæ¯åæ´æ¸å¼ï¼ç¸å°æ¼å ¶ä»å¯è®åå·¥å ·åå ç´ ï¼æå®å ¶å¤§å°ãè¨å®å¼ 2 代表èè¨å®å¼ 1 çå ©å寬ï¼0 åæ¯ä¸è½è®åçåºå®å¯¬åº¦ã
- minwidth - æå°å¯¬åº¦ï¼å®ä½çºåç´ ã
- width - åå§å¯¬åº¦ï¼å®ä½çºåç´ ã
- onkeypress - ç¶ä½¿ç¨è è¼¸å ¥æåæï¼ç¨ä¾å·è¡çç¨å¼ç¢¼ã
ä½ å¯ä»¥å¨ XUL Planet menulist element's attributes çå°å®æ´çåèæç»ã
è·æåä¹åçå°çãé¸å®æéãä¸æ¨£ï¼å¨ menulist 裡ç menupopup å å«äº menuitem å ç´ ãonpopupshowing éåäºä»¶æå¨ç·¨è¼¯åçé¸å®é ç®é¡¯ç¤ºå觸ç¼ï¼å ¶ä¸æå®ä¸åè½åæ å¯«å ¥é¸å®é ç®çå½å¼ï¼éåå½å¼æåç¨å¾ææåãä½ ä¹å¯ä»¥å å ¥éæ çé¸å®ï¼éç¨è·ãé¸å®æéãæ¯ä¸æ¨£çã
ç¾å¨ï¼éåå¥ä»¶å·²ç¶è®å¾æ´å ·é«ä¸é»äºï¼è®æåä¾ççç¨å¼ç¢¼[View XUL Overlay Revision 3]ï¼
<?xml version="1.0"?> <overlay id="TutTB-Overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <toolbox id="navigator-toolbox"> <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T" class="chromeclass-toolbar" context="toolbar-context-menu" hidden="false" persist="hidden"> <toolbarbutton id="TutTB-MainMenu" type="menu" tooltiptext="Tutorial Toolbar Main Menu"> <menupopup> <menuitem label="Google Home Page" accesskey="G" tooltiptext="Navigate to Google" oncommand="TutTB_LoadURL('http://www.google.com/')" /> <menuseparator /> <menuitem label="Born Geek Website" accesskey="B" tooltiptext="Navigate to Born Geek" oncommand="TutTB_LoadURL('http://www.borngeek.com/')" /> </menupopup> </toolbarbutton> <toolbaritem id="TutTB-SearchTerms-TBItem" persist="width"> <menulist id="TutTB-SearchTerms" editable="true" flex="1" minwidth="100" width="250" onkeypress="TutTB_KeyHandler(event);"> <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" /> </menulist> </toolbaritem> <toolbarbutton id="TutTB-Combined-Button" label="Search" type="menu-button" tooltiptext="Combined Search" oncommand="TutTB_Search(event, 'web')"> <menupopup> <menuitem id="TutTB-Combined-Web" label="Web Search" class="menuitem-iconic" tooltiptext="Search the Web" oncommand="TutTB_Search(event, 'web'); event.preventBubble();" /> <menuitem id="TutTB-Combined-Image" label="Image Search" class="menuitem-iconic" tooltiptext="Search Images" oncommand="TutTB_Search(event, 'image'); event.preventBubble();" /> </menupopup> </toolbarbutton> <toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web" label="Web Search" oncommand="TutTB_Search(event, 'web')" /> </toolbar> </toolbox> </overlay>
å¯èª¿æ´ç移é§æ¨è¨ (Resizing Gripper)
éè¨å¾ä¹åå å«å¨ menulist ä¸ toolbaritem å ç´ ææå°ç persist 屬æ§åï¼è¨å®éå屬æ§ä»¥è®æåå¨ç覽å¨ä½¿ç¨æéï¼å¯ä»¥å²åæå°åç寬度ãçºäºè®ä½¿ç¨è å¯ä»¥æ¹è®å¯¬åº¦ï¼æåè¦æä¾ ç§»é§æ¨è¨ ãç¨ä¾åé件äºçå ç´ æ¯ splitter ï¼è®æåä¾ççç¨å¼ç¢¼ï¼
<splitter id="TutTB-ResizeSplitter" state="open" collapse="none" resizebefore="closest" resizeafter="farthest" tooltiptext="Resize the Search Box"> <vbox id="TutTB-ResizeBar" /> </splitter>
éæ¯ splitter ç屬æ§ï¼
- state - æå®åå²æ¨è¨æ¯å¦æºç(é±è)å §å®¹ï¼ open å¼æå®ä¸ç®¡æ¯å¦æå §å®¹ç顯示ã
- collapse - 決å®åªéç splitter 被é±èãæåä½¿ç¨ none ï¼ä¸è®ä»»ä½ä¸éç splitter 被é±èã
- resizebefore - ç¶ splitter æ¹è®æï¼æå® splitter å·¦éçåªåå ç´ å¿ é 被éæ°èª¿æ´ãç¶ splitter 移åæï¼ä½¿ç¨ closest ä¾éæ°èª¿æ´æé è¿ splitter å·¦éç編輯åã
- resizeafter - ç¶ splitter æ¹è®æï¼æå® splitter å³éçåªåå ç´ å¿ é 被éæ°èª¿æ´ãå¨éåç¯ä¾è£¡ï¼æåä½¿ç¨ farthest ä¾éæ°èª¿æ´æå³éçå½æ§ç©ºéã
vbox æ¯ç¨ä¾è¨å®æ¨£å¼çï¼æåæå¨ç¬¬äºç« è¨è«é¢æ¿æï¼æå°éé»ã ä½ å¯ä»¥å¨ XUL Planet splitter element's attributes çå°æ´å®æ´çåèæç»ã
è®æåä¾ççå å« splitter è toolbaritem çè¦è¼ç¨å¼ç¢¼[View XUL Overlay Revision 4]ï¼
<?xml version="1.0"?> <overlay id="TutTB-Overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <toolbox id="navigator-toolbox"> <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T" class="chromeclass-toolbar" context="toolbar-context-menu" hidden="false" persist="hidden"> <toolbarbutton id="TutTB-MainMenu" type="menu" tooltiptext="Tutorial Toolbar Main Menu"> <menupopup> <menuitem label="Google Home Page" accesskey="G" tooltiptext="Navigate to Google" oncommand="TutTB_LoadURL('http://www.google.com/')" /> <menuseparator /> <menuitem label="Born Geek Website" accesskey="B" tooltiptext="Navigate to Born Geek" oncommand="TutTB_LoadURL('http://www.borngeek.com/')" /> </menupopup> </toolbarbutton> <toolbaritem id="TutTB-SearchTerms-TBItem" persist="width"> <menulist id="TutTB-SearchTerms" editable="true" flex="1" minwidth="100" width="250" onkeypress="TutTB_KeyHandler(event);"> <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" /> </menulist> </toolbaritem> <splitter id="TutTB-ResizeSplitter" state="open" collapse="none" resizebefore="closest" resizeafter="farthest" tooltiptext="Resize the Search Box"> <vbox id="TutTB-ResizeBar" /> </splitter> <toolbaritem flex="0"> <toolbarbutton id="TutTB-Combined-Button" label="Search" type="menu-button" tooltiptext="Combined Search" oncommand="TutTB_Search(event, 'web')"> <menupopup> <menuitem id="TutTB-Combined-Web" label="Web Search" class="menuitem-iconic" tooltiptext="Search the Web" oncommand="TutTB_Search(event, 'web'); event.preventBubble();" /> <menuitem id="TutTB-Combined-Image" label="Image Search" class="menuitem-iconic" tooltiptext="Search Images" oncommand="TutTB_Search(event, 'image'); event.preventBubble();" /> </menupopup> </toolbarbutton> <toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web" label="Web Search" oncommand="TutTB_Search(event, 'web')" /> </toolbaritem> </toolbar> </toolbox> </overlay>
çºäºé¿å 移é§æ¨è¨è¨åç細微顯示åé¡ï¼æåééè¦å»ºç«é¡å¤ç toolbaritem ï¼éèæåååå¨ãé¸å®æéãä¸çæå°æéæåçä¸æ¨£ã åä¸æ¬¡ç¢ºå® flex 屬æ§çå¼çº 0ï¼éå°æé¿å ï¼ç¶æåçé¸å®æé被ææ³å°å·¦éæ被移é¤ã
æ¥èï¼è®æååä¾å¢å å ©åé ç®ãé¦å ï¼å° toolbarseparator æ¾ç½®å¨æå¾å ©åæéä¸ï¼æ¤ç®çæ¯çºäºè£é£¾ãåä¾ï¼å° toolbarspring æ¾ç½®å¨æå¾ç toolbaritem å ç´ ä¹å¾ãThis spring will allow us to drag the resizer all the way to the right, so that we can see the full resizing effect in action. éå ©åæ¨ç¤ºæ¯å¾ç°¡å®çï¼åæ¯é樣ï¼
<toolbarseparator /> <toolbarspring />
è®æåä¾ççå®æ´çè¦è¼ç¯ä¾[View XUL Overlay Revision 5]ï¼
<?xml version="1.0"?> <overlay id="TutTB-Overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <toolbox id="navigator-toolbox"> <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T" class="chromeclass-toolbar" context="toolbar-context-menu" hidden="false" persist="hidden"> <toolbaritem flex="0"> <toolbarbutton id="TutTB-MainMenu" type="menu" tooltiptext="Tutorial Toolbar Main Menu"> <menupopup> <menuitem label="Google Home Page" accesskey="G" tooltiptext="Navigate to Google" oncommand="TutTB_LoadURL('http://www.google.com/')" /> <menuseparator /> <menuitem label="Born Geek Website" accesskey="B" tooltiptext="Navigate to Born Geek" oncommand="TutTB_LoadURL('http://www.borngeek.com/')" /> </menupopup> </toolbarbutton> </toolbaritem> <toolbaritem id="TutTB-SearchTerms-TBItem" persist="width"> <menulist id="TutTB-SearchTerms" editable="true" flex="1" minwidth="100" width="250" onkeypress="TutTB_KeyHandler(event);"> <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" /> </menulist> </toolbaritem> <splitter id="TutTB-ResizeSplitter" state="open" collapse="none" resizebefore="closest" resizeafter="farthest" tooltiptext="Resize the Search Box"> <vbox id="TutTB-ResizeBar" /> </splitter> <toolbaritem flex="0"> <toolbarbutton id="TutTB-Combined-Button" label="Search" type="menu-button" tooltiptext="Combined Search" oncommand="TutTB_Search(event, 'web')"> <menupopup> <menuitem id="TutTB-Combined-Web" label="Web Search" class="menuitem-iconic" tooltiptext="Search the Web" oncommand="TutTB_Search(event, 'web'); event.preventBubble();" /> <menuitem id="TutTB-Combined-Image" label="Image Search" class="menuitem-iconic" tooltiptext="Search Images" oncommand="TutTB_Search(event, 'image'); event.preventBubble();" /> </menupopup> </toolbarbutton> <toolbarseparator /> <toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web" label="Web Search" oncommand="TutTB_Search(event, 'web')" /> </toolbaritem> <toolbarspring /> </toolbar> </toolbox> </overlay>
第åç« ï¼åæ éç¼ (Dynamic Development)
(è¯è ï¼å¦æä¸æ³ç¨æ¤éç¼ç°å¢ï¼å¯ä»¥ç¥éæ¤ç« ï¼ä¸¦ç¨ç¬¬ä¸ç« çæ¹å¼æ¸¬è©¦å¥ä»¶ã)
å¨ Firefox 1.5 ä¸ï¼åæ å¥ä»¶éç¼æ¯æ°çæè¡ï¼å°éç¼è èè¨ï¼éæ¯ææç¨çéå åè½ãéé æè¡å¯ä»¥è®ä½ å¨éç¼å¥ä»¶æï¼å³æå°çå°çµæãç¶ä½ è¦æ¸¬è©¦ XUL è¦è¼ææ¯ JavaScript ç¨å¼ç¢¼æï¼ä¸ç¨æ¯æ¬¡åéæ°å°è£å¥ä»¶ãéä¸åªç¯çäºä½ çæéï¼ä¹è®ä½ è½æ´å¿«éå°é¤é¯ã
é£éº¼ï¼éé ç¹è²æ¯å¦ä½éä½çå¢ï¼éå°±è¦æè¬æåå¨ç¬¬äºç« 建ç«ç chrome æ¸ å®äºãç´å°ç¾å¨çºæ¢ï¼æé½éæ²è·ä½ 說 chrome æ¸ å®è©¦ä½ç麼ç¨éãå¨éåæåä¸ï¼æåä¸éå§å»ºç«ççæ¬å°±æ¯ç¹å¥çºåæ éç¼èè¨è¨çãæè¨ä¹ï¼æåä¸å¿ éæ°å°è£é£ä»½çæ¬çå¥ä»¶ï¼ä½éæ¯æäºæ¹è®éè¦å®æï¼æå¯ä»¥å°è£ãæå¹¾åç¨ä¾ãååãå¥ä»¶åæ éç¼çæ¥é©ï¼å¨é£ä¹åï¼æè¦å çµ¦ä½ å¹¾å建è°ã
注æäºé (A Word of Warning)
å¥ä»¶éç¼ææææé»å±éªï¼å°¤å ¶æ¯è¨è¨ XUL è¦è¼æªæ¡æãæå¼·ç建è°ä½ è¦é¿å éç¼å¥ä»¶è·å¹³å¸¸ç覽網é å ±ç¨ä¸åè¨å®æª(profile)ãæè¨ä¹ï¼ä½ å¿ é çºä½ çéç¼ç°å¢å»ºç«ä¸åæ°çè¨å®æªãéå¯ä»¥é¿å ä½ å¤±å»ä¸äºééµçè³æï¼å¦ï¼å²åçå¯ç¢¼ãcookiesãæ¸ç±¤ææ¯å ¶ä»ä½ ä¸æ³éºå¤±çæ±è¥¿ã
æå¸æè½åå¿« Born Geek å¨ç¼è¡¨éæ¼å¦ä½å»ºç«è使ç¨è¨å®æªçæå¸ãå¨é£ä¹åï¼ä½ å¯ä»¥å ççå¨ Mozilla.org çè¨å®æªæ件ã建ç«è使ç¨è¨å®æªæ¯å¾ç°¡å®çï¼éæé¿å è®ä½ é ççæ æ³ç¼çã
å¦ä½åæ éç¼ (How to Develop Dynamically)
æ主è¦çå·¥ä½ï¼æåå·²ç¶å¨ chrome æ¸ å®å®æ(å³ä½¿ä½ éä¸äºè§£æåé£æåäºä»éº¼)ãç¾å¨ï¼æåéè¦çï¼æ¯ä¸åå° Firefox æå硬ç¢ä¸å¥ä»¶ä½ç½®çæªæ¡ï¼æåå°èç± pointer æªæ¡ä¾å®æã
é¦å ï¼å¨ä½ çé»è ¦çé¨ä¾¿ä¸åå°æ¹ï¼ä»¥æåå¨å®è£æ¸ å®(install manifest)ä¸æ使ç¨ç GUID å稱ï¼å»ºç«ä¸åæåæªãå¨é份æåä¸ï¼æåä½¿ç¨ tuttoolbar@borngeek.com ä½çºæªåãä¸å¹¸çæ¯ï¼å¨å¾®è»è¦çªç°å¢è£¡ï¼ã.comãçæªæ¡æ¯è¢«ç¨ä¾ç¶ä½å·è¡æªï¼èæåéè¦çæ¯æåæªãä½ å¯ä»¥æã.comãæ¿æï¼ä½ä¹è¨å¾å»ä¿®æ¹å¨å®è£æ¸ å®ç GUIDï¼ç¢ºä¿å ©åå稱æ¯ä¸æ¨£çã
å¨éåæªæ¡è£¡ï¼æåå°è¦è¼¸å ¥ä¸è¡æåï¼å¥ä»¶å²åççµå°ä½ç½®ï¼ä¹å°±æ¯åæ¾ install.rdf è chrome.manifest æªæ¡çç®éãå¨æçä¾åï¼å²åè·¯å¾å¦ä¸ï¼
C:\Born Geek\TutToolbar
ä½ å¿ é 使ç¨ä½ èªå·±è¨å®çè·¯å¾ï¼é¤éä½ çè·¯å¾è·æçä¸æ¨£ãè¼¸å ¥å®è·¯å¾å¾ï¼å²åæªæ¡ã
ç¾å¨ï¼æåå¿ é å°éåæªæ¡ç§»åå°è·éç¼ç°å¢çè¨å®æª(profile)åä¸åç®é(å¦ï¼C:\Documents and Settings\Administrator\Application Data\Mozilla\Firefox\Profiles)ãæååæå°çè¨å®æªæ件æè¨è«å°è¨å®æªç®éçä½ç½®ãç¶ä½ æ¾å°è¨å®æªç®éæï¼å°æååå建ç«ç pointer æªæ¡ç§»åå°è©²ç®éç extensions ç®éä¸ãéæ¯æçä¾åï¼
+- tl5wlpz3.Nightly/ +- bookmarkbackups/ +- chrome/ +- extensions/ +- tuttoolbar@borngeek.com +- (... other files and folders ...)
ä½ å¯ä»¥çå°æçè¨å®æªæä¸å±¤ç®éï¼æ使ç¨ä»¥ãNightlyãçºåçè¨å®æªï¼ä¾ä½çºæçå¥ä»¶éç¼ç°å¢ãä¸æ¦ä½ æ pointer æªæ¡æ¾å¨é©ç¶çä½ç½®ï¼éå Firefoxï¼ç¢ºå®ä½ 使ç¨çæ¯å¥ä»¶éç¼çè¨å®æª(å次æéï¼ååæå°çè¨å®æªæ件æåè¨´ä½ å¦ä½é樣å)ã å°ç®åçºæ¢ï¼å¦æä½ æ¯æ¨£é½åçæ£ç¢ºï¼ä½ æçå°æ²æé¢æ¿çç°è²å·¥å ·åã
éç¼é±æ (The Development Cycle)
ç¾å¨ï¼æåå·²ç¶ååäºåæ éç¼ç°å¢ï¼é£è¦å¦ä½å»å©ç¨å¢ï¼éç¨å ¶å¯¦æ¯é常簡å®çï¼
- ç·¨è¼¯ä½ çå¥ä»¶æªæ¡
- éæ°éåå·²æ´æ¹æªæ¡æå¥ç¨çè¦çªï¼ææ¯ä½¿ç¨ Extension Developer's Extension çéæ°æ´ç(Reload Chrome)ã
æå ©ä»¶äºæ¯ä½ è¦ç¥éçï¼
- å¦æä½ æ¹è®äº chrome.manifest æªæ¡ï¼ä½ å¿ é éæ°éå Firefox (éåæªæ¡åªæå¨ç¨å¼ååææç¼çä½ç¨)ã
- å¦æä½ æ¹è®äº install.rdf æªæ¡ï¼ä½ å¿ é æ¹è® pointer æªæ¡ææåç®éçä¿®æ¹æéãå¨ Linux ä¸ï¼ä½ åªè¦ä½¿ç¨ touch æ令ãèå¨ Windows 裡就æé»é£åº¦ï¼é¤éä½ å®è£äºå¯ä»¥ä½¿ç¨ touch æ令ç Cygwin å·¥å ·ãå¯ä¸è¦åçï¼å°±æ¯å¨å¥ä»¶æä¸å±¤ç®é建ç«ä¸åæ°ç®éï¼ç¶å¾åªé¤æ°ç®é以æ¹è®ç®éçãä¸ä¸æ¬¡ä¿®æ¹ãæéã
ä½ å¯ä»¥çå°ï¼æåæäºæ¹ä¾¿çéç¼èé¤é¯å·¥å ·ãéåéæ¼ï¼å¨ 1.5 çä¹åçæ¨æºéç¨ï¼å°±æ¯æ¯æ¬¡å¨å¥ä»¶éç¼éç¨é½è¦å°è£æªæ¡ã
ç¾å¨ï¼è®æåæéåééçå·¥å ·åè®å¾æ´æ¼äº®ä¸é»å§ï¼
第äºç« ï¼é¢æ¿è£½ä½ (Skinning the Toolbar)
é¢æ¿æ¯ç±æ¨£å¼æ¨æºèåçææ§æçãè¨ä½ï¼å管è¨è¨é¢æ¿æ¯éå¿ è¦çï¼ä½æ¯å®è½æåå¥ä»¶çå質ãç¢ç«ä½¿ç¨è å°å¥ä»¶ç第ä¸å°è±¡æ¯å®çå¤è§ï¼èä¸æ¯å®çåè½ãç¶èï¼å¦æä½ è¦ºå¾ä½¿ç¨æåæ¨ç±¤è®ä½ æ¯è¼èªå¨ï¼ææ¯ä¸éè¦å»ºç«å¤è§ï¼ä½ å¯ä»¥ç¥ééåç« ç¯ã
æ´æ°æªæ¡çµæ§ (Updating the File Structure)
è¨è¨é¢æ¿ç第ä¸æ¥å°±æ¯å»ºç«ä¸åç®éï¼ç¨ä¾åæ¾éæ¼é¢æ¿çæªæ¡ãå¨ chrome ç®éä¸å»ºç«ä¸å skin ç®éãæªæ¡çµæ§æåé樣ï¼
+- TutToolbar/ +- install.rdf +- chrome.manifest +- chrome/ +- content/ +- tuttoolbar.xul +- skin/
ç¾å¨æåæåæ¾é¢æ¿æªæ¡çå°æ¹äºï¼ä¹å¾å¿ é è¦å¨ chrome 裡註åéåä½ç½®ã
æ´æ° Chrome æ¸ å® (Updating the Chrome Manifest)
éè¨å¾æåå¨ç¬¬äºç« 建ç«ç chrome æ¸ å®åï¼æåå¿ é å¨éåæªæ¡å å ¥ä¸è¡ç¨å¼ç¢¼ï¼ç¨ä¾è¨»åæåçé¢æ¿ãæ°å å ¥çä½ç½®(第ä¸è¡)ï¼
content tuttoolbar chrome/content/ overlay chrome://browser/content/browser.xul chrome://tuttoolbar/content/tuttoolbar.xul skin tuttoolbar classic/1.0 chrome/skin/
æ°å å ¥çéä¸è¡ç¸ç¶ç°¡å®ï¼èä¸åªæååé¨ä»½ã第ä¸é¨ä»½ï¼skin 說æéä¸è¡è¦è¨»åé¢æ¿çè³è¨ãæ¥èæ¯å¥ä»¶çå稱ï¼éè£¡ä½¿ç¨ tuttoolbar ç¶ä½æåçå¥ä»¶å稱ã第ä¸é¨ä»½ï¼èªªææåå°ææ´å±çå·²å®è£å¥ä»¶å稱ï¼ãclassic/1.0ãæ¯ä½ æä¸ç´ç¨å°çå¼ãæå¾ï¼ä¹æ¯æéè¦çé¨ä»½ï¼å°±æ¯å å«é¢æ¿æªæ¡çç®éè·¯å¾ã注æå°éåè·¯å¾å¾é¢çæç·(/)ï¼éåæç·æ¯å¿ è¦çï¼ç¢ºå®ä½ æè¼¸å ¥ã
建ç«åçæªæ¡ (Creating the Image Files)
æåæè®æ¯åå·¥å ·åæé使ç¨åèªçååã注æå°ï¼éä¸æ¯æææçææ¯ç²¾ç·»çä½æ³ï¼ä½æ¯å¯ä»¥è®äººæ´å®¹æäºè§£ãæ´å¥½çæ¹å¼æ¯ä½¿ç¨åå樣å¼è¡¨ï¼ä½æ¯é£è¶ åºé份æåçç¯åã
æåéè¦äºåååä¾å·¥å ·åççµåé¸å®ä½¿ç¨ï¼ä¸»è¦é¸å®ãç¶åæå°æéã網é æå°æéãåçæå°é¸å®ä»¥åå¯èª¿æ´ç移é§æ¨è¨ãå¨ä¸é¢çå表ä¸ï¼æäºåæç¨å¨éåå¥ä»¶çååã注æï¼ éäºååé½æ¯éæç PNG æ ¼å¼æªæ¡ï¼å¦æä½ ä½¿ç¨ IE ææ¯å ¶ä»ç覽å¨ï¼å¯è½ä¸è½æ£ç¢ºå°é¡¯ç¤ºã
主è¦é¸å®å示 Main Menu Icon (main.png): http://wiki.moztw.org/uimages/b/b7/Borngeek_main.png
ç¶åæå°å示 Combined Search Icon (combined.png): http://wiki.moztw.org/uimages/3/36/Borngeek_combined.png
網é æå°å示 Web Search Icon (web.png): http://wiki.moztw.org/uimages/9/9c/Borngeek_web.png
åçæå°å示 Images Search Icon (images.png): http://wiki.moztw.org/uimages/6/61/Borngeek_images.png
å¯èª¿æ´ç§»é§æ¨è¨å示 Resizing Gripper Icon (gripper.png): http://wiki.moztw.org/uimages/5/50/Borngeek_gripper.png
å°éäºååå²åå¨æååå建ç«ç skin ç®é裡ï¼æªæ¡çµæ§æåé樣ï¼
+- TutToolbar/ +- install.rdf +- chrome.manifest +- chrome/ +- content/ +- tuttoolbar.xul +- skin/ +- combined.png +- gripper.png +- images.png +- main.png +- web.png
èç±ä¸²æ¥æ¨£å¼è¡¨å¥ç¨åç (Applying the Images with CSS)
ç¾å¨ï¼æéäºååå¯ä»¥ä½¿ç¨ï¼é¢æ¿ç®éä¹å·²ç¶è¨»åï¼æåå¯ä»¥éå§æååå¥ç¨å¨å·¥å ·åæéä¸äºãæåå°æèç± CSS ä¾å®æãå°±å¦æå¨æåä¸éå§æå°çï¼å¦æä½ å° CSS ä¸çæï¼å¯ä»¥åè W3Schools ç excellent CSS tutorial ã
è®æåéå§å»ºç« CSS æªæ¡å§ï¼å¨ skin ç®éä¸ï¼å»ºç«ä¸åæªåçº tuttoolbar.css çæªæ¡ï¼æéåæªæ¡è·ååæ¾å¨ä¸èµ·ãæªæ¡çµæ§å¦ä¸ï¼
+- TutToolbar/ +- install.rdf +- chrome.manifest +- chrome/ +- content/ +- tuttoolbar.xul +- skin/ +- combined.png +- gripper.png +- images.png +- main.png +- web.png +- tuttoolbar.css
å¨èªªæç´°ç¯åï¼å è®æåä¾çç樣å¼è¡¨çå §å®¹ï¼
#TutTB-MainMenu { list-style-image: url("chrome://tuttoolbar/skin/main.png"); } #TutTB-Combined-Button { list-style-image: url("chrome://tuttoolbar/skin/combined.png"); } #TutTB-Combined-Button > .toolbarbutton-menubutton-button { -moz-box-orient: horizontal; } #TutTB-Web-Button, #TutTB-Combined-Web { list-style-image: url("chrome://tuttoolbar/skin/web.png"); } #TutTB-Combined-Image { list-style-image: url("chrome://tuttoolbar/skin/images.png"); } #TutTB-ResizeBar { background-image: url("chrome://tuttoolbar/skin/gripper.png"); min-height: 22px; min-width: 3px; } #TutTB-ResizeSplitter { background: transparent; border: none !important; }
第ä¸é è¦åæ¯æå®è©²åå給ã主è¦é¸å®ãæé使ç¨ãå顧ä¸ä¸ç¬¬ä¸ç« ï¼æå給äºè©²æéä¸å ID å¼ï¼TutTB-MainMenuï¼æåç¨è©²å¼ä¾è¨å®æé顯示çååãå¨åé¢çäºè(#)æ¯ ID é¸åå¨(ID selector)ï¼ä¹å°±æ¯ç¨ä¾æå® CSS å ç´ è¦åçç¹å®èå¥å¼ãå¨å·¥å ·åæé裡ï¼æåä½¿ç¨ CSS 屬æ§ç list-style-image ä¾æå®ååã注æå°æå使ç¨çæ¯ chrome è·¯å¾ï¼ä¹å°±æ¯å¥ä»¶æªæ¡çµæ§ä¸çååè·¯å¾ï¼å¸¸ç¨çæ ¼å¼å¦ä¸ï¼
chrome://<packagename>/skin/<image_file_name>
å¨æåçç¯ä¾è£¡ï¼å°è£å稱(package name)æ¯ tuttoolbarï¼è主è¦é¸å®ä½¿ç¨çåååç¨±çº main.pngãä½ å¯ä»¥çå°ï¼ææçå·¥å ·åæé使ç¨é¡ä¼¼çè¦åï¼å¨ç¶åæå°æéçé¸å®é ç®ä¹æ¯ä¸æ¨£ãThere's one caveat to handling menu item icons, however. åæ³ä¸ä¸ï¼å¨ç¶åæå°é¸å®ä¸ï¼æåçºé¸å®é ç®ä½¿ç¨äºä¸åç¹å¥çé¡å¥å¼ï¼menuitem-iconicï¼éæ¯ Firefox å §å»ºçãéåå¼ãååãå示æ¯æ´ä½¿ç¨å®çæ¯åé¸å®é ç®ã
æ³å¿ ä½ ä¹æ³¨æå°äºéåç¶åæå°æéçç¹å®è¦åï¼
#TutTB-Combined-Button > .toolbarbutton-menubutton-button { -moz-box-orient: horizontal; }
éåç¹å¥ç CSS 屬æ§å¨éè£¡ä½¿ç¨ -moz-box-orientï¼éæå®æéçæ¨ç±¤è©²å¦ä½é¡¯ç¤ºï¼æ°´å¹³ææ¯åç´é¡¯ç¤ºãå·¥å ·åæéæ¨ç±¤çé è¨å¼æ¯åç´é¡¯ç¤ºï¼ä¹å°±æ¯é¡¯ç¤ºå¨å示ä¸æ¹ãå¨éåç¯ä¾ï¼ä¸ä½¿ç¨é樣çæ¹å¼ï¼æ以æåæ¹çºæ°´å¹³é¡¯ç¤ºï¼ä»¥ä½¿æ¨ç±¤é¡¯ç¤ºå¨å示ä¹å¾ã
å¨èçå¯èª¿æ´ç移é§æ¨è¨(resizing gripper)æï¼æå ©æ¢æ¨£å¼è¡¨çè¦åãéè¨å¾å¨ç¬¬åç« è£¡ï¼æåå¨åé¢çå ç´ (splitter element)使ç¨ç vbox å ç´ åï¼æåçºç§»é§æ¨è¨ä½¿ç¨äº vbox ä¾é¡¯ç¤ºèæ¯ååãé次ï¼æåä½¿ç¨ background-image 屬æ§ãæåå¿ é èç± min-height è min-width 屬æ§ï¼æä¾æå°é«åº¦èæå°å¯¬åº¦ï¼ä»¥è®ç§»é§æ¨è¨é¡¯ç¤ºåºä¾ãvbox è hbox 屬æ§çé è¨å¼å¯è½æ¯ä¾å §å®¹å¤§å°å¤å®ãç±æ¼ vbox æ¯ç©ºçï¼é è¨å¼å°±æ¯ 0ï¼éä¹é¿å æåæçå°èæ¯ååã
æåä¹çºåé¢çå ç´ æä¾ä¸æ¢è¦åã æåè®èæ¯æ¯éæçï¼èä¸ä¸ä½¿ç¨éæ¡(åé¢å ç´ çé è¨å¼æ¯æ使ç¨éæ¡ç)ãç¾å¨ï¼CSS æªæ¡å·²ç¶å®æï¼æåè¦è¨å®è¦è¼(overlay)以使ç¨å®ã
使ç¨æ¨£å¼è¡¨ (Using the Style Sheet)
åªæä¸è¡ç¨å¼ç¢¼æ¯éè¦è¢«å å ¥å¨ XUL è¦è¼çï¼éç¨ä¾ååæååå建ç«ç樣å¼è¡¨ãéå¿ é æ¾ç½®å¨ XML 宣åæ令çä¸æ¹ï¼ä»¥åè¦è¼(overlay)å ç´ ä¹åãä¸é¢ï¼æååºè¦è¼æªæ¡çåå¹¾è¡éè¦æ´åçå°æ¹ï¼
<?xml version="1.0"?> <?xml-stylesheet href="chrome://tuttoolbar/skin/tuttoolbar.css" type="text/css"?> <overlay id="TutTB-Overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> (... rest of XUL overlay file ...)
å°±åæåå¨æ¨£å¼è¡¨ä¸çå°çååä¸æ¨£ï¼chrome è·¯å¾è¢«ç¨ä¾æå®ä½ç½®ãè type 屬æ§åªæ¯ææéæ¯ CSS çæªæ¡ãç¾å¨è®æåççè¦è¼æªæ¡å¨å å ¥éä¸è¡å¾çå®æ´å §å®¹[View XUL Overlay Revision 6]ï¼
<?xml version="1.0"?> <?xml-stylesheet href="chrome://tuttoolbar/skin/tuttoolbar.css" type="text/css"?> <overlay id="TutTB-Overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <toolbox id="navigator-toolbox"> <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T" class="chromeclass-toolbar" context="toolbar-context-menu" hidden="false" persist="hidden"> <toolbaritem flex="0"> <toolbarbutton id="TutTB-MainMenu" type="menu" tooltiptext="Tutorial Toolbar Main Menu"> <menupopup> <menuitem label="Google Home Page" accesskey="G" tooltiptext="Navigate to Google" oncommand="TutTB_LoadURL('http://www.google.com/')" /> <menuseparator /> <menuitem label="Born Geek Website" accesskey="B" tooltiptext="Navigate to Born Geek" oncommand="TutTB_LoadURL('http://www.borngeek.com/')" /> </menupopup> </toolbarbutton> </toolbaritem> <toolbaritem id="TutTB-SearchTerms-TBItem" persist="width"> <menulist id="TutTB-SearchTerms" editable="true" flex="1" minwidth="100" width="250" onkeypress="TutTB_KeyHandler(event);"> <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" /> </menulist> </toolbaritem> <splitter id="TutTB-ResizeSplitter" state="open" collapse="none" resizebefore="closest" resizeafter="farthest" tooltiptext="Resize the Search Box"> <vbox id="TutTB-ResizeBar" /> </splitter> <toolbaritem flex="0"> <toolbarbutton id="TutTB-Combined-Button" label="Search" type="menu-button" tooltiptext="Combined Search" oncommand="TutTB_Search(event, 'web')"> <menupopup> <menuitem id="TutTB-Combined-Web" label="Web Search" class="menuitem-iconic" tooltiptext="Search the Web" oncommand="TutTB_Search(event, 'web'); event.preventBubble();" /> <menuitem id="TutTB-Combined-Image" label="Image Search" class="menuitem-iconic" tooltiptext="Search Images" oncommand="TutTB_Search(event, 'image'); event.preventBubble();" /> </menupopup> </toolbarbutton> <toolbarseparator /> <toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web" label="Web Search" oncommand="TutTB_Search(event, 'web')" /> </toolbaritem> <toolbarspring /> </toolbar> </toolbox> </overlay>
å¥å¿è¨è¦æ¸¬è©¦ï¼ç¨åæ éç¼ç Firefox å¯æ¬éåï¼ç¶å¾ççå¥ä»¶ç樣åãæ¥ä¸ä¾ï¼æåè¦çºå·¥å ·åæ³¨å ¥çå½ã
第å ç« ï¼ä¸»ç¨å¼ (Scripting the Toolbar)
å¥ä»¶é常æ¯ç¨ JavaScript å·è¡çï¼éæ¯ä¸ç¨®ç°¡å®æå¸çç¨å¼èªè¨ãä½ å°æç¼ç¾ï¼æåçå·¥å ·åå¥ä»¶çç¨å¼ç¢¼æ¯é常簡å®çãæåå°æ大é使ç¨æ件ç©ä»¶æ¨¡å(DOM)ï¼éå¯ä»¥è®æåèçå®ç¨çå ç´ ã
å¨æåéå§åï¼ä½ è¦å ç¥éä¸åéé»ãid 屬æ§å¿ é æ¯æ´åç覽å¨å¯ä¸çï¼è JavaScript çè®æ¸åå½å¼ä¹æ¯ãå¨ç覽å¨è¦è¼ä¸çJavaScript æ¯å ¨åæ§çï¼å æ¤æææéåéå¶ãæåå°æ使ç¨è· XUL å ç´ ä¸æ¨£çæå·§ï¼ææçè®æ¸åå½å¼çå稱ï¼å°ææ以æåå¥ä»¶çºåèµ·å§å稱ãæåä½¿ç¨ TutTB_ ç¶ä½èµ·å§å稱ï¼æ以æåçæå°å½å¼ææ¯ TutTB_Search()ã
ç¾å¨ï¼è®æåå»ºç« JavaScript æªæ¡ãå¨ content ç®éä¸ï¼å»ºç«ä¸å tuttoolbar.js çæåæªãç®éçµæ§å¦ä¸ï¼
+- TutToolbar/ +- install.rdf +- chrome.manifest +- chrome/ +- content/ +- tuttoolbar.xul +- tuttoolbar.js +- skin/ +- combined.png +- gripper.png +- images.png +- main.png +- web.png +- tuttoolbar.css
å¨å»ºç«ä»»ä½ç¨å¼ç¢¼åï¼å å訴 XUL æªæ¡è©²å¦ä½ä½¿ç¨ JavaScript æªæ¡ã
é£çµ XUL è JavaScript (Tying XUL to JavaScript)
æåç XUL æªæ¡ tuttoolbar.xul éè¦è¢«åç¥ç¸å°æç JavaScript æªï¼æåå¯ä»¥ä½¿ç¨ä¸é¢çæè¿°ï¼
<script type="application/x-javascript" src="chrome://tuttoolbar/content/tuttoolbar.js" />
éå¿ é æ¾ç½®å¨ overlay å ç´ ä¹ä¸ãtype 屬æ§æ¯æå®ä½¿ç¨ JavaScriptï¼src 屬æ§æ¯æå®åå建ç«ç JavaScript æªãå §å®¹å¦ä¸[View XUL Overlay Revision 7]ï¼
<?xml version="1.0"?> <?xml-stylesheet href="chrome://tuttoolbar/skin/tuttoolbar.css" type="text/css"?> <overlay id="TutTB-Overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script type="application/x-javascript" src="chrome://tuttoolbar/content/tuttoolbar.js" /> <toolbox id="navigator-toolbox"> <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T" class="chromeclass-toolbar" context="toolbar-context-menu" hidden="false" persist="hidden"> <toolbaritem flex="0"> <toolbarbutton id="TutTB-MainMenu" type="menu" tooltiptext="Tutorial Toolbar Main Menu"> <menupopup> <menuitem label="Google Home Page" accesskey="G" tooltiptext="Navigate to Google" oncommand="TutTB_LoadURL('http://www.google.com/')" /> <menuseparator /> <menuitem label="Born Geek Website" accesskey="B" tooltiptext="Navigate to Born Geek" oncommand="TutTB_LoadURL('http://www.borngeek.com/')" /> </menupopup> </toolbarbutton> </toolbaritem> <toolbaritem id="TutTB-SearchTerms-TBItem" persist="width"> <menulist id="TutTB-SearchTerms" editable="true" flex="1" minwidth="100" width="250" onkeypress="TutTB_KeyHandler(event);"> <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" /> </menulist> </toolbaritem> <splitter id="TutTB-ResizeSplitter" state="open" collapse="none" resizebefore="closest" resizeafter="farthest" tooltiptext="Resize the Search Box"> <vbox id="TutTB-ResizeBar" /> </splitter> <toolbaritem flex="0"> <toolbarbutton id="TutTB-Combined-Button" label="Search" type="menu-button" tooltiptext="Combined Search" oncommand="TutTB_Search(event, 'web')"> <menupopup> <menuitem id="TutTB-Combined-Web" label="Web Search" class="menuitem-iconic" tooltiptext="Search the Web" oncommand="TutTB_Search(event, 'web'); event.preventBubble();" /> <menuitem id="TutTB-Combined-Image" label="Image Search" class="menuitem-iconic" tooltiptext="Search Images" oncommand="TutTB_Search(event, 'image'); event.preventBubble();" /> </menupopup> </toolbarbutton> <toolbarseparator /> <toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web" label="Web Search" oncommand="TutTB_Search(event, 'web')" /> </toolbaritem> <toolbarspring /> </toolbar> </toolbox> </overlay>
çºæéå ä¸åè½ (Adding Functionality to the Buttons)
éè¨å¾æåçºå·¥å ·åæéæä¾ç oncommand 屬æ§åï¼éå屬æ§æ¯æå®ç¨å¼ç¢¼å·è¡çäºä»¶ãæåä¹å¯ä»¥ä½¿ç¨ onclick ä»£æ¿ oncommandï¼ä½æ¯ onclick å°éµç¤ç¡æï¼è oncommand å¯ä»¥åæåæéµç¤èæ»é¼ çåä½ãè®æåå顧ä¸ä¸æå°æéï¼
oncommand="TutTB_Search(event, 'web')"
éåå¼å¼å« TutTB_Search() å½å¼ï¼å ¶ä¸å å«å ©åå¼ï¼éåå½å¼å¼å«çäºä»¶(event)ï¼ä»¥åæå°ç網é (web)ã
ç¨å¼ç¢¼å¦ä¸[View JavaScript Revision 1]ï¼
//////////////////////////////////////////////////////////////////////////////// // TutTB_Search() å½å¼æçºæåå®ææå°ãevent åæ¸æ觸ç¼å½å¼çå¼å«ï¼type åæ¸ // çºæå°çé¡åã //////////////////////////////////////////////////////////////////////////////// function TutTB_Search(event, type) { // å°è¦ç覽ç網å var URL = ""; // 辨å¥æå°æ¬ä½æ¯å¦çºç©ºå¼ var isEmpty = false; // èçæå°æ¬ä½ ( <menulist> å ç´ ) var searchTermsBox = document.getElementById("TutTB-SearchTerms"); // å¾æå°æ¬ä½ååºå串ï¼æ´çå¿ è¦çç©ºç½ // å¯ä»¥å¨ä¸é¢çç TutTB_TrimString() å½å¼éä½çç´°ç¯ var searchTerms = TutTB_TrimString(searchTermsBox.value); if(searchTerms.length == 0) // Is the search terms box empty? isEmpty = true; // If so, set the isEmpty flag to true else // If not, convert the terms to a URL-safe string searchTerms = TutTB_ConvertTermsToURI(searchTerms); // é¸ææå°çé¡å // å¦ææ¬ä½æ¯ç©ºç½çï¼æåæå¼å°ä½¿ç¨è å° Google 網é ä¸é©ç¶çå°æ¹ã // å¦åï¼æå°è¼¸å ¥çæåã switch(type) { // 建ç«åçæå°ç網å case "image": if(isEmpty) { URL = "http://images.google.com/"; } else { URL = "http://images.google.com/images?q=" + searchTerms; } break; // 建ç«ç¶²é æå°ç網å case "web": default: if(isEmpty) { URL = "http://www.google.com/"; } else { URL = "http://www.google.com/search?q=" + searchTerms; } break; } // ä½¿ç¨ TutTB_LoadURL å½å¼å¨ç覽è¦çªä¸è¼å ¥ç¶²å TutTB_LoadURL(URL); } //////////////////////////////////////////////////////////////////////////////// // TutTB_TrimString() å½å¼æä¿®åªå串çåå¾ç©ºç½é¨ä»½ï¼ç¶å¾å°ææç空ç½é¨ä»½è½ææ // å®ä¸å空ç½ï¼ç¶å¾å³åä¿®æ¹å¾å串ã //////////////////////////////////////////////////////////////////////////////// function TutTB_TrimString(string) { // å¦æå³å ¥çå串ç¡æï¼ææ¯æ²ææ±è¥¿ï¼åå³åç©ºå¼ if (!string) return ""; string = string.replace(/^\s+/, ''); // Remove leading whitespace string = string.replace(/\s+$/, ''); // Remove trailing whitespace // å°ææ空ç½é¨ä»½ç¨å®ä¸ç©ºç½ä»£æ¿ string = string.replace(/\s+/g, ' '); return string; // å³åæ¹è®å¾çå¼ } //////////////////////////////////////////////////////////////////////////////// // TutTB_ConvertTermsToURI() å½å¼å°å³å ¥çæå°å串è½æçºå®å ¨ç網å //////////////////////////////////////////////////////////////////////////////// function TutTB_ConvertTermsToURI(terms) { // 建ç«é£ååæ¾æ¯åæå°å串 var termArray = new Array(); // ç¨ç©ºç½åå åå²å串 termArray = terms.split(" "); // ç¨ä¾åæ¾å®å ¨ç網å var result = ""; // å¨å串ä¸éè¿´ for(var i=0; i<termArray.length; i++) { // å¨ç¬¬ä¸åå串å¾çææçå串æç¨å è(+)éé if(i > 0) result += "+"; // ä½¿ç¨ Firefox å §å»ºç encodeURIComponent() å½å¼å å¯ result += encodeURIComponent(termArray[i]); } return result; // å³åçµæ } //////////////////////////////////////////////////////////////////////////////// // TutTB_LoadURL() å½å¼å¨ç覽å¨ä¸è¼å ¥ç¹å®ç網å //////////////////////////////////////////////////////////////////////////////// function TutTB_LoadURL(url) { // å¨ç¶²ååè¨å®å³å ¥ç網å window._content.document.location = url; // Make sure that we get the focus window.content.focus(); }
éåä½ ç Firefox éç¼çæ¬ï¼å¨æåçå·¥å ·åå¥ä»¶è¼¸å ¥æå°çå¼ï¼ç¶å¾æä¸ç¶²é æå°æéãç¨å¼ç¢¼æ該æå·è¡ï¼ç¶å¾æåºç¾æå°çµæãéååæ éç¼çæ¬ç¢ºå¯¦æ¯ç¸ç¶ä¾¿å©çå§ï¼
æéé¸å®ç注æäºé (A Special Note About Button-Menu Buttons)
å¨æåé²å ¥ä¸ä¸å¼µç« ç¯ä¹åï¼æä¸é»éæ¼æéé¸å®æè¦æ³¨æçãåæ³ä¸ä¸ï¼éé¡åçæéæä¾å¯ä»¥é»æçæéèå½åºå¼é¸å®(主è¦ç¯ä¾çºå¾åèåå¾ç覽)ãä¹æ³ä¸ä¸ï¼toolbarbutton 以åå å« oncommand ç menuitem å ç´ ãç¶å·¥å ·åæéçä¸é¨å被ååï¼toolbarbutton å ç´ ç oncommand ç¨å¼ç¢¼å¦ä½ æææç被å·è¡ãä½æ¯ï¼ç¶ä½¿ç¨è ååäºmenuitem å ç´ çå ¶ä¸ä¸åæï¼æç¼çä»éº¼äºï¼
ä¸åªæ¯ menuitem å ç´ ç oncommand äºä»¶å·è¡ï¼toolbarbutton å ç´ çäºä»¶ä¹è¢«å·è¡ãæä»¥å ©åäºä»¶æ¯åæå·è¡çï¼åç®¡ä½ åªæ¯æ³è¦å ¶ä¸ä¸ä»¶è¢«å·è¡ãå çº toolbarbutton äºä»¶æ¯æå¾ç¼ççï¼æ以實éå·è¡çæ¯ toolbarbutton äºä»¶ãæå¥è©±èªªï¼menuitem äºä»¶æ²ææ©æå·è¡ãé£æåè¦æ樣解決éååé¡å¢ï¼äºå¯¦ä¸ï¼æ¯æ辦æ³çãè®æåå¾åçç menuitem å ç´ ï¼
<menuitem id="TutTB-Combined-Image" label="Image Search" class="menuitem-iconic" tooltiptext="Search Images" oncommand="TutTB_Search(event, 'image'); event.preventBubble();" />
èç±ä½¿ç¨ DOM å½å¼ preventBubble()ï¼æåå¯ä»¥é¿å oncommand 被å·è¡ãçºäºé¿å å¤é·å¤¢å¤ï¼è¨ä½ä¸ä»¶äºï¼ç¶ä½ 建ç«æéé¸å®æï¼è¨å¾å¨ menuitem å ç´ ç oncommand 屬æ§å å ¥ event.preventBubble()ã
çºæå°åå å ¥åè½ (Adding Functionality to the Search Box)
ç¾å¨ï¼æåå·²ç¶è®æå°æéå¯ä»¥ä½¿ç¨ï¼æ¥ä¸ä¾ï¼æåéè¦å¹«æå°åå å ¥ä¸äºåè½ãè®ä½¿ç¨è å¯ä»¥å¨è¼¸å ¥å串å¾æä¸ãEnterã以å·è¡æå°ãè¦æ麼åå¢ï¼è®æåççè¦ä½¿ç¨çå½å¼ï¼
<toolbaritem id="TutTB-SearchTerms-TBItem" persist="width"> <menulist id="TutTB-SearchTerms" editable="true" flex="1" minwidth="100" width="250" onkeypress="TutTB_KeyHandler(event);"> <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" /> </menulist> </toolbaritem>
é次ï¼æåä½¿ç¨ onkeypress ä»£æ¿ oncommandãéåäºä»¶æå¨ä½¿ç¨è å¨æå°åæä¸æéµæ觸ç¼ãå¨éåç¯ä¾ï¼æå建ç«ä¸åç¸ç¶ç°¡å®ç TutTB_KeyHandler()å½å¼ï¼
function TutTB_KeyHandler(event) { if(event.keyCode == event.DOM_VK_RETURN) TutTB_Search(event, 'web'); }
éåå½å¼åªä¸éæ¯è¦æª¢æ¥ãEnterãæ¯å¦è¢«æä¸ãå¦ææ¯ï¼TutTB_Search()æ被å¼å«ãå¦åï¼ä¸åä»»ä½äºãè®æåä¾ççå å ¥æ¤å½å¼ç JavaScript æªæ¡[View JavaScript Revision 2]ï¼
//////////////////////////////////////////////////////////////////////////////// // TutTB_Search() å½å¼æçºæåå®ææå°ãevent åæ¸æ觸ç¼å½å¼çå¼å«ï¼type åæ¸ // çºæå°çé¡åã //////////////////////////////////////////////////////////////////////////////// function TutTB_Search(event, type) { // å°è¦ç覽ç網å var URL = ""; // 辨å¥æå°æ¬ä½æ¯å¦çºç©ºå¼ var isEmpty = false; // èçæå°æ¬ä½ ( <menulist> å ç´ ) var searchTermsBox = document.getElementById("TutTB-SearchTerms"); // å¾æå°æ¬ä½ååºå串ï¼æ´çå¿ è¦çç©ºç½ // å¯ä»¥å¨ä¸é¢çç TutTB_TrimString() å½å¼éä½çç´°ç¯ var searchTerms = TutTB_TrimString(searchTermsBox.value); if(searchTerms.length == 0) // æå°æ¬ä½æ¯ç©ºç½çåï¼ isEmpty = true; // æ¯ï¼è¨å® isEmpty çº true else // ä¸ï¼è½æçºå®å ¨ç網å searchTerms = TutTB_ConvertTermsToURI(searchTerms); // é¸ææå°çé¡å // å¦ææ¬ä½æ¯ç©ºç½çï¼æåæå¼å°ä½¿ç¨è å° Google 網é ä¸é©ç¶çå°æ¹ã // å¦åï¼æå°è¼¸å ¥çæåã switch(type) { // 建ç«åçæå°ç網å case "image": if(isEmpty) { URL = "http://images.google.com/"; } else { URL = "http://images.google.com/images?q=" + searchTerms; } break; // 建ç«ç¶²é æå°ç網å case "web": default: if(isEmpty) { URL = "http://www.google.com/"; } else { URL = "http://www.google.com/search?q=" + searchTerms; } break; } // ä½¿ç¨ TutTB_LoadURL å½å¼å¨ç覽è¦çªä¸è¼å ¥ç¶²å TutTB_LoadURL(URL); } //////////////////////////////////////////////////////////////////////////////// // TutTB_TrimString() å½å¼æä¿®åªå串çåå¾ç©ºç½é¨ä»½ï¼ç¶å¾å°ææç空ç½é¨ä»½è½ææ // å®ä¸å空ç½ï¼ç¶å¾å³åä¿®æ¹å¾å串ã //////////////////////////////////////////////////////////////////////////////// function TutTB_TrimString(string) { // å¦æå³å ¥çå串ç¡æï¼ææ¯æ²ææ±è¥¿ï¼åå³åç©ºå¼ if (!string) return ""; string = string.replace(/^\s+/, ''); // Remove leading whitespace string = string.replace(/\s+$/, ''); // Remove trailing whitespace // å°ææ空ç½é¨ä»½ç¨å®ä¸ç©ºç½ä»£æ¿ string = string.replace(/\s+/g, ' '); return string; // å³åæ¹è®å¾çå¼ } //////////////////////////////////////////////////////////////////////////////// // TutTB_ConvertTermsToURI() å½å¼å°å³å ¥çæå°å串è½æçºå®å ¨ç網å //////////////////////////////////////////////////////////////////////////////// function TutTB_ConvertTermsToURI(terms) { // 建ç«é£ååæ¾æ¯åæå°å串 var termArray = new Array(); // ç¨ç©ºç½åå åå²å串 termArray = terms.split(" "); // ç¨ä¾åæ¾å®å ¨ç網å var result = ""; // å¨å串ä¸éè¿´ for(var i=0; i<termArray.length; i++) { // å¨ç¬¬ä¸åå串å¾çææçå串æç¨å è(+)éé if(i > 0) result += "+"; // ä½¿ç¨ Firefox å §å»ºç encodeURIComponent() å½å¼å å¯ result += encodeURIComponent(termArray[i]); } return result; // å³åçµæ } //////////////////////////////////////////////////////////////////////////////// // TutTB_LoadURL() å½å¼å¨ç覽å¨ä¸è¼å ¥ç¹å®ç網å //////////////////////////////////////////////////////////////////////////////// function TutTB_LoadURL(url) { // å¨ç¶²ååè¨å®å³å ¥ç網å window._content.document.location = url; // Make sure that we get the focus window.content.focus(); } //////////////////////////////////////////////////////////////////////////////// // TutTB_KeyHandler() 檢æ¥ãEnterãæ¯å¦è¢«è¼¸å ¥ãæ¯ç話ï¼å°±å·è¡æå° //////////////////////////////////////////////////////////////////////////////// function TutTB_KeyHandler(event) { // [ENTER]被æä¸äºåï¼å¦ææ¯ï¼å·è¡æå° if(event.keyCode == event.DOM_VK_RETURN) TutTB_Search(event, 'web'); }
å¨ä¸æ¬¡ï¼å·è¡ä½ ç Firefox éç¼çæ¬ï¼å¨æå°åè¼¸å ¥æå°å串ï¼ç¶å¾æä¸ãEnterããå°±åæ¯æä¸æå°æéä¸æ¨£ï¼æå°çµææ該æåºç¾ãç¾å¨ï¼æåçå¥ä»¶å·²ç¶æäºçå½ï¼
åæ ç½®å ¥é¸å® (Dynamically Populating a Menu)
åæ çå°é¸å®é ç®æ¾ç½®å¨é¸å®è£¡æ¯å¾æç¨çï¼é好éåç¹è²æ¯å¾å®¹æå®æçãå¨éåæå裡ï¼æåå°æå¨æå°åä¸æå¼é¸å®åæ çå å ¥ä¸äºé ç®ãè®æåççç¨ä¾å»ºç«å·¥å ·åçé¨ä»½ï¼
<toolbaritem id="TutTB-SearchTerms-TBItem" persist="width"> <menulist id="TutTB-SearchTerms" editable="true" flex="1" minwidth="100" width="250" onkeypress="TutTB_KeyHandler(event);"> <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" /> </menulist> </toolbaritem>
注æå°ï¼å¨ menupopup å ç´ ç onpopupshowing 屬æ§ãæåæå® TutTB_Populate()å½å¼å¨æ¯æ¬¡ãå½åºå¼é¸å®ãå³å°é¡¯ç¤ºæ被å·è¡ï¼éåå½å¼å°æ建ç«æåçåæ é¸å®é ç®ãè®æåä¾ççå½å¼çç¨å¼ç¢¼[View TutTB_Populate() Code]ï¼
//////////////////////////////////////////////////////////////////////////////// // TutTB_Populate() å½å¼å¨å·¥å ·åæ¬ä½çä¸æå¼é¸å®æ¾ç½®åæ ç¢ççé¸å®é ç®ã // éç¶éä¸æ¯é常實ç¨çï¼ä½æ¯èç±éåç¯ä¾ï¼æåå¯ä»¥ççåæ é¸å®ç½®å ¥çéä½æ¹å¼ã //////////////////////////////////////////////////////////////////////////////// function TutTB_Populate() { // åå¾å½åºé¸å®å ç´ var menu = document.getElementById("TutTB-SearchTermsMenu"); // 移é¤å¨å½åºé¸å®ç®åçé ç® for(var i=menu.childNodes.length - 1; i >= 0; i--) { menu.removeChild(menu.childNodes.item(i)); } // æå®è¦å¨é¸å®å¢å çé ç®æ¸é var numItemsToAdd = 10; for(var i=0; i<numItemsToAdd; i++) { // 建ç«è¦å¢å çæ°é¸å®é ç® var tempItem = document.createElement("menuitem"); // è¨å®æ°é¸å®é ç®çæ¨ç±¤ tempItem.setAttribute("label", "Dynamic Item Number " + (i+1)); // å¨é¸å®ä¸æ°å¢é ç® menu.appendChild(tempItem); } }
éåå½å¼ç¯ä¾ä¸æå½ä»¤æ¯å menuitem å ç´ å»å·è¡é¸æçæ令ãçºäºè®æ¯å menuitem ç¥éæ該å·è¡çæ令ï¼æåå å åªè¦å å ¥ setAttribute()å½å¼ä¾èçäºä»¶åå·è¡ç¨å¼ç¢¼ãéæ¯èç oncommand äºä»¶çç¯ä¾ï¼
tempItem.setAttribute("oncommand", "TutTB_SomeFunction()");
å å ¥ TutTB_Populate()å½å¼å¾ç JavaScript æªæ¡[View JavaScript Revision 3]ï¼
//////////////////////////////////////////////////////////////////////////////// // TutTB_Search() å½å¼æçºæåå®ææå°ãevent åæ¸æ觸ç¼å½å¼çå¼å«ï¼type åæ¸ // çºæå°çé¡åã //////////////////////////////////////////////////////////////////////////////// function TutTB_Search(event, type) { // å°è¦ç覽ç網å var URL = ""; // 辨å¥æå°æ¬ä½æ¯å¦çºç©ºå¼ var isEmpty = false; // èçæå°æ¬ä½ ( <menulist> å ç´ ) var searchTermsBox = document.getElementById("TutTB-SearchTerms"); // å¾æå°æ¬ä½ååºå串ï¼æ´çå¿ è¦çç©ºç½ // å¯ä»¥å¨ä¸é¢çç TutTB_TrimString() å½å¼éä½çç´°ç¯ var searchTerms = TutTB_TrimString(searchTermsBox.value); if(searchTerms.length == 0) // æå°æ¬ä½æ¯ç©ºç½çåï¼ isEmpty = true; // æ¯ï¼è¨å® isEmpty çº true else // ä¸ï¼è½æçºå®å ¨ç網å searchTerms = TutTB_ConvertTermsToURI(searchTerms); // é¸ææå°çé¡å // å¦ææ¬ä½æ¯ç©ºç½çï¼æåæå¼å°ä½¿ç¨è å° Google 網é ä¸é©ç¶çå°æ¹ã // å¦åï¼æå°è¼¸å ¥çæåã switch(type) { // 建ç«åçæå°ç網å case "image": if(isEmpty) { URL = "http://images.google.com/"; } else { URL = "http://images.google.com/images?q=" + searchTerms; } break; // 建ç«ç¶²é æå°ç網å case "web": default: if(isEmpty) { URL = "http://www.google.com/"; } else { URL = "http://www.google.com/search?q=" + searchTerms; } break; } // ä½¿ç¨ TutTB_LoadURL å½å¼å¨ç覽è¦çªä¸è¼å ¥ç¶²å TutTB_LoadURL(URL); } //////////////////////////////////////////////////////////////////////////////// // TutTB_TrimString() å½å¼æä¿®åªå串çåå¾ç©ºç½é¨ä»½ï¼ç¶å¾å°ææç空ç½é¨ä»½è½ææ // å®ä¸å空ç½ï¼ç¶å¾å³åä¿®æ¹å¾å串ã //////////////////////////////////////////////////////////////////////////////// function TutTB_TrimString(string) { // å¦æå³å ¥çå串ç¡æï¼ææ¯æ²ææ±è¥¿ï¼åå³åç©ºå¼ if (!string) return ""; string = string.replace(/^\s+/, ''); // 移é¤åé¢ç©ºç½ string = string.replace(/\s+$/, ''); // 移é¤å¾é¢ç©ºç½ // å°ææ空ç½é¨ä»½ç¨å®ä¸ç©ºç½ä»£æ¿ string = string.replace(/\s+/g, ' '); return string; // å³åæ¹è®å¾çå¼ } //////////////////////////////////////////////////////////////////////////////// // TutTB_ConvertTermsToURI() å½å¼å°å³å ¥çæå°å串è½æçºå®å ¨ç網å //////////////////////////////////////////////////////////////////////////////// function TutTB_ConvertTermsToURI(terms) { // 建ç«é£ååæ¾æ¯åæå°å串 var termArray = new Array(); // ç¨ç©ºç½åå åå²å串 termArray = terms.split(" "); // ç¨ä¾åæ¾å®å ¨ç網å var result = ""; // å¨å串ä¸éè¿´ for(var i=0; i<termArray.length; i++) { // å¨ç¬¬ä¸åå串å¾çææçå串æç¨å è(+)éé if(i > 0) result += "+"; // ä½¿ç¨ Firefox å §å»ºç encodeURIComponent() å½å¼å å¯ result += encodeURIComponent(termArray[i]); } return result; // å³åçµæ } //////////////////////////////////////////////////////////////////////////////// // TutTB_LoadURL() å½å¼å¨ç覽å¨ä¸è¼å ¥ç¹å®ç網å //////////////////////////////////////////////////////////////////////////////// function TutTB_LoadURL(url) { // å¨ç¶²ååè¨å®å³å ¥ç網å window._content.document.location = url; // Make sure that we get the focus window.content.focus(); } //////////////////////////////////////////////////////////////////////////////// // TutTB_KeyHandler() 檢æ¥ãEnterãæ¯å¦è¢«è¼¸å ¥ãæ¯ç話ï¼å°±å·è¡æå° //////////////////////////////////////////////////////////////////////////////// function TutTB_KeyHandler(event) { // [ENTER]被æä¸äºåï¼å¦ææ¯ï¼å·è¡æå° if(event.keyCode == event.DOM_VK_RETURN) TutTB_Search(event, 'web'); } //////////////////////////////////////////////////////////////////////////////// // TutTB_Populate() å½å¼å¨å·¥å ·åæ¬ä½çä¸æå¼é¸å®æ¾ç½®åæ ç¢ççé¸å®é ç®ã // éç¶éä¸æ¯é常實ç¨çï¼ä½æ¯èç±éåç¯ä¾ï¼æåå¯ä»¥ççåæ é¸å®ç½®å ¥çéä½æ¹å¼ã //////////////////////////////////////////////////////////////////////////////// function TutTB_Populate() { // åå¾å½åºé¸å®å ç´ var menu = document.getElementById("TutTB-SearchTermsMenu"); // 移é¤å¨å½åºé¸å®ç®åçé ç® for(var i=menu.childNodes.length - 1; i >= 0; i--) { menu.removeChild(menu.childNodes.item(i)); } // æå®è¦å¨é¸å®å¢å çé ç®æ¸é var numItemsToAdd = 10; for(var i=0; i<numItemsToAdd; i++) { // 建ç«è¦å¢å çæ°é¸å®é ç® var tempItem = document.createElement("menuitem"); // è¨å®æ°é¸å®é ç®çæ¨ç±¤ tempItem.setAttribute("label", "Dynamic Item Number " + (i+1)); // å¨é¸å®ä¸æ°å¢é ç® menu.appendChild(tempItem); } }
åæ å å ¥å·¥å ·åæé (Dynamically Adding Toolbar Buttons)
å å ¥åæ å·¥å ·åæéå°±è·åæ ç½®å ¥é¸å®ä¸æ¨£ç°¡å®ï¼èä¸éé常ç¸ä¼¼ãé¦å ï¼æåéè¦ä¸åå å«åæ æéç容å¨ãå¨éå ï¼ toolbaritem å ç´ æ¯ä¸é¯çé¸æï¼æ¨è¨å¦ä¸ï¼
<toolbaritem id="TutTB-DynButtonContainer" />
ç¾å¨ï¼å®¹å¨å·²ç¶å¯ä»¥å©ç¨äºï¼æåå¯ä»¥ä½¿ç¨å®ï¼ä¾å å ¥åæ toolbarbutton å ç´ ï¼è®æåä¾çä¸ä¸å¯ä»¥è®æåå å ¥åæ æéçå½å¼ç¯ä¾ï¼
function TutTB_AddDynamicButtons() { // åå¾æåå¨ XUL æè¿°ä¸å¢å çå·¥å ·åé ç®ã容å¨ã var container = document.getElementById("TutTB-DynButtonContainer"); // 移é¤ææåå¨çæé for(i=container.childNodes.length; i > 0; i--) { container.removeChild(container.childNodes[0]); } // å¢å äºååæ æé for(var i=0; i<5; i++) { var tempButton = null; tempButton = document.createElement("toolbarbutton"); tempButton.setAttribute("label", "Button " + i); tempButton.setAttribute("tooltiptext", "Button " + i); tempButton.setAttribute("oncommand", "TutTB_SomeFunction()"); container.appendChild(tempButton); } }
éåå½å¼åç½®å ¥åæ é¸å®é常ç¸ä¼¼ãæåå¾å®¹å¨ä¸ç§»é¤ç¾æçåæ æéï¼ç¶å¾å å ¥æ°çã
Optional Programming Exerciseï¼è©¦èç¨éåæ¦å¿µä¾å¢å ãæå°å串æé(search word buttons)ãå°å·¥å ·åãç¶ä½¿ç¨è å¨æå°å串æééµå ¥æåæï¼åæ å°å¢å æéå°å·¥å ·åçæå¾ï¼ä¸åæéä¸ååãéå æå¹¾åæ示ï¼
- ä½ éè¦å¢å toolbaritem 容å¨å° XUL æè¿°æªçæå¾(right before the toolbarspring element is a good choice)ãç¢ºå® ID æ¯å¯ä¸çã
- å¨ menulist å ç´ ä¸ä½¿ç¨ oninput äºä»¶ï¼éåäºä»¶æå¨ä½¿ç¨è è¼¸å ¥æåæ觸ç¼ã
- ä½ å¼å«ç JavaScript æåä¸åçäºï¼(a)å¨æå°æ¬ä½ä¸åå¾æå°æå(b)移é¤ææå å建ç«çåæ æé(c)以空ç½åéæå°æå(d)çºæ¯åç¨ç«çæå建ç«æéã
éå°±æ¯æèç Googlebar Lite çæ¹å¼ã
ééèååæé (Disabling and Enabling Buttons)
(éé¨ä»½åªæ¯åè¨´ä½ æ麼ç¨ï¼å¨éåå·¥å ·åç¯ä¾ä¸¦ä¸æåºç¾)ã
ä½ å¶ç¾å¯è½ææ³è¦ééææ¯ååå·¥å ·åæéãèåä¾åï¼Googlebar Lite çé«äº®åº¦æ¨è¨æéä¸æå¨æå°æ¬ä½æ²ææå°å串æç¼çä½ç¨ï¼åªè½å·è¡æ¼ææå°å串æã
ä¸é¢çä¾åæ¯å¦ä½å»ºç«ä¸åå¯ä»¥æ§å¶ééçä¸è¬å·¥å ·åæéãå次æéï¼éä¸æ¯å¯¦ç¨çç¯ä¾ï¼åªæ¯èæéåæææ¯å¯ä»¥åå¾å°çãæ¥èæ¯é¸å®é ç®çæè¿°æ¨è¨ï¼
<menuitem label="Toggle Web Search Button" tooltiptext="Toggle Web Search Button" oncommand="TutTB_ToggleWebSearchButton()" />
TutTB_ToggleWebSearchButton()å½å¼çç¨å¼ç¢¼ï¼
function TutTB_ToggleWebSearchButton() { var button = document.getElementById("TutTB-Web-Button"); var value = button.disabled; if(value == true) button.disabled = false; else button.disabled = true; }
é¦å ï¼æåå°æè趣çå·¥å ·åæéä½¿ç¨ ID å¼ä»¥å getElementById()å½å¼ãåªè¦ææéï¼æåå°±è½ä½¿ç¨ disabled 屬æ§æ§å¶è©²æéç©ä»¶çç¾æçæ (ååæéé)ãå¦æå¼çº trueï¼å°±ä½¿ç¨ false åæ¶æéééï¼åä¹äº¦ç¶ãFirefox æ幫æåèçæéçééï¼è®è©²æéä¸è½é»æ(note that the button's image may not appeared grayed out: we must rely on skinning for that)ã
åæ 顯示èé±èæé (Dynamically Showing and Hiding Buttons)
(éé¨ä»½åªæ¯åè¨´ä½ æ麼ç¨ï¼å¨éåå·¥å ·åç¯ä¾ä¸¦ä¸æåºç¾)ã
Googlebar Lite å 許使ç¨è é¸ææéå¨å·¥å ·åæçå°ç樣åãä¹å°±æ¯èªªï¼å·¥å ·åå¿ é è½å¤ åæ ç顯示ææ¯é±èå¯ç¨çæéãéæ¯æåè¦å®æç JavaScriptç¨å¼ç¢¼ç段ï¼
var TB_Web = document.getElementById("TutTB-Web-Button"); TB_Web.setAttribute("hidden", !TutTB_ShowWebButton);
é¦å æåè®å·¥å ·åæéä½¿ç¨ getElementById() å½å¼ï¼ç¶å¾æåå¼å« setAttribute()å½å¼ä¾æ¹è® hidden 屬æ§çå¼ãä½ æç¼ç¾éå hidden å¼è·æå¨ TutTB_ShowWebButton æè¨å®çç¸åãéåå¼æ¯åå¸ææ¨ç±¤(boolean flag)ï¼ç¨ä¾è¾¨å¥ä½¿ç¨è æ¯å¦æ³è¦çå°ã網é æå°ãæéãå²åå¨éåè®æ¸çå¼ï¼æ¯å¾ä½¿ç¨è è¨å®ä¸è®åå°çãç¹¼çºé±è®ï¼ä¾ççæåå¦ä½åå°éé»ã
è®åèå²å使ç¨è è¨å® (Reading and Storing User Preferences)
(éé¨ä»½åªæ¯åè¨´ä½ æ麼ç¨ï¼å¨éåå·¥å ·åç¯ä¾ä¸¦ä¸æåºç¾)ã
çºäºè®åæå²åçè¨å®ï¼æåéè¦åå Firefox è¨å®æåä»é¢(preferences service interface)ãæåå¯ä»¥å»ºç«ä¸åè®æ¸ä¾å®æï¼
const TutTB_PrefService = Components.classes["@mozilla.org/preferences-service;1"]. getService(Components.interfaces.nsIPrefService);
ä¸æ¦ååè¨å®ä»é¢ï¼æåå°±å¯ä»¥ç²å¾å¥ä»¶è¨å®çä¸é¨å(i.e. the location in the preferences "registry" where our extension's settings are kept)ï¼
const TutTB_Branch = TutTB_PrefService.getBranch("tuttoolbar.");
åè¨éåå¥ä»¶ç¯ä¾çè¨å®èµ·å§æ¼ tuttoolbar æåï¼å æ¤ï¼æåè¨å®å串 getBranch() (å §å»ºç Fireofx å½å¼) ãéåå½å¼å¯ä»¥è®æåååå¥ä»¶çè¨å®ï¼æå¾å¯ä»¥ç²å¾åå¥é¸é çå¼ãéæ¯æåååæå°ã顯示網é æå°æéãé¸é å¯ä»¥åå¾çå¼ï¼
if(TutTB_Branch.prefHasUserValue("show.button.web")) TutTB_ShowWebButton = TutTB_Branch.getBoolPref("show.button.web"); else { TutTB_Branch.setBoolPref("show.button.web", false); TutTB_ShowWebButton = false; }
é¦å ï¼æå測試éåè¨å®æ¯å¦åå¨æ¼è¨å®æ¨¹ççµæ§è£¡ãå¦æåå¨ï¼å°±ç¨ getBoolPref()å½å¼è®åå®çå¼(å²åæ¼ TutTB_ShowWebButton è®æ¸)ãå¦åï¼æåå°±è¨å®çºé è¨å¼(è¨å®ç樹èå ¨åè®æ¸)ã
å²åè¨å®æ¯å¾ç°¡å®çå§ï¼ä½ åªè¦æä¾è¨å®çå稱ï¼ç¶å¾ä½¿ç¨éåå¼ï¼
TutTB_Branch.setBoolPref("show.button.web", TutTB_ShowWebButton);
ãè®åèå²åè¨å®ãç¨ä¾å²åä½ çå¥ä»¶è¨å®æ¯å¾æ¹ä¾¿çæ¹å¼ã大é¨åçå¥ä»¶é½ä½¿ç¨éååè½ï¼æ許å¤å¯ä½¿ç¨çç¯ä¾çèä½ å»ç 究ãå¦å¤ï¼å¯ä»¥çç MozillaZine knowledge base çæç« ã
第ä¸ç« ï¼å°è£ (Packaging the Toolbar)
å°ç®åçºæ¢ï¼æåç¨åæ éç¼ä¾èçå®è£çé¨ä»½ãä½æ¯ä½¿ç¨è 並ä¸ææ³ç¨é樣çæ¹å¼ä¾å®è£å¥ä»¶ï¼æ以æåå¿ é å°è£æªæ¡æä¸åå®è£æªãæåå°è¦å»ºç«å ©åæªæ¡ï¼XPI å JARãå¥è¢«é樣çæªæ¡å稱給é¨äºï¼ä»ååªä¸éæ¯ç¨ zip å£ç¸®æªæ¡æ ¼å¼å½è£çã
ç¾å¨æ¯å£ç¸®å·¥å ·ç¼æ®åæçæåäºï¼æå人建è°ä½¿ç¨ WinZip (å½ä»¤å模å¼)ï¼ä½æ¯ç¶²è·¯ä¸ä¹æä¸å°å è²»çå·¥å ·ãå¨é份æåä¸ ï¼ ææä½¿ç¨ UNIX å£ç¸®å·¥å ·;å¨ Windows ä¸ï¼å¯ä»¥ä½¿ç¨ Cygwin ã
æ´æ° Chrome æ¸ å® (Updating the Chrome Manifest)
第ä¸æ¥å°è£å å«äºæ´æ° chrome æ¸ å®ã注æï¼å¦æè¦ç¹¼çºåæ éç¼ï¼ä½ è¦æå ©å chrome æ¸ å®ï¼ä¸åæ¯å°è£ç¨çï¼å¦ä¸åæ¯åæ éç¼ç¨çãèçéå ©åæªæ¡æ¯å¾éº»ç ©çï¼æ以æååªéå°æåä¸å·²åå¨ç chrome æ¸ å®åèçã注æï¼å¨æåä¿®æ¹æ¸ å®å¾ï¼å°±ä¸è½ç¨å¨åæ éç¼äºï¼é¤éä½ ä¿®æ¹åä¾ãè®æåå ä¾åæ¶ä¸ä¸æ¸ å®çå §å®¹ï¼
content tuttoolbar chrome/content/ overlay chrome://browser/content/browser.xul chrome://tuttoolbar/content/tuttoolbar.xul skin tuttoolbar classic/1.0 chrome/skin/
æå ©åå°æ¹éè¦ä¿®æ¹ï¼å çç第ä¸è¡ï¼
content tuttoolbar jar:chrome/tuttoolbar.jar!/content/
æåå å ¥äºå ©åé ç®ãé¦å æ¯ jar: ï¼æ¾ç½®å¨è·¯å¾çåé¢ãéæå® Firefox å¿ é å¾ JAR æªæ¡ä¸ååºå¥ä»¶çå §å®¹ãåä¾ï¼æåå å ¥ tuttoolbar.jar!/ï¼ä»æ¼ chrome/ å content/ ç®éä¸éï¼éæè¿°äºåªå JAR éè¦è¢«ååºçãéå JAR çæªåå¿ é è¦è·å¥ä»¶çæªåç¸åï¼å樣å°ï¼å¿ é è·æªåä¸æ¨£ä½¿ç¨å°å¯«åé«ã注æï¼é©åèä¸æ¯æåé¯èª¤ï¼éæ¯å¿ è¦çãå¦ä¸åéè¦ä¿®æ¹çè·¯å¾æ¯ skin ï¼ä¾ççä¿®æ¹å¾çå §å®¹ï¼
content tuttoolbar jar:chrome/tuttoolbar.jar!/content/ overlay chrome://browser/content/browser.xul chrome://tuttoolbar/content/tuttoolbar.xul skin tuttoolbar classic/1.0 jar:chrome/tuttoolbar.jar!/skin/
å»ºç« JAR æªæ¡ (Creating the JAR File)
第ä¸åè¦å°è£çæ¯ JAR æªæ¡ãé¦å æåèç chrome ç®éï¼å å«äº XULãJavaScriptãCSS 以ååçãæªæ¡çµæ§å¦ä¸ï¼
+- TutToolbar/ +- install.rdf +- chrome.manifest +- chrome/ +- tuttoolbar.jar +- content/ +- tuttoolbar.xul +- tuttoolbar.js +- skin/ +- combined.png +- gripper.png +- images.png +- main.png +- web.png +- tuttoolbar.css
å°è£ JAR ææ¯ XPI æï¼æ容æç¯çé¯èª¤å°±æ¯éºæ¼äºç¸éçæªæ¡ãå¦ææååè£ JAR æªæ¡æ¯åç®éï¼è£¡é¢å å«äºï¼
+- content/ +- tuttoolbar.xul +- tuttoolbar.js +- skin/ +- combined.png +- gripper.png +- images.png +- main.png +- web.png +- tuttoolbar.css
éæ¯æç¨ UNIX å·¥å ·çæ¹å¼(å½ä»¤å模å¼)ï¼
zip -r tuttoolbar.jar content/* skin/*
(è¯è ï¼ä¸è¬ Windows 使ç¨è å¯ä»¥ç´æ¥å° content å skin ç®é以 zip æ ¼å¼å£ç¸®æå¯æªå .jar çæªæ¡ã)
å»ºç« XPI æªæ¡(Creating the XPI File)
å¨å»ºç«å¥½ JAR æªæ¡ä¹å¾ï¼æåå¿ é å»ºç« XPI æªæ¡ï¼éæ¯çæ£ä½ è¦çµ¦ä½¿ç¨è ç¨çå¥ä»¶å®è£æªãæåå¿ é å¨æä¸å±¤ç®éä¸å»ºç«éåæªæ¡ï¼çµæ§å¦ä¸ï¼
+- TutToolbar/ +- tuttoolbar.xpi +- install.rdf +- chrome.manifest +- chrome/ +- tuttoolbar.jar +- content/ +- tuttoolbar.xul +- tuttoolbar.js +- skin/ +- combined.png +- gripper.png +- images.png +- main.png +- web.png +- tuttoolbar.css
è· JAR æªæ¡ä¸æ¨£ï¼XPI å¿ é ç¶æç¸å°çè·¯å¾ãå¨ XPI æªæ¡ä¸ï¼å å«äºä¸åæªæ¡ï¼å®è£æ¸ å®ãchrome æ¸ å®ååå建ç«ç JAR æªæ¡ãXPI 裡å å«äºï¼
+- install.rdf +- chrome.manifest +- chrome/ +- tuttoolbar.jar
ä½¿ç¨ UNIX å·¥å ·çæ¹å¼ï¼
zip tuttoolbar.xpi install.rdf chrome.manifest chrome/tuttoolbar.jar
å¥ä»¶å®è£æ¸¬è©¦ (Installing Your Toolbar Extension)
æäº XPI æªæ¡ä¹å¾ï¼å°±å¯ä»¥éå§å®è£çæ¥é©ãå¨ç¼è¡¨å¥ä»¶åï¼ä½ ä¸å®è¦å 確å®å¥ä»¶å¯ä»¥å®è£ãä¸å¯ä»¥ä½¿ç¨éç¼è¨å®æªä¾æ¸¬è©¦å®è£ï¼å管å¨é£ä»½è¨å®æªå·²ç¶æå¥ä»¶çå®è£çæ¬ãç¨ä½ ä¸è¬ä½¿ç¨çï¼ææ¯å¦ä¸åè¨å®æªï¼ä¾ä¸é¢çæ¥é©ä¾æ¸¬è©¦å®è£ï¼
- æªæ¡ > éåæªæ¡ (ææ¯ç¨ Ctrl+O) ã
- å¨å°è©±æ¡ä¸ï¼æ¾å°ä½ ç XPI æªæ¡ï¼é»é¸ãéåãã
å¦ææ£ç¢ºå°å®æå¾ï¼ä½ æçå°å®è£ç«é¢ãé¸æä½ è¦å®è£å¾ï¼éæ°éå Firefoxãä¹å¾ï¼ä½ æ該æçå°å·¥å ·åäºï¼æåä½ å®æ第ä¸åå·¥å ·åå¥ä»¶ï¼
å éå°è£éç¨ (Speeding Up the Packaging Process)
æåå°è£å¥ä»¶å¾è®äººåç ©çï¼çºä½ä¸ç¨æè¿°æªä¾å®æå¢ï¼å¦ææå½ä»¤å模å¼ç ZIP å·¥å ·ï¼ä½ å¯ä»¥å°éç¨èªååãä¸é¢çç¯ä¾ä½¿ç¨ DOS æ¹æ¬¡æªå UNIX å£ç¸®å·¥å ·ã
é¦å 建ç«å ©åæåæªï¼æä¸å±¤ç®éç xpizip.txt ï¼å chrome ç®éä¸ç jarzip.txt ã æªæ¡ä¸å å«äºè¦å°è£çé ç®ï¼ [View xpizip.txt] [View jarzip.txt]
ä¸ä¸æ¥ï¼å¨æä¸å±¤ç®éä¸å»ºç« DOS æ¹æ¬¡æª(.bat)ï¼å §å®¹å¦ä¸ï¼
zip -r chrome/tuttoolbar.jar -@ < chrome/jarzip.txt zip -r tuttoolbar.xpi -@ < xpizip.txt
å¦ä½ æè¦ï¼éåæè¿°æªç¸ç¶ç°¡å®ãç¶èï¼ä½ çæè¿°æªå¯è½æ¯éåæ´è¤éãæç¨ä¾å»ºç« Googlebar Lite çæè¿°æªå¯ä»¥åæ´å¤äºãå®å¯ä»¥çºæèªåæ´æ°ææççæ¬ä»£èï¼åå®ææªæ¡çå°è£ãéåæè¿°æªæ¯ç¨ Perl å®æçï¼èä¸ä½¿ç¨ 1.0.x çå®è£æ¹æ¡(èé份æåæäºå¾®çä¸å)ãææä¾éåæè¿°æªçµ¦æè趣ç人ï¼[View the Googlebar Lite Build Script]ã
(Ant Support)
å¦æä½ å¯§é¡ä½¿ç¨ Ant ä¾å»ºç«ä½ çå¥ä»¶ï¼å¯ä»¥åè sample XML file sent in by Brett Clippingdale. éåæè¿°æªæ該è·å®è£æ¸ å®æ¾ç½®å¨åä¸åç®éï¼ç¶å¾ä½¿ç¨ ant æ令ã
ç¬¬å «ç« ï¼æ¸¬è©¦ (Testing Our Extension)
å¨ç¬¬åç« è¨è«çåæ éç¼å°æ¼å¥ä»¶æ¸¬è©¦æå¾å¤§ç幫å©ï¼ä½æ¯é裡éæä¸äºç« éæ¯éç¼è éè¦ç¥éçãJavaScript æ¯å¾é£é¤é¯ç ï¼å¹¸å¥½ Firefox çä¸äºç¹è²å¯ä»¥è®æåé¿å é£äºæ±äººçè¦ç¤º(æ¤æ alert() å½å¼å¼å«)ã
ç¶ Firefox ææ¯æ該æ麼辦 (What to Do if Firefox Breaks)
ææåå¥ä»¶æç¢çç½é£æ§çé¯èª¤ï¼å°è´ Firefox æçµéåãç¶é種æ æ³ç¼çæï¼ä½ å¿ é å 檢æ¥å·¥ä½ç®¡çå¡æ¯å¦æç¶æç Firefox å¨å·è¡ä¸ï¼ä¸¦æå®ééãä¸æ¦ç¢ºå®æ²æ Firefox å¨å·è¡ï¼ä½ éè¦ç§»é¤æåé¡çå¥ä»¶ã移é¤çæ¹æ³å決æ¼ä½ æ¯å¦æ£å¨ä½¿ç¨åæ éç¼ç³»çµ±ã
å¦æä½ æ£å¨ç¨åæ éç¼ï¼åªè¦ç覽åæ éç¼è¨å®çå¥ä»¶ç®é(第åç« )ï¼ç¶å¾å°å¥ä»¶çææ¨æªæ¡(tuttoolbar@borngeek.com)移åå°æ«åçä½ç½®ãç¨ä½ çåæ éç¼è¨å®æªéæ°éå Firefox (å 許å®æ¸ é¤ææ°ç§»é¤çå¥ä»¶)ï¼ ç¶å¾å次ééç覽å¨ãå¨ä½ 解決éåå°è´ Firefox ç¶æçåé¡ä¹å¾ï¼å°ä½ çææ¨æªæ¡ç§»åå°å¥ä»¶ç®éï¼ç¶å¾éæ°éå Firefox ã
å¦æä½ æ²æ使ç¨åæ éç¼ç話ï¼å°±ç¨ Firefox çå®å ¨æ¨¡å¼ä¾ç§»é¤æåé¡çå¥ä»¶ãä½ å¯ä»¥ç¨å ©ç¨®æ¹å¼ä¾ï¼
- éå§ > ææç¨å¼ > Mozilla Firefox >> Mozilla Firefox (Safe Mode) ã
- å¨ Firefox æ·å¾ä¸å å ¥ -safe-mode å½ä»¤ååæ¸ã
å¨å®å ¨æ¨¡å¼ä¸ï¼ Firefox ä¸æè¼å ¥ä»»ä½å¥ä»¶ææ¯ä¸»é¡ãä¸æ¦å¨å®å ¨æ¨¡å¼ä¸ï¼ä½ å°±å¯ä»¥ä½¿ç¨å¥ä»¶ç®¡çå¡ä¾ç§»é¤æåé¡çå¥ä»¶ãå¨ç§»é¤å¥ä»¶ä¹å¾ï¼è¨å¾å° -safe-mode å½ä»¤ååæ¸ç§»é¤(å¦æä½ å¨æ·å¾ä¸æåå å ¥)ã
æç¨çç覽å¨è¨å® (Useful Browser Settings)
å¨ about:config ä»é¢ä¸ï¼æå ©åè¨å®å¯ä»¥è®ä½ æ´å®¹æéç¼ï¼éæå½±é¿ JavaScript 主æ§å°ç輸åºè¨æ¯ã
第ä¸åè¨å®æ¯ javascript.options.showInConsole ãç¶è¨å®çº true æï¼ææå¥ä»¶ç¢ççé¯èª¤ææ¯è¦åé½æ被å³éå° JavaScript 主æ§å°ãé è¨å¼æ¯ false ï¼ æä»¥ä½ å¿ é éåå®ãéåè¨å®å°æ¼è¿½è¹¤é¯èª¤æ¯å¾æ¹ä¾¿çã
ä¸ä¸åæ¯ javascript.options.strict ï¼é è¨å¼ä¹æ¯ false ãç¶è¨å®çº true æï¼Firefox ç JavaScript èªæ³æè®æå´è¬¹æ¨¡å¼ï¼å°ä½ çç¨å¼ç¢¼è®æå´æ ¼çç´æãéè®ä½ çç¨å¼ç¢¼æ´å®åï¼ä¹æ´å®¹æ追蹤ç¨å¼ç¢¼é¯èª¤ã
JavaScript 主æ§å°ç´é (Logging to the JavaScript Console)
測試 JavaScript ç¨å¼ç¢¼ç好æ¹æ³å°±æ¯å¨ JavaScript 主æ§å°ä¸å°åºé¤é¯å¼ï¼ä½ å¯ä»¥å¨ ãå·¥å · > JavaScript 主æ§å°ãéåãæåå¿ é å å¾å° nsIConsoleService ä»é¢ç實é«(instance)ï¼ä¸é¢æ¯ç¨å¼ç¢¼çç段ï¼
const TutTB_ConsoleService = Components. classes['@mozilla.org/consoleservice;1']. getService(Components.interfaces.nsIConsoleService);
注æå°æåç¨äº TutTB_ çåç½®è©ï¼å°±å¦æ使ç¨æ¼ææå½å¼èè®æ¸ä¸æ¨£ãä¸æ¦æååå¾éåæ§å¶å°å¯¦é«(console instance)ï¼æåå°±å¯ä»¥ä½¿ç¨å®ä¾ç·¨å¯«èªå·±çè¨æ¯ãä¸é¢çå½å¼æ幫æåå®æé件äºï¼
function TutTB_Log(aMessage) { TutTB_ConsoleService.logStringMessage('Tut_Toolbar: ' + aMessage); }
實éä¸ï¼ä½ æ該æ¹è®å¨ä½ çå¥ä»¶ä¸ãMy_Extension:ãçè¨æ¯é¨ä»½å稱ãèç±ä½¿ç¨ä½ çå¥ä»¶å稱ä¾ç¶åç½®è©ï¼ä½ å¯ä»¥æ´å®¹æåå¾åªäºè¨æ¯æ¯è¦ç¥éçãç¾å¨ï¼è®å½å¼ä½ç¨ä¹å¾ï¼æåå¯ä»¥å¨ç¨å¼ç¢¼ä¸çä»»ä¸ä½ç½®ä¾å¼å«å®ï¼ä»¥é¡¯ç¤ºé¤é¯è¨æ¯ï¼
TutTB_Log("The value of the URL variable is: " + URL);
è¨å¾ä¸å®è¦å¨ç¼è¡¨ä½ çå¥ä»¶å移é¤éåå½å¼ãä¸ç¶ï¼éä¸åªæ¯éä½ä¸»æ§å°ç´éçé度ï¼éå¢å äºä½¿ç¨è 主æ§å°è¦çªçéå¿ è¦è¨æ¯ãè¦æ´é²ä¸æ¥å°äºè§£ JavaScript 主æ§å°ï¼å¯ä»¥åè MozillaZine knowledge base article ã
æ¨æºä¸»æ§å°ç´é (Logging to the Standard Console)
å¦ä¸åç´éé¤é¯è³è¨çæ¹æ³ï¼å°±æ¯ä½¿ç¨æ¨æºä¸»æ§å°çæå·§ãå¨ä½¿ç¨éåæ¹æ³ä¹åï¼æä¸äºç覽å¨çä¿®æ¹å¿ é è¦å å®æãé¦å ï¼æåå¿ é å å ¥æ°çç覽å¨è¨å®ï¼å¨ç¶²ååè¼¸å ¥ about:config ï¼ä¸¦æä¸ Enter ãå³éµé»æå表並é¸æ ãæ°å¢ > çåå¼(Boolean)ãä¾å»ºç«ä¸åæ°çå¸æå¼è¨å®ãå°éåå¼è¨å®çº browser.dom.window.dump.enabled ï¼ä¸¦åç¨å®(true)ã
ä¸ä¸æ¥ï¼æ¯å¨ Firefox æ·å¾ä¸å å ¥ -console å½ä»¤å串ã使ç¨éååæ¸ï¼æä½ æ¯æ¬¡å·è¡ Firefox æï¼é¡¯ç¤ºæ¨æºè¼¸åºä¸»æ§å°ãä¸ä½éé å®æå¾ï¼ Firefox ä¹éåäºï¼ä»»ä½èç± dump() å½å¼ç¢çç輸åºï¼é½æ顯示å¨ä¸»æ§å°è¦çªä¸ãdump()å½å¼å°±å¦ JavaScript æ¨æºç alert() å½å¼ä¸æ¨£ï¼èªæ³ä¹ç¸ä¼¼ã
æ件ç©ä»¶æ¨¡å檢æ¥å¨ (The DOM Inspector)
å°æ¼è¨è¨å·¥å ·åæ大ç幫å©å°±æ¯ DOM (Document Object Model) Inspector ï¼éæ¯ä¸åå¯ä»¥è®ä½ æª¢æ¥ XML æ件(å å« XUL, HTML)çµæ§çå·¥å ·ãéåå·¥å ·è· Firefox å è£å¨ä¸èµ·ï¼ä½æ¯é è¨æ¯ä¸å®è£çï¼ä½ å¿ é 使ç¨é²éå®è£ä¾å®è£éåå·¥å ·ãä¸æ¦å¯ä»¥ä½¿ç¨æï¼å°±ææè±å¯çè³è¨å¯ä»¥ç²å¾ï¼æä»¥ä½ è¦å å¸æå¦ä½ä½¿ç¨å®ã
å¨ä¸äºç¶²é å¯ä»¥æ¾å°é樣çä»ç´¹ï¼
- The DOM Inspector (from Creating Applications with Mozilla)
- DOM Inspector FAQ
éæ¯å¹«å©æåå°æ¾ XUL è¨è¨åé¡çæå¥½å·¥å ·ï¼å®å¯ä»¥è®ä½ 檢è¦å¤å XUL å ç´ çèªæ³ãæå¼·ç建è°ä½ å»å¸ç¿å¦ä½ä½¿ç¨éåå·¥å ·ï¼éé»ç¸ç¶å®¹æï¼èä¸ä½ æå°æ¼å¸æ使ç¨éé å·¥å ·æå°é常å°é«èã
‧返回上一頁: éç¼äººå¡æ件主é