|
1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 var gLanguagesDialog = { |
|
7 |
|
8 _availableLanguagesList : [], |
|
9 _acceptLanguages : { }, |
|
10 |
|
11 _selectedItemID : null, |
|
12 |
|
13 init: function () |
|
14 { |
|
15 if (!this._availableLanguagesList.length) |
|
16 this._loadAvailableLanguages(); |
|
17 }, |
|
18 |
|
19 get _activeLanguages() |
|
20 { |
|
21 return document.getElementById("activeLanguages"); |
|
22 }, |
|
23 |
|
24 get _availableLanguages() |
|
25 { |
|
26 return document.getElementById("availableLanguages"); |
|
27 }, |
|
28 |
|
29 _loadAvailableLanguages: function () |
|
30 { |
|
31 // This is a parser for: resource://gre/res/language.properties |
|
32 // The file is formatted like so: |
|
33 // ab[-cd].accept=true|false |
|
34 // ab = language |
|
35 // cd = region |
|
36 var bundleAccepted = document.getElementById("bundleAccepted"); |
|
37 var bundleRegions = document.getElementById("bundleRegions"); |
|
38 var bundleLanguages = document.getElementById("bundleLanguages"); |
|
39 var bundlePreferences = document.getElementById("bundlePreferences"); |
|
40 |
|
41 function LanguageInfo(aName, aABCD, aIsVisible) |
|
42 { |
|
43 this.name = aName; |
|
44 this.abcd = aABCD; |
|
45 this.isVisible = aIsVisible; |
|
46 } |
|
47 |
|
48 // 1) Read the available languages out of language.properties |
|
49 var strings = bundleAccepted.strings; |
|
50 while (strings.hasMoreElements()) { |
|
51 var currString = strings.getNext(); |
|
52 if (!(currString instanceof Components.interfaces.nsIPropertyElement)) |
|
53 break; |
|
54 |
|
55 var property = currString.key.split("."); // ab[-cd].accept |
|
56 if (property[1] == "accept") { |
|
57 var abCD = property[0]; |
|
58 var abCDPairs = abCD.split("-"); // ab[-cd] |
|
59 var useABCDFormat = abCDPairs.length > 1; |
|
60 var ab = useABCDFormat ? abCDPairs[0] : abCD; |
|
61 var cd = useABCDFormat ? abCDPairs[1] : ""; |
|
62 if (ab) { |
|
63 var language = ""; |
|
64 try { |
|
65 language = bundleLanguages.getString(ab); |
|
66 } |
|
67 catch (e) { continue; }; |
|
68 |
|
69 var region = ""; |
|
70 if (useABCDFormat) { |
|
71 try { |
|
72 region = bundleRegions.getString(cd); |
|
73 } |
|
74 catch (e) { continue; } |
|
75 } |
|
76 |
|
77 var name = ""; |
|
78 if (useABCDFormat) |
|
79 name = bundlePreferences.getFormattedString("languageRegionCodeFormat", |
|
80 [language, region, abCD]); |
|
81 else |
|
82 name = bundlePreferences.getFormattedString("languageCodeFormat", |
|
83 [language, abCD]); |
|
84 |
|
85 if (name && abCD) { |
|
86 var isVisible = currString.value == "true" && |
|
87 (!(abCD in this._acceptLanguages) || !this._acceptLanguages[abCD]); |
|
88 var li = new LanguageInfo(name, abCD, isVisible); |
|
89 this._availableLanguagesList.push(li); |
|
90 } |
|
91 } |
|
92 } |
|
93 } |
|
94 this._buildAvailableLanguageList(); |
|
95 }, |
|
96 |
|
97 _buildAvailableLanguageList: function () |
|
98 { |
|
99 var availableLanguagesPopup = document.getElementById("availableLanguagesPopup"); |
|
100 while (availableLanguagesPopup.hasChildNodes()) |
|
101 availableLanguagesPopup.removeChild(availableLanguagesPopup.firstChild); |
|
102 |
|
103 // Sort the list of languages by name |
|
104 this._availableLanguagesList.sort(function (a, b) { |
|
105 return a.name.localeCompare(b.name); |
|
106 }); |
|
107 |
|
108 // Load the UI with the data |
|
109 for (var i = 0; i < this._availableLanguagesList.length; ++i) { |
|
110 var abCD = this._availableLanguagesList[i].abcd; |
|
111 if (this._availableLanguagesList[i].isVisible && |
|
112 (!(abCD in this._acceptLanguages) || !this._acceptLanguages[abCD])) { |
|
113 var menuitem = document.createElement("menuitem"); |
|
114 menuitem.id = this._availableLanguagesList[i].abcd; |
|
115 availableLanguagesPopup.appendChild(menuitem); |
|
116 menuitem.setAttribute("label", this._availableLanguagesList[i].name); |
|
117 } |
|
118 } |
|
119 }, |
|
120 |
|
121 readAcceptLanguages: function () |
|
122 { |
|
123 while (this._activeLanguages.hasChildNodes()) |
|
124 this._activeLanguages.removeChild(this._activeLanguages.firstChild); |
|
125 |
|
126 var selectedIndex = 0; |
|
127 var preference = document.getElementById("intl.accept_languages"); |
|
128 if (preference.value == "") |
|
129 return undefined; |
|
130 var languages = preference.value.toLowerCase().split(/\s*,\s*/); |
|
131 for (var i = 0; i < languages.length; ++i) { |
|
132 var name = this._getLanguageName(languages[i]); |
|
133 if (!name) |
|
134 name = "[" + languages[i] + "]"; |
|
135 var listitem = document.createElement("listitem"); |
|
136 listitem.id = languages[i]; |
|
137 if (languages[i] == this._selectedItemID) |
|
138 selectedIndex = i; |
|
139 this._activeLanguages.appendChild(listitem); |
|
140 listitem.setAttribute("label", name); |
|
141 |
|
142 // Hash this language as an "Active" language so we don't |
|
143 // show it in the list that can be added. |
|
144 this._acceptLanguages[languages[i]] = true; |
|
145 } |
|
146 |
|
147 if (this._activeLanguages.childNodes.length > 0) { |
|
148 this._activeLanguages.ensureIndexIsVisible(selectedIndex); |
|
149 this._activeLanguages.selectedIndex = selectedIndex; |
|
150 } |
|
151 |
|
152 return undefined; |
|
153 }, |
|
154 |
|
155 writeAcceptLanguages: function () |
|
156 { |
|
157 return undefined; |
|
158 }, |
|
159 |
|
160 onAvailableLanguageSelect: function () |
|
161 { |
|
162 var addButton = document.getElementById("addButton"); |
|
163 addButton.disabled = false; |
|
164 |
|
165 this._availableLanguages.removeAttribute("accesskey"); |
|
166 }, |
|
167 |
|
168 addLanguage: function () |
|
169 { |
|
170 var selectedID = this._availableLanguages.selectedItem.id; |
|
171 var preference = document.getElementById("intl.accept_languages"); |
|
172 var arrayOfPrefs = preference.value.toLowerCase().split(/\s*,\s*/); |
|
173 for (var i = 0; i < arrayOfPrefs.length; ++i ){ |
|
174 if (arrayOfPrefs[i] == selectedID) |
|
175 return; |
|
176 } |
|
177 |
|
178 this._selectedItemID = selectedID; |
|
179 |
|
180 if (preference.value == "") |
|
181 preference.value = selectedID; |
|
182 else { |
|
183 arrayOfPrefs.unshift(selectedID); |
|
184 preference.value = arrayOfPrefs.join(","); |
|
185 } |
|
186 |
|
187 this._acceptLanguages[selectedID] = true; |
|
188 this._availableLanguages.selectedItem = null; |
|
189 |
|
190 // Rebuild the available list with the added item removed... |
|
191 this._buildAvailableLanguageList(); |
|
192 |
|
193 this._availableLanguages.setAttribute("label", this._availableLanguages.getAttribute("label2")); |
|
194 }, |
|
195 |
|
196 removeLanguage: function () |
|
197 { |
|
198 // Build the new preference value string. |
|
199 var languagesArray = []; |
|
200 for (var i = 0; i < this._activeLanguages.childNodes.length; ++i) { |
|
201 var item = this._activeLanguages.childNodes[i]; |
|
202 if (!item.selected) |
|
203 languagesArray.push(item.id); |
|
204 else |
|
205 this._acceptLanguages[item.id] = false; |
|
206 } |
|
207 var string = languagesArray.join(","); |
|
208 |
|
209 // Get the item to select after the remove operation completes. |
|
210 var selection = this._activeLanguages.selectedItems; |
|
211 var lastSelected = selection[selection.length-1]; |
|
212 var selectItem = lastSelected.nextSibling || lastSelected.previousSibling; |
|
213 selectItem = selectItem ? selectItem.id : null; |
|
214 |
|
215 this._selectedItemID = selectItem; |
|
216 |
|
217 // Update the preference and force a UI rebuild |
|
218 var preference = document.getElementById("intl.accept_languages"); |
|
219 preference.value = string; |
|
220 |
|
221 this._buildAvailableLanguageList(); |
|
222 }, |
|
223 |
|
224 _getLanguageName: function (aABCD) |
|
225 { |
|
226 if (!this._availableLanguagesList.length) |
|
227 this._loadAvailableLanguages(); |
|
228 for (var i = 0; i < this._availableLanguagesList.length; ++i) { |
|
229 if (aABCD == this._availableLanguagesList[i].abcd) |
|
230 return this._availableLanguagesList[i].name; |
|
231 } |
|
232 return ""; |
|
233 }, |
|
234 |
|
235 moveUp: function () |
|
236 { |
|
237 var selectedItem = this._activeLanguages.selectedItems[0]; |
|
238 var previousItem = selectedItem.previousSibling; |
|
239 |
|
240 var string = ""; |
|
241 for (var i = 0; i < this._activeLanguages.childNodes.length; ++i) { |
|
242 var item = this._activeLanguages.childNodes[i]; |
|
243 string += (i == 0 ? "" : ","); |
|
244 if (item.id == previousItem.id) |
|
245 string += selectedItem.id; |
|
246 else if (item.id == selectedItem.id) |
|
247 string += previousItem.id; |
|
248 else |
|
249 string += item.id; |
|
250 } |
|
251 |
|
252 this._selectedItemID = selectedItem.id; |
|
253 |
|
254 // Update the preference and force a UI rebuild |
|
255 var preference = document.getElementById("intl.accept_languages"); |
|
256 preference.value = string; |
|
257 }, |
|
258 |
|
259 moveDown: function () |
|
260 { |
|
261 var selectedItem = this._activeLanguages.selectedItems[0]; |
|
262 var nextItem = selectedItem.nextSibling; |
|
263 |
|
264 var string = ""; |
|
265 for (var i = 0; i < this._activeLanguages.childNodes.length; ++i) { |
|
266 var item = this._activeLanguages.childNodes[i]; |
|
267 string += (i == 0 ? "" : ","); |
|
268 if (item.id == nextItem.id) |
|
269 string += selectedItem.id; |
|
270 else if (item.id == selectedItem.id) |
|
271 string += nextItem.id; |
|
272 else |
|
273 string += item.id; |
|
274 } |
|
275 |
|
276 this._selectedItemID = selectedItem.id; |
|
277 |
|
278 // Update the preference and force a UI rebuild |
|
279 var preference = document.getElementById("intl.accept_languages"); |
|
280 preference.value = string; |
|
281 }, |
|
282 |
|
283 onLanguageSelect: function () |
|
284 { |
|
285 var upButton = document.getElementById("up"); |
|
286 var downButton = document.getElementById("down"); |
|
287 var removeButton = document.getElementById("remove"); |
|
288 switch (this._activeLanguages.selectedCount) { |
|
289 case 0: |
|
290 upButton.disabled = downButton.disabled = removeButton.disabled = true; |
|
291 break; |
|
292 case 1: |
|
293 upButton.disabled = this._activeLanguages.selectedIndex == 0; |
|
294 downButton.disabled = this._activeLanguages.selectedIndex == this._activeLanguages.childNodes.length - 1; |
|
295 removeButton.disabled = false; |
|
296 break; |
|
297 default: |
|
298 upButton.disabled = true; |
|
299 downButton.disabled = true; |
|
300 removeButton.disabled = false; |
|
301 } |
|
302 } |
|
303 }; |
|
304 |