This document provides an overview and examples of creating user interfaces with XML User Interface Language (XUL) in Mozilla Firefox extensions. It discusses XUL elements like boxes, buttons, menus and layout attributes. Code snippets demonstrate how to use these elements to build interfaces with labels, text boxes, checkboxes and nested menus. The document also explains how JavaScript and CSS can be used to add interactivity and styles to XUL interfaces.
Report
Share
Report
Share
1 of 117
More Related Content
Mozilla Firefox Extension Development, Course 1: Basic
1. Mozilla Firefox
Extension Development
Course 1: Basic
Littlebtc
OSSF Workshop / MozTW Acitivity
The text of the slide is under CC-BY-SA-3.0.
Most photos are under CC-BY-SA compatible license,
while screenshots / logos are under Fair Use.
Code is under MIT license.
2. Note
• This slide is partialy based on Firefox addons
developer guide (CC-BY-SA-2.1JP)
https://developer.mozilla.org/En/Firefox_addons
_developer_guide/
Original authors:
– Hideyuki Emura
– Hiroshi quot;Piroquot; Shimoda
– Taiga Gomibuchi
– Taro Matsuzawa
– Yutaka Kachi
9. Extensions
• One of the “Add-ons”:
– Extensions, Themes, Plugin
• “Extend” your browser
– Provide more features
– Fix some problem
– Integrate with sites or applications
10. Extensions with Single Feature…
• Locationbar2
• Hide Menubar (Made in Taiwan!)
After Press Alt
23. • Rendered by Gecko Engine
XUL • “Write” Interface in an XML
text format
XML User
– Just Like write web pages in
Interface
HTML
Language
• Cross-platform interface
elements
• The idea may be similar to
Adobe’s MXML (Flex) and
THERE IS NO DATA. Microsoft’s XAML (WPF)
THERE IS ONLY XUL.
25. CSS
• It’s true!
• CSS can also modify user interface’s style
• For example: Toolbar icon
26. JavaScript
• It’s true… again!
• Handle the command in the interface
• Almost like what it is on AJAX websites
– XMLHTTPRequest, DOM, …
• But able to access some core API
• ... So it is more dangerous
<script type=“application/x-javascript”>
alert(„Hello World!‟);
</script>
27. XPCOM
• Cross Platform Component Object Model
• The core, or the “black box” of Firefox
• Very similar to Microsoft’s COM
• A cross-platform API that can be extended
• Some API may allow access from JavaScript
28. Above all…
• XPCOM is the “brain”
• XUL is the “skeleton”
• JavaScript is the “muscle”
• CSS is the “skin”
29. Break #1
• Try to Install some extensions on your Firefox!
• And remember to install our tutorial
extensions set
34. Some common attribute
• Identifier: id
• Classes: class
• Style: style, width, height, flex
– We will explain flex later
• disabled=quot;truequot;
– In .NET, it is Enabled=“False” ;p
35. <label>
• <label>
– Attributes
• value
• control (explain later)
• accesskey: Used for Alt+…
<label value=quot;好玩!quot; accesskey=quot;Fquot; />
37. <label>, again
• controls element in <label>:
• When clicking on the specific label,
• will focus on the control with specific id.
<label control=quot;txtquot; value=quot;Comments:quot;/>
<textbox id=quot;txtquot; value=quot;Add texts here!quot;
multiline=quot;truequot; rows=quot;3quot; />
38. <button>
• Attributes
– label
• Beware: <button label=quot;quot; /> but <label value=quot;quot; /> !
– accesskey
– Image
• Events
– oncommand: beware!
(though onclick can be OK, but oncommand is
usually used in XUL)
39. <button> Example
• With a little scripting
<button label=quot;Testquot; accesskey=quot;Squot;
oncommand=quot;alert('hello!');quot; />
40. Layout controls: boxes & flex
• <hbox>: Horizontal Box
• <vbox>: Vertical Box
• <groupbox>: Group Box (can have a <caption>)
• <grid>: Like <table>
• flex (flexibility): An integer attribute in control
elements, which indicates the element in the box
should automatically change its width/height to fit
box/window's size.
– If there is multiple elements, elements with larger flex
values will be larger than ones with lower flex values.
43. Example, again
http://gist.github.com/108791
<label value=quot;Enter Your Name:quot; control=quot;namequot; accesskey=quot;Nquot; />
<textbox id=quot;namequot; value=quot;quot; />
<button label=quot;OKquot;
oncommand=quot;alert('Hello, ' + document.getElementById('name').value + '!');quot; />
44. Script in XUL
<script type=quot;application/x-javascriptquot;>
…
</script>
Will be used widly later
45. Checkbox / Radio
• Common: label/accesskey
• <checkbox>
– checked
• Radio: use a <radiogroup> to contain them
– <radiogroup>
• onselect: Fire when selection changed
• selectedIndex, selectedItem
– <radio>
• selected
• Note: oncommand will fire in a strange time! :
48. Menu: <menupopup>
• Can be used by <menu>, <menulist>,
<toolbarbutton> or <button type=quot;menuquot;>
• Or anything with popup=quot;idquot;
• Or anything with context=quot;idquot;
49. <menupopup> (I)
• In a <menulist>
<hbox>
<label value=quot;Select a Fruit:quot; />
<menulist id=quot;listquot;>
<menupopup>
<menuitem label=quot;Applequot; />
<menuitem label=quot;Bananaquot; />
<menuitem label=quot;Orangequot; />
</menupopup>
</menulist>
</hbox>
50. <menupopup> (II)
• For <button type=quot;menuquot;> :
<button type=quot;menuquot; label=quot;Click on me!quot; >
<menupopup>
<menuitem label=quot;Aboutquot; accesskey=quot;Aquot; />
<menuitem label=quot;Testquot; accesskey=quot;Tquot; />
</menupopup>
</button>
52. More complex
• For Popup / Menu mode:
– <menuitem> can set oncommand to handle the
command
– It can be quot;checkedquot; (like most menu)
• We will see a lot of these later ;)
53. <dialog>
• A quiet different type of window
• Have default buttons!
– <dialog buttons=quot;accept,cancelquot;
buttonlabelaccept=quot;OKquot;
buttonlabelcancel=quot;Cancel!quot;>
– Buttons can be accept, cancel, help, disclosure,
extra1, extra2
• Events: ondialogxxx
56. Scripting: From the very beginning…
<script type=quot;application/x-javascriptquot;>
alert('Hello Scripting in XUL!');
</script>
57. Load / unload
• <window onload=quot;onload()quot; … >
– Good, but sometimes you won't have chance to
modify onload
• <script type=quot;application/x-javascriptquot;>
window.addEventListener('load', onLoad, false);
window.addEventListener('unload', onUnload,
false);
</script>
• Why unload? ==> We usaually need to release
unneeded things
58. So we can…
<script type=quot;application/x-javascriptquot;>
<![CDATA[
window.addEventListener('load', function() {
document.getElementById('Hello').value=quot;Hello
World!quot;;
}, false);
]]>
</script>
<label value=quot;quot; id=quot;Helloquot;/>
61. Some recommended extensions
• Extension Developer:
https://addons.mozilla.org/firefox/addon/743
4
which helps you set up the environment,
doing extension packaging and find something
useful
64. A very simple extension structure
• this-is-a-extension@moztw.org
– install.rdf -- Your Addons info
– chrome.manifest -- Your file paths to register into quot;Chromequot;
– content
• XULs and JSs…
– defaults
• preferences
– skin -- CSS
65. Check our testing extension
• Go
%APPDATA%MozillaFirefoxProfilesxxxxxxxx
.defaultextensionsextension-tutorial-
may09@moztw.org
• Check the install.rdf and chrome.manifest!
67. Explain
• em:id
– identical to the folder name
– Unique ID to your extension
– Can be in Email format or GUID format
• em:version
• em:type
– 2: Extensions
• em:targetApplication
– Set compatible application
– Application can be identified with UUID, which can be also Email
or GUID format. For example:
• Firefox is {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
• Songbird is songbird@songbirdnest.com
68. How about !!@#$%^&?
• L10n?
– Set <em:localized>
• Multiple Applications?
– A lot of <em:targetApplication>
• For details:
https://developer.mozilla.org/en/Install_Manifests
• See a complex example (My NicoFox install.rdf)
http://code.google.com/p/nicofox/source/brows
e/trunk/install.rdf
69. chrome.manifest
content tutorial content/
• First is the quot;instructionsquot;:
content/locale/skin/overlay/# (comment)
deciding what to do
• content instructions:
content packagename paths/to/files/ [flags]
– Will Register paths/to/files in
chrome://packagename/content !
70. chrome.manifest
• locale instruction:
locale packagename localename paths/to/files/ [flags]
– loacle is use to store l10n files, ex:
locale tutorial zh-TW locale/zh-TW/
• skin instruction:
skin packagename skinname paths/to/files/ [flags]
– skin is used to store skin files (CSS/pictures)
skin tutorial classic/1.0 skin/
71. chrome.manifest
• overlay instruction:
overlay chrome://to-be-overlaid chrome://overlay [flags]
– Use for XUL overlays
– quot;ADD SOMETHINGquot; in the existing XUL
– So we can do a lot of things in our browser
window!
• overlay chrome://browser/content/browser.xul
chrome://tutorial/content/overlay.xul
• For more, see:
https://developer.mozilla.org/en/Chrome_Registration
72. Go and see
• chrome://tutorial/content/test.xul
– Do you see a quot;Hello Worldquot; ?
73. Create another profile (optional)
• start quot;quot; quot;%ProgramFiles%Mozilla
Firefoxfirefox.exequot; -no-remote -P dev
– no-remote allows multiple profile at a time
– -P dev means open a “dev” profile
74. Go overlay
Change the browser window
(http://www.flickr.com/photos/ybite/367039657/ CC-BY-SA-2.0 by ybite)
75. At beginning, overlay.xul:
<?xml version=quot;1.0quot;?>
<overlay
xmlns=quot;http://www.mozilla.org/keymaster/ga
tekeeper/there.is.only.xulquot;>
</overlay>
76. You need to know your enemy
• chrome://browser/content/browser.xul
id=quot;main-menubarquot;
id=quot;navigator-
toolbox quot;
id=quot;menu_ToolsPopupquot;
id=quot;status-barquot;
77. Add an item in Tools Menu
<menupopup id=quot;menu_ToolsPopupquot;>
<menuitem label=quot;Hello Extensions!quot;
accesskey=quot;Hquot; oncommand=quot;alert('Hello!');quot;
insertafter=quot;devToolsSeparatorquot; />
</menupopup>
78. How to test?
• After disabling XUL cache, open a new
window and overlay will work
• Or using Extension Developer to Reload All
Chrome (Not suggested)
79. Add Item to the statusbar
<statustoolbar id=quot;status-barquot;>
<statusbarpanel id=quot;tutorial-custom-statusbarquot;
class=quot;statusbarpanel-iconic-textquot;
label=quot;Mybarquot;
tooltiptext=quot;It is my statusbar!quot; hidden=quot;falsequot;
src=quot;chrome://tutorial/skin/sport_basketball.pngquot;
oncommand=quot;alert('Hello!');quot; />
</statustoolbar>
Class:
• statusbarpanel-iconic-text: Icon & text
• statusbarpanel-iconic: Icon only
• statusbarpanel-menu-iconic: icon & popup menu
80. Custom Toolbar Button
or a new Toolbar?
• Custom Toolbar Button:
https://developer.mozilla.org/en/Creating_too
lbar_buttons
• Create a Toolbar:
http://www.borngeek.com/firefox/toolbar-
tutorial/
81. Localization Preparation in XUL
• Before <overlay>:
<!DOCTYPE overlay SYSTEM
quot;chrome://tutorial/locale/tutorial.dtdquot;>
• Add a file zh-TW/tutorial.dtd:
<!ENTITY tutorial.hello quot;我的狀態列quot;>
• Add a file en-US/tutorial.dtd:
<!ENTITY tutorial.hello quot;MyBarquot;>
• Change the overlay.xul:
label=quot;&tutorial.hello;quot;
82. L10n normal tips
• Entities naming:
– xxxxx.label
– xxxxx.accesskey
• Remember to l10n as most as you can
• If your strings consists of variable value, try
JavaScript way (explain later)
83. JavaScript time
Basic JavaScript technique in Extension development
(http://www.flickr.com/photos/nicksieger/280662871/ CC-BY-SA-2.0 by
nicksieger)
84. Review: DOM Tree
previousSibling
firstChild
element
parentNode
lastChild
nextSibling
85. Review: Some Simple DOM
• Find elements
– id: document.getElementById(‘…’)
– class: document.getElementsByClassName(‘…’)
(Support Firefox3+ / Gecko 1.9+ only
Workaround: XPath :D)
• Work with elements
– element.style.xxx;
– element.disabled = true;
– element.setAttribute(‘disabled’, true);
– var value = element.getAttribute(‘value’);
86. Add Script code in our overlay
<script type=quot;application/x-javascriptquot;
src=quot;chrome://tutorial/content/overlay.jsquot; />
• Insert right after <overlay>
87. overlay.js
var moztw_tutorial = {
onLoad: function() {
// Fire when browser window loading
},
onUnload: function() {
// Fire when browser window unloading
}
};
window.addEventListener('load', moztw_tutorial.onLoad, false);
window.addEventListener('unload', moztw_tutorial.onUnload, false);
88. Why use a object to wrap everything?
• The global object may be used by more than 50
extensions (so easy to conflict!)
• So wrap everything in an object is a safe way
• Some better implementations:
– http://blogger.ziesemer.com/2007/10/respecting-
javascript-global-namespace.html
– http://www.softwareishard.com/blog/planet-
mozilla/firefox-extensions-global-namespace-
pollution/
89. Code snippets
• Open a XUL Dialog
window.openDialog('chrome://tutorial/content/test.xul',
'chrome,centerscreen,dialog=no,resizable=yes ');
– chrome: needed for chrome-level window
– dialog=no: needed if it is not a <dialog>
– resizable=yes: can it be resize?
– modal: will it lock the outer window?
• Window size?
– Define it on your XUL window CSS
90. Sending data
• A very complex job!
• There exists some way like using the
window.openDialog to send
• https://developer.mozilla.org/en/Working_wit
h_windows_in_chrome_code
• https://developer.mozilla.org/en/Code_snippe
ts/Interaction_between_privileged_and_non-
privileged_pages
92. Coping with the page
• Can we cope with the our viewing content in
our browser? Yes, But Strictly Limited
93. Getting document of currently
selected tab
• content.document or
gBrowser.selectedBrowser.contentDocument
• So you can modify the content!
• The following code is a little dirty!
fixIt: function() {
if (content.document) {
var h1 = content.document.getElementsByTagName('h1');
if (h1 && h1.length > 0) { h1[0].innerHTML = quot;Testquot;; }
}
}
94. Get JavaScript variable in currently
selected tab
• … Are You sure?
– It can be very dangerous
– And it is very hard
• Try Greasemonkey and understand
unsafeWindow carefully
– It has a compiler to make your userscript an
independent xpi
95. Tab browser related?
• https://developer.mozilla.org/En/Code_snippe
ts/Tabbed_browser
• It has a lot of data, and very useful!
96. XPCOM
• You will be able to use some XPCOM in the
following way:
– Instance:
var file = Components.classes[quot;@mozilla.org/file/local;1quot;].
createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(quot;D:doggy.txtquot;);
– Usually, Cc = Components.classes, Ci = Components.interfaces
– Service:
var bookmarksSvc = Cc[quot;@mozilla.org/browser/nav-bookmarks-
service;1quot;]. getService(Ci.nsINavBookmarksService);
97. What can I do with XPCOM?
• File access: nsILocalFIle
• Cross-site XMLHTTPRequest: nsIXMLHTTPRequest
• Advanced window operations: nsIWindowMediator
• Access places database (Firefox3+ / Gecko 1.9+):
nsINavBookmarksService, nsITaggingService, …
• Access password manager: nsILoginManager (Fx3+/Gecko1.9+)
• Save pages into files: nsIPersist
• Etc…
98. JS l10n ways (I)
• You need a .properties file
• put locale/en-US/tutorial.properties:
hello=Hello World!
• And locale/zh-TW/tutorial.properties:
hello=哈囉世界!
99. JS l10n ways (II)
• In overlay.xul, add:
<stringbundleset id=quot;stringbundlesetquot;>
<stringbundle id=quot;tutorial-bundlequot;
src=quot;chrome://tutorial/locale/tutorial.properti
esquot; />
</stringbundleset>
• Now you can access hello locale in
document.getElementById('tutorial-bundle').getString('hello');
100. Full l10n examples
• I will add two new entities in .dtd (XUL-l10n)
<!ENTITY tutorial.helloMenu.label quot;打聲招呼quot;>
<!ENTITY tutorial.helloMenu.accesskey quot;Hquot;>
• Then, modify the overlay.xul:
<stringbundleset id=quot;stringbundlesetquot;>
<stringbundle id=quot;tutorial-bundlequot;
src=quot;chrome://tutorial/locale/tutorial.propertiesquot; />
</stringbundleset>
And
<menupopup id=quot;menu_ToolsPopupquot;>
<menuitem label=quot;&tutorial.helloMenu.label;quot;
accesskey=quot;&tutorial.helloMenu.accesskey;quot;
oncommand=quot;moztw_tutorial.hello();quot; insertafter=quot;devToolsSeparatorquot; />
</menupopup>
101. Full l10n examples (II)
• Then, the overlay.js:
hello: function() {
alert( document.getElementById('tutorial-
bundle').getString('hello'));
}
102. Example: TagHelper++
• Improve Gomita's TagHelper example
• Make it more easy and accurate
• A complete demo for JavaScript, XUL and
XPCOM!
106. Overlay: JavaScript
onLoad: function() {
// Fire when browser window loading
var contextMenu = document.getElementById(quot;contentAreaContextMenuquot;);
if (contextMenu) {
contextMenu.addEventListener(quot;popupshowingquot;, taghelper2.popupShowing, false);
}
},
popupShowing: function(e) {
var item = document.getElementById(quot;taghelper2-menuitemquot;);
if (gContextMenu.isContentSelected) { // Popup will show when selected
item.hidden = false;
} else {
item.hidden = true;
}
},
107. Overlay: JavaScript (II)
addTags: function() {
// Check selection
var selection = window.content.getSelection();
var texts = [];
for (var i = 0; i < selection.rangeCount; i++) {
var text = selection.getRangeAt(i).toString();
// Trim
text = text.replace(/^s/,'').replace(/s$/,'');
texts.push(text);
}
var text = texts.join(quot;,quot;);
selection.removeAllRanges();
// Open Dialog
var params = {text: text, url: window.content.document.location.href, title:
window.content.document.title};
window.openDialog(quot;chrome://taghelper2/content/taghelper2.xulquot;, quot;quot;,
quot;chrome,centerscreen,modalquot;, params);
}
113. XPI packaging, the easiest way
• Zip your extensions
Make sure install.rdf & chrome.manifest is in
the first level of zip files
• Rename the file to xxx.xpi
• And you are done!
114. Advanced: pack a .jar for chrome files
• File structure:
– chrome
• taghelper2.jar (a zip file)
– content
»…
– locale
»…
– skin
»…
• The correspoding chrome.manifest fix:
before: locale/zh-TW/
after: chrome/taghelper2.jar!/locale/zh-TW/
116. Send it to a public website
• Spread your .xpi file
• Or, use Mozilla Add-ons
– A good add-ons hosting
– Strict review process
– Public extension will have automatically update