Comparar revisiones

Elementos esenciales de una extensión

Change Revisions

Revisión 267180:

Revisión 267180 de camilourd el

Revisión 217921:

Revisión 217921 de camilourd el

Título:
Elementos esenciales de una extensión
Elementos esenciales de una extensión
Enlace amigable (slug):
Escuela_XUL/Elementos_esenciales_de_una_extensión
Escuela_XUL/Elementos_esenciales_de_una_extensión
Contenido:

Revisión 267180
Revisión 217921
t7    <p>t
8      {{ Traducción("inglés", "XUL_School/The_Essentials_of_an_Ex
>tension", "en") }} 
9    </p>
10    <p>
11      {{ PreviousNext("Escuela_XUL/Introducción_a_las_extensiones
>_de_Firefox", "Escuela_XUL/Montando_un_ambiente_de_desarrollo") } 
>} 
12    </p>
13    <h2 id="The_install.rdf_File">
14      The install.rdf File
15    </h2>
16    <p>
17      In the last section we looked at the contents of the Hello 
>World extension. Now we'll look into its files and code, starting 
> with the <em>install.rdf</em> file. You can open it with any tex 
>t editor. 
18    </p>
19    <p>
20      The file is formatted in a special flavor of XML called <a 
>class="external" href="http://en.wikipedia.org/wiki/Resource_Desc 
>ription_Framework">RDF</a>. RDF used to be the central storage me 
>chanism for Firefox, but it is now being replaced for a simpler d 
>atabase system. We'll discuss both of these storage systems furth 
>er ahead in the tutorial. 
21    </p>
22    <p>
23      Now let's look at the important parts of the file.
24    </p>
25    <div class="code panel" style="border-width: 1px;">
26      <div class="codeContent panelContent">
27        <pre class="code-java">
28&lt;em:id&gt;helloworld@xulschool.com&lt;/em:id&gt;
29</pre>
30      </div>
31    </div>
32    <p>
33      This is the unique identifier for the extension. Firefox ne
>eds this to distinguish your extension from other extensions, so  
>it is required that you have an ID that is unique. 
34    </p>
35    <p>
36      There are two accepted standards for add-on ids. One is the
> email-like format in the Hello World example, which should be so 
>mething like <em>&lt;project-name&gt;@&lt;yourdomain&gt;</em>. Th 
>e other standard practice is to use a generated <a class="externa 
>l" href="http://en.wikipedia.org/wiki/Uuid">UUID</a> string, whic 
>h is extremely unlikely to be duplicated. Unix-based systems have 
> a command line tool called <em>uuidgen</em> that generates UUIDs 
>. There are also downloadable tools for all platforms that genera 
>te them. The enclosing brackets are just notation, and they're ju 
>st common practice. As long as your id has some uniqueness to it, 
> it's OK to use either form. 
37    </p>
38    <div class="code panel" style="border-width: 1px;">
39      <div class="codeContent panelContent">
40        <pre class="code-java">
41&lt;em:name&gt;XUL School Hello World&lt;/em:name&gt;
42&lt;em:description&gt;Welcome to XUL School!&lt;/em:description&g
>t; 
43&lt;em:version&gt;0.1&lt;/em:version&gt;
44&lt;em:creator&gt;Appcoast&lt;/em:creator&gt;
45<span class="code-comment">&lt;em:homepageURL&gt;https://develope
>r.mozilla.org/en/XUL_School&lt;/em:homepageURL&gt;</span> 
46</pre>
47      </div>
48    </div>
49    <p>
50      This is the data that is displayed before and after the ext
>ension is installed, that you can see in the Add-ons window. The  
>homepage URL can be visited by right-clicking on the extension an 
>d choosing Visit Home Page. There are many other tags that can be 
> added, for contributors and translators. The <a href="/en/Instal 
>l_Manifests" title="en/Install Manifests">full specification</a>  
>of the install.rdf file has all the details. 
51    </p>
52    <p>
53      Since extensions can be translated to multiple languages, i
>t is often necessary to translate the extension's description, or 
> even its name. On Firefox 3 and above, a localized description a 
>nd name can be added with the following code: 
54    </p>
55    <div class="code panel" style="border-width: 1px;">
56      <div class="codeContent panelContent">
57        <pre class="code-java">
58&lt;em:localized&gt;
59  &lt;Description&gt;
60    &lt;em:locale&gt;es-ES&lt;/em:locale&gt;
61    &lt;em:name&gt;XUL School Hola Mundo&lt;/em:name&gt;
62    &lt;em:description&gt;Bienvenido a XUL School!&lt;/em:descrip
>tion&gt; 
63  &lt;/Description&gt;
64&lt;/em:localized&gt;
65</pre>
66      </div>
67    </div>
68    <p>
69      The <em>es-ES</em> locale string indicates that this is the
> Spanish (es) localization for Spain (ES). You can add as many <e 
>m>&lt;em:localized&gt;</em> sections as you need. For Firefox 2,  
>localizing this file is a <a href="/en/Localizing_extension_descr 
>iptions#Localizing_before_Gecko_1.9" title="en/Localizing extensi 
>on descriptions#Localizing before Gecko 1.9">little more complica 
>ted</a>. We'll discuss localization further ahead in this section 
>. 
70    </p>
71    <div class="code panel" style="border-width: 1px;">
72      <div class="codeContent panelContent">
73        <pre class="code-java">
74&lt;em:type&gt;2&lt;/em:type&gt;
75</pre>
76      </div>
77    </div>
78    <p>
79      This specifies that the add-on being installed is an extens
>ion. You can read about different possible types in the <a href=" 
>/en/Install_Manifests#type" title="en/Install Manifests#type">ins 
>tall.rdf specification</a>. 
80    </p>
81    <div class="code panel" style="border-width: 1px;">
82      <div class="codeContent panelContent">
83        <pre class="code-java">
84&lt;em:targetApplication&gt;
85  &lt;Description&gt;
86    &lt;em:id&gt;{ec8030f7-c20a-464f-9b0e-13a3a9e97384}&lt;/em:id
>&gt; 
87    &lt;em:minVersion&gt;3.0&lt;/em:minVersion&gt;
88    &lt;em:maxVersion&gt;6.0a1&lt;/em:maxVersion&gt;
89  &lt;/Description&gt;
90&lt;/em:targetApplication&gt;
91</pre>
92      </div>
93    </div>
94    <p>
95      This node specifies the target application and target versi
>ons for the extension, specifically Firefox, from version 3.0 up  
>to experimental versions of Firefox 6. The UUID is Firefox's uniq 
>ue ID. Other Mozilla and Mozilla-based applications such as Thund 
>erbird and Seamonkey have their own. You can have an extension th 
>at works on multiple applications and versions. For example, if y 
>ou create a Firefox extension, it would normally take little effo 
>rt to port it to Flock or SeaMonkey, which have very similar feat 
>ures and UI. 
96    </p>
97    <p>
98      The min and max version specify the version range in which 
>the extension can be installed. Here's more about the <a href="/e 
>n/Toolkit_version_format" title="en/Toolkit version format">versi 
>on format</a>. If the application or version range don't match, y 
>ou won't be allowed to install the extension, or the extension wi 
>ll be installed in a disabled state. Users can disable version ch 
>ecks through preferences or installing add-ons like the <a class= 
>"link-https" href="https://addons.mozilla.org/en-US/firefox/addon 
>/15003" title="https://addons.mozilla.org/en-US/firefox/addon/150 
>03">Add-on Compatibility Reporter</a>. 
99    </p>
100    <p>
101      This is all the information Firefox and other Mozilla appli
>cations need to install an add-on. Any errors or missing informat 
>ion will cause the installation process to fail, or the extension 
> to be installed in a disabled state. 
102    </p>
103    <h2 id="The_chrome.manifest_File">
104      The chrome.manifest File
105    </h2>
106    <blockquote>
107      <p>
108        Chrome is the set of user interface elements of the appli
>cation window that are outside of a window's content area. Toolba 
>rs, menu bars, progress bars, and window title bars are all examp 
>les of elements that are typically part of the chrome. 
109      </p>
110    </blockquote>
111    <p>
112      Taken from <a href="/en/Chrome_Registration" title="en/Chro
>me Registration">Chrome Registration</a>. 
113    </p>
114    <p>
115      In other words, the chrome is everything you see in Firefox
>. All Firefox windows can be seen as having two parts: (1) the ch 
>rome and (2) possibly a content area, like the one that displays  
>web pages in a Firefox tab. Windows like the Add-ons Manager and  
>the Downloads window are pure chrome. Most of the code for an ext 
>ension resides in the chrome folder, just like in the Hello World 
> example. 
116    </p>
117    <p>
118      Chrome files are all packaged in a JAR archive, usually nam
>ed after the extension. It is not required to package chrome file 
>s, but it is a common practice and recommended for performance re 
>asons. 
119    </p>
120    <p>
121      As we saw in the directory structure of the unpacked extens
>ion, the chrome is composed of 3 sections: content, locale and sk 
>in. The 3 are necessary for most extensions. If we open the <em>c 
>hrome.manifest</em> file (again, any text editor will do), we see 
> that the same 3 sections are mentioned: 
122    </p>
123    <div class="code panel" style="border-width: 1px;">
124      <div class="codeContent panelContent">
125        <pre class="code-java">
126content   xulschoolhello              jar:chrome/xulschoolhello.j
>ar!/content/ 
127skin      xulschoolhello  classic/1.0 jar:chrome/xulschoolhello.j
>ar!/skin/ 
128locale    xulschoolhello  en-US       jar:chrome/xulschoolhello.j
>ar!/locale/en-US/ 
129</pre>
130      </div>
131    </div>
132    <p>
133      The <em>chrome.manifest</em> file tells Firefox where to lo
>ok for chrome files. The text is spaced to look like a table, but 
> that is not necessary. The parser will ignore repeated spaces. 
134    </p>
135    <p>
136      The first word in a line tells Firefox what it is that is b
>eing declared (content, skin, locale, or others we will see later 
> on). The second is the package name, which we will explain short 
>ly. Skin and locale packages have a third value to specify what l 
>ocale or what skin they are extending. There can be multiple skin 
> and locale entries relating to different skins and locales. The  
>most common case is having one skin entry for the global skin, <e 
>m>classic/1.0</em>, and multiple locale entries, one for each tra 
>nslation. Finally, the location is specified. Notice the <em>jar: 
></em> scheme; it tells Firefox to look into the JAR file and read 
> the files from the right path. If you want to have an extension  
>with an unpacked chrome directory, you only need to change the pa 
>ths to something like <em>chrome/content/</em>. 
137    </p>
138    <p>
139      There are some additional options that can be included in t
>he entries of a <em>chrome.manifest</em> file. They are documente 
>d in the <a href="/en/Chrome_Registration" title="en/Chrome Regis 
>tration">Chrome Registration</a> page. Notably, we can have entri 
>es that are OS-specific. This is important, specially in Firefox  
>3 and above, where the appearance of the browser is very differen 
>t for each operating system. If our extension needed to look diff 
>erently on the major systems, we could change the manifest file s 
>o that it includes this: 
140    </p>
141    <div class="code panel" style="border-width: 1px;">
142      <div class="codeContent panelContent">
143        <pre class="code-java">
144content   xulschoolhello              jar:chrome/xulschoolhello.j
>ar!/content/ 
145skin      xulschoolhello  classic/1.0 jar:chrome/xulschoolhello.j
>ar!/skin/unix/ 
146skin      xulschoolhello  classic/1.0 jar:chrome/xulschoolhello.j
>ar!/skin/mac/ os=Darwin 
147skin      xulschoolhello  classic/1.0 jar:chrome/xulschoolhello.j
>ar!/skin/win/ os=WinNT 
148locale    xulschoolhello  en-US       jar:chrome/xulschoolhello.j
>ar!/locale/en-US/ 
149</pre>
150      </div>
151    </div>
152    <p>
153      This way we can have separate skins for Windows, Mac OS X, 
>and Linux (plus other unix-like systems), each defined in a separ 
>ate directory. Since most other systems are Unix-based, the "unix 
>" skin is the default, with no flags. 
154    </p>
155    <h2 id="The_Chrome">
156      The Chrome
157    </h2>
158    <p>
159      As mentioned earlier, the chrome is composed of 3 sections:
> content, locale and skin. The content is the most important sect 
>ion, holding user interface (XUL) and script (JS) files. The skin 
> section has the files that define most of the look and feel of t 
>he UI (using CSS and images, just like web pages). Finally, the l 
>ocale section holds all text used in the extension, in DTD and pr 
>operties files. This division allows other developers to create t 
>hemes that replace skins, and translators to create localizations 
> in different languages, all of this without having to change you 
>r extension or your code. This gives Firefox extensions a great d 
>eal of flexibility. 
160    </p>
161    <p>
162      Chrome files are accessed through the chrome protocol. Chro
>me URIs are defined like so: 
163    </p>
164    <div class="code panel" style="border-width: 1px;">
165      <div class="codeContent panelContent">
166        <pre class="code-java">
167chrome:<span class="code-comment">//packagename/section/path/to/f
>ile</span> 
168</pre>
169      </div>
170    </div>
171    <p>
172      So, for instance, if I want to access the file <span style=
>"font-style: italic;">b</span><em>rowserOverlay.xul</em> in the e 
>xtension, the chrome URI would be <em><a class=" external" href=" 
>chrome://xulschoolhello/content/browserOverlay.xul" rel="freelink 
>">chrome://xulschoolhello/content/browserOverlay.xul</a></em>. If 
> you have too many files in the content and you want to organize  
>them in subdirectories, there's nothing you need to change in <em 
>>chrome.manifest</em>, all you need is to add the right path afte 
>r <em>content</em> in the URI. Skin and locale files work in the  
>same way, and you don't need to specify skin names or locale name 
>s. So, to access the DTD file in the Hello World extension, the c 
>hrome path is <em><a class=" external" href="chrome://xulschoolhe 
>llo/locale/browserOverlay.dtd" rel="freelink">chrome://xulschoolh 
>ello/locale/browserOverlay.dtd</a></em>. Firefox knows what local 
>e to look for. 
173    </p>
174    <p>
175      Here's an interesting experiment. Open a new Firefox tab, t
>ype <em><a class=" external" href="chrome://mozapps/content/downl 
>oads/downloads.xul" rel="freelink">chrome://mozapps/content/downl 
>oads/downloads.xul</a></em> on your location bar and press ENTER. 
> Surprised? You just opened the Downloads window in a Firefox tab 
>! You can access any chrome file by just typing its URI in the lo 
>cation bar. This can come in handy if you want to inspect script  
>files that are part of Firefox, other extensions, or your own. Mo 
>st of these files are opened as text files, with the exception of 
> XUL files, which are executed and displayed like you would norma 
>lly see them on a window. 
176    </p>
177    <h3 id="Content">
178      Content
179    </h3>
180    <p>
181      There are 2 files in the content directory. Let's look at t
>he XUL file first. 
182    </p>
183    <p>
184      <a href="/en/XUL" title="en/XUL">XUL</a> files are XML file
>s that define the user interface elements in Firefox and Firefox  
>extensions. XUL was inspired by HTML, so you'll see many similari 
>ties between the two. However, XUL is also an improvement over HT 
>ML, having learned from many of the mistakes made during the evol 
>ution of HTML. XUL allows you to create richer and more interacti 
>ve interfaces than the ones you can create with HTML, or at least 
> XUL makes it easier. 
185    </p>
186    <p>
187      XUL files usually define one of two things: windows or over
>lays. The file you opened before, <em>downloads.xul</em>, has the 
> code that defines the Downloads window. The XUL file included in 
> the Hello World extension is an overlay. An overlay extends an e 
>xisting window, adding new elements to it or replacing some of th 
>e elements in it. The line that we skipped in the <em>chrome.mani 
>fest</em> file states that this XUL file is an overlay for the ma 
>in browser window: 
188    </p>
189    <div class="code panel" style="border-width: 1px;">
190      <div class="codeContent panelContent">
191        <pre class="code-java">
192overlay chrome:<span class="code-comment">//browser/content/brows
>er.xul  chrome://xulschoolhello/content/browserOverlay.xul</span> 
193</pre>
194      </div>
195    </div>
196    <p>
197      With this line, Firefox knows that it needs to take the con
>tents of <em>browserOverlay.xul</em> and overlay it on the main b 
>rowser window, <em>browser.xul</em>. You can declare overlays for 
> any window or dialog in Firefox, but overlaying the main browser 
> window is the most common case by far. 
198    </p>
199    <p>
200      Now let's look at the contents of our XUL file. We'll skip 
>the first few lines because they relate to skin and locale, which 
> we'll cover later. 
201    </p>
202    <div class="code panel" style="border-width: 1px;">
203      <div class="codeContent panelContent">
204        <pre class="code-java">
205&lt;overlay id="xulschoolhello-browser-overlay"
206  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.onl
>y.xul"&gt; 
207</pre>
208      </div>
209    </div>
210    <p>
211      The root element in the file is an <em>overlay</em>. Other 
>XUL documents use the <em>window</em> or <em>dialog</em> tag. The 
> element has a unique id, which you should have on most elements  
>in your XUL. The second attribute is the namespace, which is some 
>thing you should always define in your XUL root element. It says  
>that this node and all child nodes are XUL. You only need to chan 
>ge namespace declarations when you combine different types of con 
>tent, such as XUL with HTML or SVG. 
212    </p>
213    <div class="panel" style="border-width: 1px;">
214      <div class="panelContent">
215        <div class="note">
216          You may have noticed the naming we use on several place
>s, such as the id <em>xulschoolhello-browser-overlay</em>. This i 
>s the namespacing standard that we use to avoid conflicts with Fi 
>refox and other extensions, as well as making some development ta 
>sks easier. We namespace all ids and style classes in overlay ele 
>ments because they will be mixed with other elements in the main  
>browser window. If we used generic ids like <em>container</em> or 
> <em>input</em>, they will likely conflict with ids used within F 
>irefox, or with ids from other extension overlays. Using namespac 
>es minimizes compatibility problems with other extensions. We use 
> camel casing for file names, and all lower case with dashes for  
>element ids and CSS style class names. 
217        </div>
218      </div>
219    </div>
220    <div class="code panel" style="border-width: 1px;">
221      <div class="codeContent panelContent">
222        <pre class="code-java">
223&lt;script type=<span class="code-quote">"application/x-javascrip
>t"</span> 
224  src=<span class="code-quote">"chrome:<span class="code-comment"
>>//xulschoolhello/content/browserOverlay.js"</span> /&gt;</span> 
225</pre>
226      </div>
227    </div>
228    <p>
229      Just like in HTML, this includes a JavaScript script file. 
>You can have as many <em>script</em> elements on a XUL file as yo 
>u need. We'll look into its code later. 
230    </p>
231    <div class="panel" style="border-width: 1px;">
232      <div class="panelContent">
233        <div class="note">
234          You also probably noticed how we format our code, and w
>onder about the rules we follow. Our general rule on line length  
>is not having lines longer than 80 characters. This feels very re 
>strictive, specially with XML files, but the number was chosen to 
> allow pretty much any text editor to handle these files easily.  
>Even old command line editors work well with files that cut their 
> lines at 80 characters. The tabulation is very straightforward:  
>2 blank space indents. We never use actual tab characters, with t 
>he exception of Makefiles, which will be covered later on. Most o 
>f our coding standards are based on Mozilla's or other known and  
>used standards. 
235        </div>
236      </div>
237    </div>
238    <p>
239      &nbsp;We'll skip some code that is covered in the locale se
>ction, moving on to the most important part of the content: 
240    </p>
241    <div class="code panel" style="border-width: 1px;">
242      <div class="codeContent panelContent">
243        <pre class="code-java">
244&lt;menubar id="main-menubar"&gt;
245  &lt;menu id="xulschoolhello-hello-menu" label="&amp;xulschoolhe
>llo.hello.label;" 
246    accesskey="&amp;xulschoolhello.helloMenu.accesskey;" insertaf
>ter="helpMenu"&gt; 
247    &lt;menupopup&gt;
248      &lt;menuitem id="xulschoolhello-hello-menu-item"
249        label="&amp;xulschoolhello.hello.label;"
250        accesskey="&amp;xulschoolhello.helloItem.accesskey;"
251        oncommand="XULSchoolChrome.BrowserOverlay.sayHello(event)
>;" /&gt; 
252    &lt;/menupopup&gt;
253  &lt;/menu&gt;
254&lt;/menubar&gt;
255</pre>
256      </div>
257    </div>
258    <p>
259      This is the code that adds the Hello World menu to the brow
>ser window. In order to write this code, we needed some knowledge 
> of the XUL code in <em>browser.xul</em>. We needed to know that  
>the id of the main menu is <em>main-menubar</em>. We're adding a  
>menu of our own, and telling Firefox to add it in the main menu b 
>ar, right after the Help menu. That's the purpose of the attribut 
>e: 
260    </p>
261    <div class="code panel" style="border-width: 1px;">
262      <div class="codeContent panelContent">
263        <pre class="code-java">
264insertafter=<span class="code-quote">"helpMenu"</span>
265</pre>
266      </div>
267    </div>
268    <p>
269      <em>helpMenu</em> is the id of the menu element that corres
>ponds to the Help menu in the main menu of the browser. We'll see 
> later how we can find out things like the ids of browser element 
>s, but for now let's look at the elements that compose the Hello  
>World menu. 
270    </p>
271    <p>
272      The <a href="/en/XUL/menubar" title="en/XUL/menubar">menuba
>r</a> element represents the menu bar you normally see at the top 
> of an application window. The main Firefox window has one, but f 
>ew of its other windows do. It's also rare for additional extensi 
>on windows to have their own menu bars. 
273    </p>
274    <p>
275      We added the Hello World menu right in the "root" of the me
>nu bar so that it would be very easy for you to spot it, but this 
> is not a recommended practice. Imagine if all extensions added m 
>enus to the top menu bar; having a few extensions would make the  
>menu look like an airplane dashboard, full of options. The recomm 
>ended location for extension menus is under the <em>Tools</em> me 
>nu, so the code should really look like this: 
276    </p>
277    <div class="code panel" style="border-width: 1px;">
278      <div class="codeContent panelContent">
279        <pre class="code-java">
280&lt;menupopup id=<span class="code-quote">"menu_ToolsPopup"</span
>>&gt; 
281  &lt;menu id=<span class="code-quote">"xulschoolhello-hello-menu
>"</span> label=<span class="code-quote">"&amp;</span><span class= 
>"code-quote">xulschoolhello</span><span class="code-quote">.hello 
>.label;"</span> 
282    accesskey=<span class="code-quote">"&amp;</span><span class="
>code-quote">xulschoolhello</span><span class="code-quote">.helloM 
>enu.accesskey;"</span> 
283    insertafter=<span class="code-quote">"javascriptConsole,devTo
>olsSeparator"</span>&gt; 
284    &lt;menupopup&gt;
285      &lt;menuitem id=<span class="code-quote">"</span><span clas
>s="code-quote">xulschoolhello</span><span class="code-quote">-hel 
>lo-menu-item" 
286      </span>  label=<span class="code-quote">"&amp;</span><span 
>class="code-quote">xulschoolhello</span><span class="code-quote"> 
>.hello.label;"</span> 
287        accesskey=<span class="code-quote">"&amp;</span><span cla
>ss="code-quote">xulschoolhello</span><span class="code-quote">.he 
>lloItem.accesskey;"</span> 
288        oncommand=<span class="code-quote">"XULSchoolChrome.Brows
>erOverlay.sayHello(event);"</span> /&gt; 
289    &lt;/menupopup&gt;
290  &lt;/menu&gt;
291&lt;/menupopup&gt;
292</pre>
293      </div>
294    </div>
295    <p>
296      We're overlaying a menu that is deeper into the XUL tree, b
>ut it doesn't matter because all we need is the id of the element 
> we want to overlay. In this case it is the <a href="/en/XUL/menu 
>popup" title="en/XUL/menupopup">menupopup</a> element that's insi 
>de of the Tools <a href="/en/XUL/menu" title="en/XUL/menu">menu</ 
>a> element. The <em>insertafter</em> attribute tells Firefox to a 
>dd the menu below the Error Console item (formerly known as JavaS 
>cript Console) in the Tools menu, just like recommended in the <a 
> href="/en/Extensions/Extension_etiquette" title="en/Extension Et 
>iquette"><span class="external">Extension Etiquette page</span></ 
>a>. We'll discuss more about menus later on in the tutorial. For  
>now let's focus on the following line: 
297    </p>
298    <div class="code panel" style="border-width: 1px;">
299      <div class="codeContent panelContent">
300        <pre class="code-java">
301oncommand=<span class="code-quote">"XULSchoolChrome.BrowserOverla
>y.sayHello(event);"</span> 
302</pre>
303      </div>
304    </div>
305    <p>
306      This attribute defines an event handler. The <em>command</e
>m> event is the most frequently used in Firefox, since it corresp 
>onds to the main action for most UI elements.&nbsp;The value of t 
>he attribute is JavaScript code that invokes a function. This fun 
>ction is defined in the JS file that was included with the <em>sc 
>ript</em> tag. The JS function will be called once the user click 
>s on the menu item in the Hello World menu. All event handlers de 
>fine a special object named <em>event</em>, which is usually good 
> to pass as an argument to the function. Event handlers are expla 
>ined in greater depth further ahead. 
307    </p>
308    <p>
309      Now let's look at the JavaScript file and see what's going 
>on when the event is fired. 
310    </p>
311    <div class="code panel" style="border-width: 1px;">
312      <div class="codeContent panelContent">
313        <pre class="brush: js">
314/**
315 * XULSchoolChrome namespace.
316 */
317if ("undefined" == typeof(XULSchoolChrome)) {
318  var XULSchoolChrome = {};
319};
320</pre>
321      </div>
322    </div>
323    <p>
324      The <em>XULSchoolChrome</em> namespace is defined. All obje
>cts and variables we define in this JavaScript are global, meanin 
>g that scripts in Firefox and other extensions can see them and i 
>nteract with them. This also means that if we define an object ca 
>lled <em>MenuHandler</em> or some other generic name, it's likely 
> going to conflict with an existing object. What we do here is de 
>fine a single global object: <em>XULSchoolChrome</em>. Now we kno 
>w that all of our objects are inside this object, which is unlike 
>ly to be duplicated or overwritten by other extensions. 
325    </p>
326    <p>
327      You can read more about the <a href="/en/JavaScript/Referen
>ce/Operators/Special/typeof" title="en/Core JavaScript 1.5 Refere 
>nce/Operators/Special Operators/typeof Operator"><span class="ext 
>ernal">typeof operator</span></a>. If you're unfamiliar with Java 
>Script or this particular syntax, initializing an object as <em>{ 
>}</em> is the equivalent of initializing it to <em>new Object()</ 
>em>. 
328    </p>
329    <div class="code panel" style="border-width: 1px;">
330      <div class="codeContent panelContent">
331        <pre class="brush: js">
332/**
333 * Controls the browser overlay <span class="code-keyword">for</s
>pan> the Hello World extension. 
334 */
335XULSchoolChrome.BrowserOverlay = {
336</pre>
337      </div>
338    </div>
339    <p>
340      Finally, <em>BrowserOverlay</em> is our object. Naming and 
>referencing&nbsp; objects in such a long and verbose manner can f 
>eel uncomfortable at first, but it's worth the cost. 
341    </p>
342    <div class="panel" style="border-width: 1px;">
343      <div class="panelContent">
344        <div class="note">
345          We use <a class="external" href="http://java.sun.com/j2
>se/javadoc/writingdoccomments/index.html">Javadoc</a> style comme 
>nts on all namespaces, objects and object members. This is a simi 
>lar standard to the one used in Mozilla code, and some tools can  
>generate documentation automatically from Javadoc. 
346        </div>
347      </div>
348    </div>
349    <div class="code panel" style="border-width: 1px;">
350      <div class="codeContent panelContent">
351        <pre class="brush: js">
352sayHello : function(aEvent) {
353  let stringBundle = document.getElementById("xulschoolhello-stri
>ng-bundle"); 
354  let message = stringBundle.getString("xulschoolhello.greeting.l
>abel"); 
355 
356  window.alert(message);
357}
358</pre>
359      </div>
360    </div>
361    <p>
362      And, finally, this is our function declaration. Three lines
> of code are all we need for it to work. The first line in the bo 
>dy of the function declares a variable that will hold the <a href 
>="/en/XUL/stringbundle" title="en/XUL/stringBundle">stringbundle< 
>/a> element defined in the overlay. The variable is declared usin 
>g <em>let,</em> which is similar to <em>var</em> but with more re 
>stricted scope. Here you can read more about <a href="/en/JavaScr 
>ipt/New_in_JavaScript/1.7#Block_scope_with_let" title="en/New in  
>JavaScript 1.7#Block scope with let"><span class="external">let d 
>eclarations</span></a>. It's worth noting that this is a relative 
>ly new addition to JavaScript in Firefox and you should use <em>v 
>ar</em> if you're creating an extension compatible with very old  
>versions. 
363    </p>
364    <p>
365      Just like in regular JS, we can use the <a href="/en/DOM" t
>itle="en/DOM"><span class="external">DOM</span></a> (Document Obj 
>ect Model) in order to manipulate the XUL document. First we get  
>a reference of the <a href="/en/XUL/stringbundle" title="en/XUL/s 
>tringbundle"><span class="external">stringbundle element</span></ 
>a> in the document. This is a special element that allows us to o 
>btain localized strings dynamically, by only providing a "key" th 
>at identifies the string. This is what we do on the second line.  
>We call the <a href="/en/XUL/stringbundle#m-getString" title="en/ 
>XUL/stringbundle#m-getString">getString method</a> of the bundle  
>element and get the localized message to be displayed. We then ca 
>ll the <a href="/en/DOM/window.alert" title="en/DOM/window.alert" 
>>window.alert</a> function with the message, just like we would d 
>o in an HTML document. 
366    </p>
367    <h3 id="Locale">
368      Locale
369    </h3>
370    <p>
371      There are two types of locale files: DTD and properties, an
>d in this example we use them both. DTD is the most efficient way 
> of showing text in XUL, so you should use it whenever possible.  
>It is somewhat inflexible so it can't be used for dynamically gen 
>erated text, hence the need for an alternate way of getting local 
>ized strings. 
372    </p>
373    <p>
374      Looking back at the menu code, you probably noticed some at
>tributes such as this: 
375    </p>
376    <div class="code panel" style="border-width: 1px;">
377      <div class="codeContent panelContent">
378        <pre class="code-java">
379label=<span class="code-quote">"&amp;xulschoolhello.hello.label;"
></span> accesskey=<span class="code-quote">"&amp;xulschoolhello.h 
>elloItem.accesskey;"</span> 
380</pre>
381      </div>
382    </div>
383    <p>
384      These attributes define the text that you see on the menus,
> and they are string keys that are defined in our DTD file, <em>b 
>rowserOverlay.dtd</em>. The DTD file was included in the XUL file 
> with the following code: 
385    </p>
386    <div class="code panel" style="border-width: 1px;">
387      <div class="codeContent panelContent">
388        <pre class="code-java">
389&lt;!DOCTYPE overlay SYSTEM "chrome://xulschoolhello/locale/brows
>erOverlay.dtd" &gt; 
390</pre>
391      </div>
392    </div>
393    <p>
394      And in the DTD file you can see the association between key
>s and localized strings: 
395    </p>
396    <div class="code panel" style="border-width: 1px;">
397      <div class="codeContent panelContent">
398        <pre class="code-java">
399&lt;!ENTITY xulschoolhello.hello.label            <span class="co
>de-quote">"Hello World!"</span>&gt; 
400&lt;!ENTITY xulschoolhello.helloMenu.accesskey    <span class="co
>de-quote">"l"</span>&gt; 
401&lt;!ENTITY xulschoolhello.helloItem.accesskey    <span class="co
>de-quote">"H"</span>&gt; 
402</pre>
403      </div>
404    </div>
405    <p>
406      Notice that on the XUL file you enclose the string key with
> <em>&amp;</em> and <em>;</em> while on the DTD file you only spe 
>cify the key. You may get weird parsing errors or incorrect local 
>ization if you don't get it right. 
407    </p>
408    <p>
409      Access keys are the shortcuts that allow you to quickly nav
>igate a menu using only the keyboard. They are also the only way  
>to navigate a menu for people with accessibility problems, such a 
>s partial or total blindness, or physical disabilities that make  
>using a mouse very difficult or impossible. You can easily recogn 
>ize the access keys on Windows because the letter that correspond 
>s to the access key is underlined, as in the following image: 
410    </p>
411    <div align="center">
412      <p>
413        <img alt="" class="internal" src="../../../../@api/deki/f
>iles/4226/=accesskeys.png" style="width: 167px; height: 58px;"> 
414      </p>
415    </div>
416    <p>
417      Most user interface controls have the <em>accesskey</em> at
>tribute, and you should use it. The value of the access key is lo 
>calized because it should match a letter in the label text. You s 
>hould also be careful to avoid access key repetition. For example 
>, within a menu or submenu, access keys should not be repeated. I 
>n a window you have to be more careful picking access keys becaus 
>e there are usually more controls there. You have to be specially 
> careful when picking access keys on an overlay. In our case, we  
>can't use the letter "H" as an accesskey in the Main menu item, b 
>ecause it would be the same as the access key in the Help menu. S 
>ame goes with "W" and the Window menu on Mac OS. So we settled on 
> the letter "l". 
418    </p>
419    <p>
420      DTD strings are resolved and set when the document is being
> loaded. If you request the <em>label</em> attribute value for th 
>e Hello World menu using DOM, you get the localized string, not t 
>he string key. You cannot dynamically change an attribute value w 
>ith a new DTD key, you have to set the new value directly: 
421    </p>
422    <div class="code panel" style="border-width: 1px;">
423      <div class="codeContent panelContent">
424        <pre class="brush: js">
425let helloItem = document.getElementById(<span class="code-quote">
>"xulschoolhello-hello-menu-item"</span>); 
426 
427<span class="code-comment">// The alert will say <span class="cod
>e-quote">"Hello World!"</span> 
428</span>alert(helloItem.getAttribute(<span class="code-quote">"lab
>el"</span>)); 
429<span class="code-comment">// Wrong
430</span>helloItem.setAttribute(<span class="code-quote">"label"</s
>pan>, <span class="code-quote">"&amp;</span><span class="code-quo 
>te">xulschoolhello</span><span class="code-quote">.hello2.label;" 
></span>); 
431<span class="code-comment">// Better
432</span>helloItem.setAttribute(<span class="code-quote">"label"</s
>pan>, <span class="code-quote">"Alternate message"</span>); 
433<span class="code-comment">// Right!
434</span>helloItem.setAttribute(<span class="code-quote">"label"</s
>pan>, someStringBundle.getString(<span class="code-quote">"</span 
>><span class="code-quote">xulschoolhello</span><span class="code- 
>quote">.hello2.label"</span>)); 
435</pre>
436      </div>
437    </div>
438    <p>
439      This is the reason DTD strings are not a solution for all l
>ocalization cases, and the reason we often need to include string 
> bundles in XUL files: 
440    </p>
441    <div class="code panel" style="border-width: 1px;">
442      <div class="codeContent panelContent">
443        <pre class="code-java">
444&lt;stringbundleset id="stringbundleset"&gt;
445  &lt;stringbundle id="xulschoolhello-string-bundle"
446    src="chrome://xulschoolhello/locale/browserOverlay.properties
>" /&gt; 
447&lt;/stringbundleset&gt;
448</pre>
449      </div>
450    </div>
451    <p>
452      The <a href="/en/XUL/stringbundleset" title="en/XUL/stringb
>undleset">stringbundleset</a> element is just a container for <a  
>href="/en/XUL/stringbundle" title="en/XUL/stringbundle">stringbun 
>dle</a> elements. There should only be one per document, which is 
> the reason why we overlay the <em>stringbundleset</em> that is i 
>n <em>browser.xul</em>, hence the very generic id. We don't inclu 
>de the <em>insertbefore</em> or <em>insertafter</em> attributes b 
>ecause the ordering of string bundles doesn't make a difference.  
>The element is completely invisible. If you don't include any of  
>those ordering attributes in an overlay element, Firefox will jus 
>t append your element as the last child of the parent element. 
453    </p>
454    <p>
455      All you need for the string bundle is an id (to be able to 
>fetch the element later) and the chrome path to the properties fi 
>le. And, of course, you need the properties file: 
456    </p>
457    <div class="code panel" style="border-width: 1px;">
458      <div class="codeContent panelContent">
459        <pre class="code-java">
460xulshoolhello.greeting.label = Hi! How are you?
461</pre>
462      </div>
463    </div>
464    <p>
465      The whitespace around the equals sign is ignored. Just like
> in <em>install.rdf</em>, comments can be added using the # chara 
>cter at the beginning of the line. Empty lines are ignored as wel 
>l. 
466    </p>
467    <p>
468      You will often want to include dynamic content as part of l
>ocalized strings, like when you want to inform the user about som 
>e stat related to the extension. For example: "Found 5 words matc 
>hing the search query". Your first idea would probably be to simp 
>ly concatenate strings, and have one "Found" property and another 
> "words matching..." property. This is not a good idea. It greatl 
>y complicates the work of localizers, and grammar rules on differ 
>ent languages may change the ordering of the sentence entirely. F 
>or this reason it's better to use parameters in the properties: 
469    </p>
470    <div class="code panel" style="border-width: 1px;">
471      <div class="codeContent panelContent">
472        <pre class="code-java">
473xulshoolhello.search.label = Found %S words matching the search q
>uery! 
474</pre>
475      </div>
476    </div>
477    <p>
478      Then you use <a href="/en/XUL/stringbundle#m-getFormattedSt
>ring" title="en/XUL/stringbundle#m-getFormattedString">getFormatt 
>edString</a> instead of <em>getString</em> in order to get the lo 
>calized string. Thanks to this we don't need to have multiple pro 
>perties, and life is easier for translators. You can read more ab 
>out it on the <a href="/en/XUL_Tutorial/Property_Files#Text_Forma 
>tting" title="en/XUL Tutorial/Property Files#Text Formatting">Tex 
>t Formatting section</a> of the XUL Tutorial. Also have a look at 
> the <a href="/en/Localization_and_Plurals" title="en/Localizatio 
>n and Plurals">Plurals and Localization</a> article, that covers  
>a new localization feature in Firefox 3 that allows you to furthe 
>r refine this last example to handle different types of plural fo 
>rms that are also language-dependent. 
479    </p>
480    <h3 id="Skin">
481      Skin
482    </h3>
483    <p>
484      Styling XUL is very similar to styling HTML. We'll look int
>o some of the differences when we cover the XUL Box Model, and ot 
>her more advanced topics. There isn't much styling you can do to  
>a minimal menu and a very simple alert message, so the Hello Worl 
>d extension only includes an empty CSS file and the compulsory gl 
>obal skin file: 
485    </p>
486    <div class="code panel" style="border-width: 1px;">
487      <div class="codeContent panelContent">
488        <pre class="code-java">
489&lt;?xml-stylesheet type=<span class="code-quote">"text/css"</spa
>n> href=<span class="code-quote">"chrome:<span class="code-commen 
>t">//global/skin/"</span>  ?&gt; 
490</span>&lt;?xml-stylesheet type=<span class="code-quote">"text/cs
>s"</span>  
491  href=<span class="code-quote">"chrome:<span class="code-comment
>">//xulschoolhello/skin/browserOverlay.css"</span>  ?&gt;</span> 
492</pre>
493      </div>
494    </div>
495    <p>
496      The global skin CSS file holds the default styles for all X
>UL elements and windows. Forgetting to include this file in a XUL 
> window usually leads to interesting and often unwanted results.  
>In our case we don't really need to include it, since we're overl 
>aying the main browser XUL file, and that file already includes t 
>his global CSS. At any rate it's better to always include it. Thi 
>s way it's harder to make the mistake of not including it. You ca 
>n enter the chrome path in the location bar and inspect the file  
>if you're curious. 
497    </p>
498    <p>
499      This covers all of the files in the Hello World extension. 
>Now you should have an idea of the basics involved in extension d 
>evelopment, so now we'll jump right in and set up a development e 
>nvironment. But first, a little exercise. 
500    </p>
501    <h2 id="Exercise">
502      Exercise
503    </h2>
504    <p>
505      Change the welcome message that is displayed in the alert w
>indow and move the Hello World menu to the Tools Menu, where it b 
>elongs. Repackage the XPI and re-install it. You can just drag th 
>e XPI file to the browser and it will be installed locally. Test  
>it and verify your changes worked. If you run into problems at in 
>stallation, it's likely that you didn't reproduce the XPI structu 
>re correctly, maybe adding unnecessary folders. Note that on Fire 
>fox 4 and above, on Windows and some Linux distributions, the Too 
>ls menu is hidden by default. It can be enabled using the Alt key 
>. 
506    </p>
507    <p>
508      Once you're done, you can look at this reference solution: 
><a href="/@api/deki/files/5141/=xulschoolhello2.xpi" title="https 
>://developer.mozilla.org/@api/deki/files/5141/=xulschoolhello2.xp 
>i">Hello World 2</a>. 
509    </p>
510    <p>
511      {{ PreviousNext("Escuela_XUL/Introducción_a_las_extensiones
>_de_Firefox", "Escuela_XUL/Montando_un_ambiente_de_desarrollo") } 
>} 
512    </p>
513    <p>
514      <span style="font-size: small;">This tutorial was kindly do
>nated to Mozilla by Appcoast.</span> 
515    </p>

Volver al historial