r80485 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r80484‎ | r80485 | r80486 >
Date:01:24, 18 January 2011
Author:dale
Status:deferred
Tags:
Comment:
basic response to startup module and more complete stubs for other cache elements
Modified paths:
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/DefaultSettings.php (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/Hooks.php (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedAutoLoader.php (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedMediaWikiGlobalFunctions.php (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedMediaWikiStubs.php (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedResourceLoader.php (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedResourceLoaderFileModule.php (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedResourceLoaderStartUpModule.php (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedWebStart.php (deleted) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedWebStartSetup.php (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/WebRequest.php (deleted) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/libs (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/libs/CSSJanus.php (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/libs/CSSMin.php (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/libs/JSMin.php (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/libs/README (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/resourceloader/ResourceLoader.php (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/resourceloader/ResourceLoaderFileModule.php (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/resourceloader/ResourceLoaderModule.php (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/resourceloader/ResourceLoaderStartUpModule.php (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/load.php (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/loader.js (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MediaWikiSupport/README (modified) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MediaWikiSupport/mwEmbed.i18n.php (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MediaWikiSupport/mwEmbed.js (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/mwEmbed.i18n.php (deleted) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/mwEmbed.js (deleted) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/MwEmbedSharedResources.php (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/Resources.php (deleted) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki.action (deleted) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki.language/mediawiki.language.parser.js (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki.language/mediawiki.language.parserTest.js (added) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki.special (deleted) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki.util (deleted) (history)
  • /branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki/mediawiki.js (modified) (history)

Diff [purge]

Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/mwEmbed.i18n.php
@@ -1,738 +0,0 @@
2 -<?php
3 -/**
4 - * Localization file for mwEmbed.js
5 - */
6 -
7 -$messages = array();
8 -
9 -$messages['en'] = array(
10 - 'mwe-loading_txt' => 'Loading ...',
11 - 'mwe-size-gigabytes' => '$1 GB',
12 - 'mwe-size-megabytes' => '$1 MB',
13 - 'mwe-size-kilobytes' => '$1 K',
14 - 'mwe-size-bytes' => '$1 B',
15 - 'mwe-error_load_lib' => 'Error: JavaScript $1 was not retrievable or does not define $2',
16 - 'mwe-apiproxy-setup' => 'Setting up API proxy',
17 - 'mwe-load-drag-item' => 'Loading dragged item',
18 - 'mwe-ok' => 'OK',
19 - 'mwe-cancel' => 'Cancel',
20 - 'mwe-enable-gadget' => 'Enable multimedia beta (mwEmbed) for all pages',
21 - 'mwe-enable-gadget-done' => 'Multimedia beta gadget has been enabled',
22 - 'mwe-must-login-gadget' => 'To enable gadget you must <a target="_new" href="$1">login</a>',
23 - 'mwe-test-plural' => 'I ran {{PLURAL:$1|$1 test|$1 tests}}',
24 -);
25 -
26 -/** Message documentation (Message documentation)
27 - * @author EugeneZelenko
28 - * @author Fryed-peach
29 - * @author Nike
30 - */
31 -$messages['qqq'] = array(
32 - 'mwe-loading_txt' => '{{Identical|Loading}}',
33 - 'mwe-size-gigabytes' => 'Size (of a file, typically) in gibibytes (1 gibibyte = 1024×1024×1024 bytes).',
34 - 'mwe-error_load_lib' => 'Parameters:
35 -* $1 Corresponds to the JavaScript file that was not retrievable or does not define its class name.
36 -* $2 Is the class name that was associated with the JavaScript file that was not found or could not be retrieved.',
37 - 'mwe-ok' => '{{Identical|OK}}',
38 - 'mwe-cancel' => '{{Identical|Cancel}}',
39 -);
40 -
41 -/** Afrikaans (Afrikaans)
42 - * @author Naudefj
43 - */
44 -$messages['af'] = array(
45 - 'mwe-loading_txt' => 'laai ...',
46 - 'mwe-error_load_lib' => 'Fout: JavaScript $1 kon nie gevind word of definieer nie $2 nie',
47 - 'mwe-ok' => 'OK',
48 - 'mwe-cancel' => 'Kanselleer',
49 -);
50 -
51 -/** Gheg Albanian (Gegë)
52 - * @author Mdupont
53 - */
54 -$messages['aln'] = array(
55 - 'mwe-loading_txt' => 'Loading ...',
56 - 'mwe-error_load_lib' => 'Gabim: $1 JavaScript nuk ishte shikohen ose nuk define $2',
57 - 'mwe-apiproxy-setup' => 'Ngritja proxy API',
58 - 'mwe-load-drag-item' => 'Loading zvarritur artikull',
59 - 'mwe-ok' => 'Në rregull',
60 - 'mwe-cancel' => 'Anuloj',
61 - 'mwe-enable-gadget' => 'Aktivizo multimedial beta (mwEmbed) për të gjitha faqet',
62 - 'mwe-enable-gadget-done' => 'Multimedia beta vegël ka qenë i aktivizuar',
63 -);
64 -
65 -/** Aragonese (Aragonés)
66 - * @author Juanpabl
67 - */
68 -$messages['an'] = array(
69 - 'mwe-cancel' => 'Cancelar',
70 -);
71 -
72 -/** Arabic (العربية)
73 - * @author OsamaK
74 - */
75 -$messages['ar'] = array(
76 - 'mwe-loading_txt' => 'يحمل...',
77 - 'mwe-cancel' => 'ألغِ',
78 -);
79 -
80 -/** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца))
81 - * @author EugeneZelenko
82 - * @author Jim-by
83 - */
84 -$messages['be-tarask'] = array(
85 - 'mwe-loading_txt' => 'загрузка …',
86 - 'mwe-error_load_lib' => 'Памылка: JavaScript $1 не даступны альбо не вызначае $2',
87 - 'mwe-apiproxy-setup' => 'Устаноўка API-проксі',
88 - 'mwe-load-drag-item' => 'Загрузка перанесенага элемэнту',
89 - 'mwe-ok' => 'Добра',
90 - 'mwe-cancel' => 'Адмяніць',
91 - 'mwe-enable-gadget' => 'Уключыць бэта-мультымэдыя (mwEmbed) для ўсіх старонак',
92 - 'mwe-enable-gadget-done' => 'Дапаўненьне бэта-мультымэтыя ўключанае',
93 - 'mwe-must-login-gadget' => 'Для ўключэньня дапаўненьня Вам неабходна <a target="_new" href="$1">ўвайсьці ў сыстэму</a>',
94 - 'mwe-test-plural' => 'Я прайшоў $1 {{PLURAL:$1|тэст|тэсты|тэстаў}}',
95 -);
96 -
97 -/** Breton (Brezhoneg)
98 - * @author Fohanno
99 - * @author Fulup
100 - * @author Y-M D
101 - */
102 -$messages['br'] = array(
103 - 'mwe-loading_txt' => 'o kargañ...',
104 - 'mwe-error_load_lib' => "Fazi : n'eo ket bet kavet JavaScript $1 pe n'eo ket termenet gant $2",
105 - 'mwe-apiproxy-setup' => 'Kefluniadur ar proksi API',
106 - 'mwe-load-drag-item' => 'O kargañ an elfenn digargañ',
107 - 'mwe-ok' => 'Mat eo',
108 - 'mwe-cancel' => 'Nullañ',
109 - 'mwe-enable-gadget' => 'Gweredekaat liesvedia beta (mwEmbed) war an holl bajennoù',
110 - 'mwe-enable-gadget-done' => 'Gweredekaet eo bet ar gadjet liesvedia beta',
111 - 'mwe-must-login-gadget' => 'Evit gweredekaat ar gadjet e rankit <a target="_new" href="$1">kevreañ</a>',
112 - 'mwe-test-plural' => 'Sevenet em eus $1 amprouadenn{{PLURAL:$1||}}',
113 -);
114 -
115 -/** Bosnian (Bosanski)
116 - * @author CERminator
117 - */
118 -$messages['bs'] = array(
119 - 'mwe-loading_txt' => 'učitavam ...',
120 - 'mwe-apiproxy-setup' => 'Postavljanje API proksija',
121 - 'mwe-ok' => 'U redu',
122 - 'mwe-cancel' => 'Odustani',
123 -);
124 -
125 -/** Czech (Česky)
126 - * @author Mormegil
127 - */
128 -$messages['cs'] = array(
129 - 'mwe-loading_txt' => 'Načítá se …',
130 - 'mwe-cancel' => 'Storno',
131 -);
132 -
133 -/** Welsh (Cymraeg) */
134 -$messages['cy'] = array(
135 - 'mwe-loading_txt' => "wrthi'n llwytho ...",
136 -);
137 -
138 -/** German (Deutsch)
139 - * @author Kghbln
140 - * @author Metalhead64
141 - */
142 -$messages['de'] = array(
143 - 'mwe-loading_txt' => 'lade …',
144 - 'mwe-error_load_lib' => 'Fehler: JavaScript $1 war nicht abrufbar oder lässt $2 nicht zu',
145 - 'mwe-apiproxy-setup' => 'API-Proxy-Konfiguration',
146 - 'mwe-load-drag-item' => 'Lade eingebettetes Element',
147 - 'mwe-ok' => 'OK',
148 - 'mwe-cancel' => 'Abbrechen',
149 - 'mwe-enable-gadget' => 'Aktiviere die Beta-Version des Multimedia-Helferleins (mwEmbed) für alle Seiten',
150 - 'mwe-enable-gadget-done' => 'Beta-Version des Multimedia-Helferleins wurde aktiviert',
151 - 'mwe-must-login-gadget' => 'Um das Helferlein aktivieren zu können, musst du dich <a target="_new" href="$1">anmelden</a>',
152 - 'mwe-test-plural' => '{{PLURAL:$1|$1 Test|$1 Tests}} durchlaufen',
153 -);
154 -
155 -/** Zazaki (Zazaki)
156 - * @author Aspar
157 - */
158 -$messages['diq'] = array(
159 - 'mwe-loading_txt' => 'bar beno...',
160 - 'mwe-error_load_lib' => 'xeta: $1 JavaScript re nêresiyeno ya zi pê $2yi şınasnaye niyo.',
161 - 'mwe-apiproxy-setup' => 'proxyê APIyi eyar beno',
162 - 'mwe-load-drag-item' => 'unsur bar beno',
163 - 'mwe-ok' => 'temam',
164 - 'mwe-cancel' => 'iptal',
165 -);
166 -
167 -/** Lower Sorbian (Dolnoserbski)
168 - * @author Michawiki
169 - */
170 -$messages['dsb'] = array(
171 - 'mwe-loading_txt' => 'zacytujo se ...',
172 - 'mwe-error_load_lib' => 'Zmólka: JavaScript $1 njejo wótwołujobny był abo njedefiněrujo $2',
173 - 'mwe-apiproxy-setup' => 'Proksy API zarědowaś',
174 - 'mwe-load-drag-item' => 'Wlecony zapisk se zacytujo',
175 - 'mwe-ok' => 'W pórědku',
176 - 'mwe-cancel' => 'Pśetergnuś',
177 - 'mwe-enable-gadget' => 'Multimedia beta (mwEmbed) za wšykne boki zmóžniś',
178 - 'mwe-enable-gadget-done' => 'Pśisłušk Multimedia beta jo se zmóžnił',
179 - 'mwe-must-login-gadget' => 'Aby pśisłušk zmóžnił, musyš se <a target="_new" href="$1">pśizjawiś</a>',
180 - 'mwe-test-plural' => 'Som {{PLURAL:$1|$1 test|$1 testa|$1 testy|$1 testow}} pśewjadł',
181 -);
182 -
183 -/** Greek (Ελληνικά)
184 - * @author Crazymadlover
185 - */
186 -$messages['el'] = array(
187 - 'mwe-loading_txt' => 'φόρτωση ...',
188 - 'mwe-cancel' => 'Ακύρωση',
189 -);
190 -
191 -/** Esperanto (Esperanto)
192 - * @author Yekrats
193 - */
194 -$messages['eo'] = array(
195 - 'mwe-loading_txt' => 'ŝarĝante ...',
196 - 'mwe-cancel' => 'Nuligi',
197 -);
198 -
199 -/** Spanish (Español)
200 - * @author Translationista
201 - */
202 -$messages['es'] = array(
203 - 'mwe-loading_txt' => 'cargando ...',
204 - 'mwe-error_load_lib' => 'Error: JavaScript $1 no ha podido ser recuperado o no define $2',
205 - 'mwe-apiproxy-setup' => 'Configurando proxi de la API',
206 - 'mwe-load-drag-item' => 'Cargando el objeto arrastrado',
207 - 'mwe-ok' => 'OK',
208 - 'mwe-cancel' => 'Cancelar',
209 - 'mwe-enable-gadget' => 'Habilitar multimedia beta (mwEmbed) en todas las páginas',
210 - 'mwe-enable-gadget-done' => 'Se ha habilitado el gadget multimedia beta',
211 - 'mwe-must-login-gadget' => 'Para habilitar el gadget debes <a target="_new" href="$1">ingresar</a>',
212 - 'mwe-test-plural' => 'Realicé {{PLURAL:$1|$1 prueba|$1 pruebas}}',
213 -);
214 -
215 -/** Basque (Euskara)
216 - * @author An13sa
217 - */
218 -$messages['eu'] = array(
219 - 'mwe-loading_txt' => 'Kargatzen ...',
220 - 'mwe-ok' => 'Ados',
221 - 'mwe-cancel' => 'Ezeztatu',
222 -);
223 -
224 -/** Finnish (Suomi)
225 - * @author Crt
226 - * @author Str4nd
227 - */
228 -$messages['fi'] = array(
229 - 'mwe-loading_txt' => 'Ladataan...',
230 - 'mwe-error_load_lib' => 'Virhe: JavaScript $1 ei ollut haettavissa tai se ei määrittele luokkaa $2',
231 - 'mwe-apiproxy-setup' => 'Pystytetään API-välityspalvelinta',
232 - 'mwe-ok' => 'OK',
233 - 'mwe-cancel' => 'Peruuta',
234 - 'mwe-must-login-gadget' => 'Sinun tulee <a target="_new" href="$1">kirjautua sisään</a>, jotta voisit käyttää pienoisohjelmaa',
235 - 'mwe-test-plural' => 'Ajoin {{PLURAL:$1|$1 testin|$1 testiä}}',
236 -);
237 -
238 -/** French (Français)
239 - * @author IAlex
240 - * @author Jean-Frédéric
241 - * @author PieRRoMaN
242 - */
243 -$messages['fr'] = array(
244 - 'mwe-loading_txt' => 'chargement ...',
245 - 'mwe-error_load_lib' => "Erreur : JavaScript $1 n'a pas pu être trouvé ou ne définit pas $2",
246 - 'mwe-apiproxy-setup' => 'Configuration du proxy API',
247 - 'mwe-load-drag-item' => 'Chargement de l’élément dépose',
248 - 'mwe-ok' => 'OK',
249 - 'mwe-cancel' => 'Annuler',
250 - 'mwe-enable-gadget' => 'Activer beta multimédia (mwEmbed) sur toutes les pages',
251 - 'mwe-enable-gadget-done' => 'Le gadget multimédia beta a été activé',
252 - 'mwe-must-login-gadget' => 'Afin d\'activer le gadget vous devez vous <a target="_new" href="$1">connecter</a>',
253 - 'mwe-test-plural' => "J'ai exécuté {{PLURAL:$1|$1 test|$1 tests}}",
254 -);
255 -
256 -/** Galician (Galego)
257 - * @author Toliño
258 - */
259 -$messages['gl'] = array(
260 - 'mwe-loading_txt' => 'cargando...',
261 - 'mwe-error_load_lib' => 'Erro: o JavaScript $1 non se puido atopar ou non definía $2',
262 - 'mwe-apiproxy-setup' => 'Configurando o proxy API',
263 - 'mwe-load-drag-item' => 'Cargando o elemento arrastrado',
264 - 'mwe-ok' => 'De acordo',
265 - 'mwe-cancel' => 'Cancelar',
266 - 'mwe-enable-gadget' => 'Activar a beta multimedia (mwEmbed) en todas as páxinas',
267 - 'mwe-enable-gadget-done' => 'Activouse o trebello beta multimedia',
268 - 'mwe-must-login-gadget' => 'Para activar o trebello ten que <a target="_new" href="$1">acceder ao sistema</a>',
269 - 'mwe-test-plural' => '{{PLURAL:$1|Fíxose unha proba|Fixéronse $1 probas}}',
270 -);
271 -
272 -/** Swiss German (Alemannisch)
273 - * @author Als-Holder
274 - */
275 -$messages['gsw'] = array(
276 - 'mwe-loading_txt' => 'Am Lade ...',
277 - 'mwe-error_load_lib' => 'Fähler: s JavaScript $1 het nit chenne glade wäre oder s losst $2 nit zue',
278 - 'mwe-apiproxy-setup' => 'API-Proxy-Konfiguration',
279 - 'mwe-load-drag-item' => 'Am Lade vu mitgschleipfte Poschte',
280 - 'mwe-ok' => 'OK',
281 - 'mwe-cancel' => 'Abbräche',
282 - 'mwe-enable-gadget' => 'D Beta-Version vum Multimedia-Heälferli (mwEmbed) fir alli Syte aktiviere',
283 - 'mwe-enable-gadget-done' => 'Beta-Version vum Multimedia-Hälferli isch aktiviert wore',
284 - 'mwe-must-login-gadget' => 'Go s Hälferli aktiviere chenne, muesch di <a target="_new" href="$1">aamälde</a>',
285 - 'mwe-test-plural' => '{{PLURAL:$1|$1 Tescht|$1 Tescht}} uusgfiert',
286 -);
287 -
288 -/** Hausa (هَوُسَ) */
289 -$messages['ha'] = array(
290 - 'mwe-cancel' => 'Soke',
291 -);
292 -
293 -/** Hebrew (עברית)
294 - * @author Rotemliss
295 - */
296 -$messages['he'] = array(
297 - 'mwe-loading_txt' => 'בטעינה ...',
298 - 'mwe-error_load_lib' => 'שגיאה: לא ניתן היה לטעון את ספריית ה־JavaScript בשם $1 או שהיא אינה מגדירה את $2',
299 -);
300 -
301 -/** Upper Sorbian (Hornjoserbsce)
302 - * @author Michawiki
303 - */
304 -$messages['hsb'] = array(
305 - 'mwe-loading_txt' => 'začituje so ...',
306 - 'mwe-size-gigabytes' => '$1 GB',
307 - 'mwe-size-megabytes' => '$1 MB',
308 - 'mwe-size-kilobytes' => '$1 KB',
309 - 'mwe-size-bytes' => '$1 B',
310 - 'mwe-error_load_lib' => 'Zmylk: JavaScript $1 njeda so wotwołać abo njedefinuje $2',
311 - 'mwe-apiproxy-setup' => 'Proksy API zarjadować',
312 - 'mwe-load-drag-item' => 'Wlečeny zapisk so začituje',
313 - 'mwe-ok' => 'W porjadku',
314 - 'mwe-cancel' => 'Přetorhnyć',
315 - 'mwe-enable-gadget' => 'Multimedia beta (mwEmbed) za wšě strony zmóžnić',
316 - 'mwe-enable-gadget-done' => 'Přisłušk za Multimedia beta je so zmóžnił',
317 - 'mwe-must-login-gadget' => 'Zo by přisłušk zmóžnił, dyrbiš so <a target="_new" href="$1">přizjewić</a>',
318 - 'mwe-test-plural' => 'Sym {{PLURAL:$1|$1 test|$1 testaj|testy|testow}} přewjedł',
319 -);
320 -
321 -/** Hungarian (Magyar)
322 - * @author Dani
323 - * @author Glanthor Reviol
324 - */
325 -$messages['hu'] = array(
326 - 'mwe-loading_txt' => 'betöltés…',
327 - 'mwe-error_load_lib' => 'Hiba: a(z) $1 JavaScript-fájl nem elérhető, vagy nem definiálja a(z) $2 osztályt.',
328 - 'mwe-apiproxy-setup' => 'API proxy beállítása',
329 - 'mwe-load-drag-item' => 'Vonszolt elem betöltése',
330 - 'mwe-ok' => 'OK',
331 - 'mwe-cancel' => 'Mégse',
332 - 'mwe-enable-gadget' => 'A multimédia béta (mwEmbed) engedélyezése az összes lapon',
333 - 'mwe-enable-gadget-done' => 'A multimédia béta segédeszköz engedélyezve',
334 - 'mwe-must-login-gadget' => 'Hogy engedélyezni tudd a segédeszközt, <a target="_new" href="$1">be kell jelentkezned</a>',
335 - 'mwe-test-plural' => '$1 tesztet futtattam',
336 -);
337 -
338 -/** Interlingua (Interlingua)
339 - * @author McDutchie
340 - */
341 -$messages['ia'] = array(
342 - 'mwe-loading_txt' => 'cargamento ...',
343 - 'mwe-error_load_lib' => 'Error: JavaScript $1 non esseva recuperabile o non defini $2',
344 - 'mwe-apiproxy-setup' => 'Configuration del proxy pro le API',
345 - 'mwe-load-drag-item' => 'Cargamento del file trahite',
346 - 'mwe-ok' => 'OK',
347 - 'mwe-cancel' => 'Cancella',
348 - 'mwe-enable-gadget' => 'Activar beta multimedia (mwEmbed) pro tote le paginas',
349 - 'mwe-enable-gadget-done' => 'Le gadget beta multimedia ha essite activate',
350 - 'mwe-must-login-gadget' => 'Pro activar le gadget tu debe <a target="_new" href="$1">aperir un session</a>',
351 - 'mwe-test-plural' => 'Io ha executate {{PLURAL:$1|$1 test|$1 tests}}',
352 -);
353 -
354 -/** Indonesian (Bahasa Indonesia)
355 - * @author Farras
356 - * @author Irwangatot
357 - * @author IvanLanin
358 - */
359 -$messages['id'] = array(
360 - 'mwe-loading_txt' => 'memuat...',
361 - 'mwe-error_load_lib' => 'Kesalahan: JavaScript $1 tidak dapat diambil atau tidak mendefinisikan $2',
362 - 'mwe-apiproxy-setup' => 'Menyiapkan proksi API',
363 - 'mwe-load-drag-item' => 'Memuat butir terseret',
364 - 'mwe-ok' => 'Oke',
365 - 'mwe-cancel' => 'Batalkan',
366 - 'mwe-enable-gadget' => 'Aktifkan beta multimedia (mwEmbed) untuk semua halaman',
367 - 'mwe-enable-gadget-done' => 'Gadget beta multimedia telah diaktifkan',
368 - 'mwe-must-login-gadget' => 'Untuk mengaktifkan gadget Anda harus <a target="_new" href="$1">masuk log</a>',
369 - 'mwe-test-plural' => 'Saya menjalankan {{PLURAL:$1|$1 tes|$1 tes}}',
370 -);
371 -
372 -/** Igbo (Igbo) */
373 -$messages['ig'] = array(
374 - 'mwe-ok' => 'Ngwanu',
375 - 'mwe-cancel' => 'Emekwàlà',
376 -);
377 -
378 -/** Italian (Italiano)
379 - * @author Gianfranco
380 - */
381 -$messages['it'] = array(
382 - 'mwe-cancel' => 'Annulla',
383 -);
384 -
385 -/** Japanese (日本語)
386 - * @author Fryed-peach
387 - * @author 青子守歌
388 - */
389 -$messages['ja'] = array(
390 - 'mwe-loading_txt' => '読み込み中 …',
391 - 'mwe-error_load_lib' => 'エラー:JavaScript $1 は参照不能か、$2 を定義していません。',
392 - 'mwe-apiproxy-setup' => 'API プロキシーをセットアップ中',
393 - 'mwe-load-drag-item' => 'ドラッグされた項目を読み込み中',
394 - 'mwe-ok' => 'OK',
395 - 'mwe-cancel' => '中止',
396 - 'mwe-enable-gadget' => 'マルチメディアベータ(mwEmbed)を全ページで有効化',
397 - 'mwe-enable-gadget-done' => 'マルチメディアベータのガジェットが有効です',
398 - 'mwe-must-login-gadget' => 'ガジェットを有効にするには<a target="_new" href="$1">ログイン</a>が必要です',
399 - 'mwe-test-plural' => '{{PLURAL:$1|$1のテスト}}を実行する',
400 -);
401 -
402 -/** Korean (한국어)
403 - * @author Kwj2772
404 - */
405 -$messages['ko'] = array(
406 - 'mwe-loading_txt' => '불러오는 중...',
407 - 'mwe-cancel' => '취소',
408 -);
409 -
410 -/** Colognian (Ripoarisch)
411 - * @author Purodha
412 - */
413 -$messages['ksh'] = array(
414 - 'mwe-loading_txt' => 'aam Laade …',
415 - 'mwe-size-gigabytes' => '$1&nbsp;GB',
416 - 'mwe-size-megabytes' => '$1&nbsp;MB',
417 - 'mwe-size-kilobytes' => '$1&nbsp;KB',
418 - 'mwe-size-bytes' => '$1&nbsp;Bytes',
419 - 'mwe-error_load_lib' => 'Fähler: Dat JavaSkrep „<code lang="en">$1</code>“ wohr nit ze laade udder et leiht „<code lang="en">$2</code>“ nit faß.',
420 - 'mwe-cancel' => 'Affbräsche',
421 -);
422 -
423 -/** Luxembourgish (Lëtzebuergesch)
424 - * @author Robby
425 - */
426 -$messages['lb'] = array(
427 - 'mwe-loading_txt' => 'lueden ...',
428 - 'mwe-error_load_lib' => 'Feeler: JavaScript $1 konnt net ofgeruf ginn oder definéiert $2 net',
429 - 'mwe-apiproxy-setup' => 'API-Proxy astellen',
430 - 'mwe-load-drag-item' => 'Den agebonnen Objet gëtt gelueden',
431 - 'mwe-ok' => 'OK',
432 - 'mwe-cancel' => 'Ofbriechen',
433 - 'mwe-enable-gadget' => 'Multimedia-Beta-Gadget (mwEmbed) fir all Säiten aktivéieren',
434 - 'mwe-enable-gadget-done' => 'De Multimedia-Beta-Gadget gouf aktivéiert',
435 - 'mwe-must-login-gadget' => 'Fir de Gadget aktivéieren ze kënne musst Dir Iech <a target="_new" href="$1">aloggen</a>',
436 - 'mwe-test-plural' => 'Ech hunn {{PLURAL:$1|$1 Test|$1 Tester}} gemaach',
437 -);
438 -
439 -/** Macedonian (Македонски)
440 - * @author Bjankuloski06
441 - */
442 -$messages['mk'] = array(
443 - 'mwe-loading_txt' => 'Вчитувам...',
444 - 'mwe-error_load_lib' => 'Грешка: JavaScript $1 не е достапен или не определува $2',
445 - 'mwe-apiproxy-setup' => 'Поставувам API застапник (proxy)',
446 - 'mwe-load-drag-item' => 'Го вчитувам повлечениот елемент',
447 - 'mwe-ok' => 'ОК',
448 - 'mwe-cancel' => 'Откажи',
449 - 'mwe-enable-gadget' => 'Овозможи бета-мултимедија (mwEmbed) за сите страници',
450 - 'mwe-enable-gadget-done' => 'Овозможена е алатката за бета-мултимедија',
451 - 'mwe-must-login-gadget' => 'За да ја овозможите алатката морате да се <a target="_new" href="$1">најавите</a>',
452 - 'mwe-test-plural' => 'Направив {{PLURAL:$1|$1 проверка|$1 проверки}}',
453 -);
454 -
455 -/** Malayalam (മലയാളം)
456 - * @author Praveenp
457 - */
458 -$messages['ml'] = array(
459 - 'mwe-loading_txt' => 'ശേഖരിക്കുന്നു ...',
460 - 'mwe-error_load_lib' => 'പിശക്: ജാവാസ്ക്രിപ്റ്റ് $1 ശേഖരിക്കാൻ കഴിഞ്ഞില്ല അല്ലെങ്കിൽ $2 നിർവ്വചിച്ചിട്ടില്ല',
461 - 'mwe-apiproxy-setup' => 'എ.പി.ഐ. പ്രോക്സി സജ്ജീകരിക്കുക',
462 - 'mwe-load-drag-item' => 'വലിച്ചിട്ടത് ശേഖരിക്കുന്നു',
463 - 'mwe-ok' => 'ശരി',
464 - 'mwe-cancel' => 'റദ്ദാക്കുക',
465 -);
466 -
467 -/** Erzya (Эрзянь)
468 - * @author Botuzhaleny-sodamo
469 - */
470 -$messages['myv'] = array(
471 - 'mwe-loading_txt' => 'Йовкстамозо моли…',
472 -);
473 -
474 -/** Dutch (Nederlands)
475 - * @author Siebrand
476 - */
477 -$messages['nl'] = array(
478 - 'mwe-loading_txt' => 'bezig met laden ...',
479 - 'mwe-error_load_lib' => 'Fout: JavaScript $1 kon niet opgehaald worden of definieert $2 niet',
480 - 'mwe-apiproxy-setup' => 'Bezig met het opzetten van een API-proxy',
481 - 'mwe-load-drag-item' => 'Bezig met het laden van het gesleepte bestand',
482 - 'mwe-ok' => 'OK',
483 - 'mwe-cancel' => 'Annuleren',
484 - 'mwe-enable-gadget' => "Multimedia beta (mwEmbed) voor alle pagina's inschakelen",
485 - 'mwe-enable-gadget-done' => 'Multimedia beta is ingeschakeld',
486 - 'mwe-must-login-gadget' => 'Om de uitbreiding in te schakelen, moet u <a target="_new" href="$1">aanmelden</a>',
487 - 'mwe-test-plural' => '{{PLURAL:$1|$1 test|$1 tests}} uitgevoerd',
488 -);
489 -
490 -/** Norwegian (bokmål)‬ (‪Norsk (bokmål)‬)
491 - * @author Nghtwlkr
492 - */
493 -$messages['no'] = array(
494 - 'mwe-loading_txt' => 'Laster ...',
495 - 'mwe-error_load_lib' => 'Feil: JavaScript $1 kunne ikke gjenhentes eller definerer ikke $2',
496 - 'mwe-apiproxy-setup' => 'Setter opp API-mellomtjener',
497 - 'mwe-load-drag-item' => 'Laster dratt element',
498 - 'mwe-ok' => 'OK',
499 - 'mwe-cancel' => 'Avbryt',
500 - 'mwe-enable-gadget' => 'Aktiver multimedia-beta (mwEmbed) for alle sider',
501 - 'mwe-enable-gadget-done' => 'Skjermelement for multimedia-beta har blitt aktivert',
502 - 'mwe-must-login-gadget' => 'For å aktivere skjermelement må du <a target="_new" href="$1">logge inn</a>',
503 - 'mwe-test-plural' => 'Jeg kjørte {{PLURAL:$1|én test|$1 tester}}',
504 -);
505 -
506 -/** Occitan (Occitan)
507 - * @author Cedric31
508 - */
509 -$messages['oc'] = array(
510 - 'mwe-loading_txt' => 'cargament ...',
511 - 'mwe-error_load_lib' => 'Error : JavaScript $1 a pas pogut èsser trobat o definís pas $2',
512 - 'mwe-apiproxy-setup' => 'Configuracion del proxy API',
513 - 'mwe-load-drag-item' => 'Cargament de l’element depausat',
514 - 'mwe-ok' => 'OK',
515 - 'mwe-cancel' => 'Anullar',
516 -);
517 -
518 -/** Deitsch (Deitsch)
519 - * @author Xqt
520 - */
521 -$messages['pdc'] = array(
522 - 'mwe-ok' => 'OK',
523 -);
524 -
525 -/** Polish (Polski)
526 - * @author Sp5uhe
527 - */
528 -$messages['pl'] = array(
529 - 'mwe-loading_txt' => 'ładowanie ...',
530 - 'mwe-error_load_lib' => 'Błąd – W plik JavaScript $1 brak jest możliwości pobrania oraz definicji $2',
531 - 'mwe-apiproxy-setup' => 'Konfiguracja proxy dla API',
532 - 'mwe-load-drag-item' => 'Ładowanie przeciągniętego elementu',
533 - 'mwe-ok' => 'OK',
534 - 'mwe-cancel' => 'Anuluj',
535 - 'mwe-enable-gadget' => 'Włącz wersję testową multimediów (wmEmbed) na wszystkich stronach',
536 - 'mwe-enable-gadget-done' => 'Testowy gadżet multimediów został włączony',
537 - 'mwe-must-login-gadget' => 'Gadżet można włączyć dopiero po <a target="_new" href="$1">zalogowaniu się</a>',
538 - 'mwe-test-plural' => 'Wykonałem $1 {{PLURAL:$1|test|testy|testów}}',
539 -);
540 -
541 -/** Piedmontese (Piemontèis)
542 - * @author Borichèt
543 - * @author Dragonòt
544 - */
545 -$messages['pms'] = array(
546 - 'mwe-loading_txt' => 'A caria ...',
547 - 'mwe-error_load_lib' => 'Eror: JavaScript $1 as peul pa trovesse o a definiss pa $2',
548 - 'mwe-apiproxy-setup' => 'Amposté ël proxy API',
549 - 'mwe-load-drag-item' => "carié l'element tirà",
550 - 'mwe-ok' => 'Va bin',
551 - 'mwe-cancel' => 'Scancela',
552 - 'mwe-enable-gadget' => 'Abìlita la beta multimedia (mwEmbed) për tute le pàgine',
553 - 'mwe-enable-gadget-done' => "L'acessòri beta multimedia a l'é stàit abilità",
554 - 'mwe-must-login-gadget' => 'Për abilité l\'acessòri a dev <a target="_new" href="$1">intré ant ël sistema</a>',
555 - 'mwe-test-plural' => "I l'heu fàit {{PLURAL:$1|$1 test|$1 test}}",
556 -);
557 -
558 -/** Pashto (پښتو)
559 - * @author Ahmed-Najib-Biabani-Ibrahimkhel
560 - */
561 -$messages['ps'] = array(
562 - 'mwe-ok' => 'ښه',
563 - 'mwe-cancel' => 'ناګارل',
564 -);
565 -
566 -/** Portuguese (Português)
567 - * @author Hamilton Abreu
568 - * @author Malafaya
569 - */
570 -$messages['pt'] = array(
571 - 'mwe-loading_txt' => 'A carregar ...',
572 - 'mwe-error_load_lib' => 'Erro: O JavaScript $1 não pode ser importado ou não define $2',
573 - 'mwe-apiproxy-setup' => "A preparar o ''proxy'' da API",
574 - 'mwe-load-drag-item' => 'A carregar o objecto arrastado',
575 - 'mwe-ok' => 'OK',
576 - 'mwe-cancel' => 'Cancelar',
577 - 'mwe-enable-gadget' => 'Activar multimédia beta (mwEmbed) para todas as páginas',
578 - 'mwe-enable-gadget-done' => 'Gadget de multimédia beta foi activado',
579 - 'mwe-must-login-gadget' => 'Para activar o gadget tem de estar <a target="_new" href="$1">autenticado</a>',
580 - 'mwe-test-plural' => 'Fiz $1 {{PLURAL:$1|teste|testes}}',
581 -);
582 -
583 -/** Brazilian Portuguese (Português do Brasil)
584 - * @author Giro720
585 - * @author Luckas Blade
586 - */
587 -$messages['pt-br'] = array(
588 - 'mwe-loading_txt' => 'Carregando ...',
589 - 'mwe-error_load_lib' => 'Erro: O JavaScript $1 não pode ser importado ou não define $2',
590 - 'mwe-apiproxy-setup' => 'Configurando proxy da API',
591 - 'mwe-load-drag-item' => 'Carregando o objeto arrastado',
592 - 'mwe-ok' => 'OK',
593 - 'mwe-cancel' => 'Cancelar',
594 - 'mwe-enable-gadget' => 'Ativar multimídia beta beta (mwEmbed) para todas as páginas',
595 - 'mwe-enable-gadget-done' => 'Gadget de multimídia beta foi ativado',
596 - 'mwe-must-login-gadget' => 'Para ativar o gadget você deve estar <a target="_new" href="$1">autenticado</a>',
597 - 'mwe-test-plural' => 'Eu fiz $1 {{PLURAL:$1|teste|testes}}',
598 -);
599 -
600 -/** Russian (Русский)
601 - * @author Александр Сигачёв
602 - */
603 -$messages['ru'] = array(
604 - 'mwe-loading_txt' => 'загрузка …',
605 - 'mwe-error_load_lib' => 'Ошибка. JavaScript $1 не доступен или не определяет $2',
606 - 'mwe-apiproxy-setup' => 'Настройка API-прокси',
607 - 'mwe-load-drag-item' => 'Загрузка перетащенного элемента',
608 - 'mwe-ok' => 'OK',
609 - 'mwe-cancel' => 'Отмена',
610 - 'mwe-enable-gadget' => 'Включить бета-мультимедиа (mwEmbed) для всех страниц',
611 - 'mwe-enable-gadget-done' => 'Включён гаджет бета-мультимедиа',
612 - 'mwe-must-login-gadget' => 'Для включения гаджета вам следует <a target="_new" href="$1">представиться</a>.',
613 - 'mwe-test-plural' => 'Я прошёл {{PLURAL:$1|$1 проверку|$1 проверки|$1 проверок}}',
614 -);
615 -
616 -/** Rusyn (Русиньскый)
617 - * @author Gazeb
618 - */
619 -$messages['rue'] = array(
620 - 'mwe-ok' => 'ОК',
621 - 'mwe-cancel' => 'Сторно',
622 -);
623 -
624 -/** Slovak (Slovenčina)
625 - * @author Helix84
626 - */
627 -$messages['sk'] = array(
628 - 'mwe-loading_txt' => 'načítava sa ...',
629 - 'mwe-error_load_lib' => 'Error: JavaScript $1 nebolo možné získať alebo neobsahuje definíciu $2',
630 -);
631 -
632 -/** Serbian Cyrillic ekavian (Српски (ћирилица))
633 - * @author Михајло Анђелковић
634 - */
635 -$messages['sr-ec'] = array(
636 - 'mwe-loading_txt' => 'Учитавање ...',
637 - 'mwe-ok' => 'ОК',
638 - 'mwe-cancel' => 'Поништи',
639 - 'mwe-test-plural' => 'Покренуо/ла сам {{PLURAL:$1|$1 тест|$1 тестова}}',
640 -);
641 -
642 -/** Serbian Latin ekavian (Srpski (latinica)) */
643 -$messages['sr-el'] = array(
644 - 'mwe-loading_txt' => 'Učitavanje ...',
645 - 'mwe-ok' => 'OK',
646 - 'mwe-cancel' => 'Poništi',
647 - 'mwe-test-plural' => 'Pokrenuo/la sam {{PLURAL:$1|$1 test|$1 testova}}',
648 -);
649 -
650 -/** Swedish (Svenska)
651 - * @author Dafer45
652 - * @author GameOn
653 - */
654 -$messages['sv'] = array(
655 - 'mwe-loading_txt' => 'Laddar…',
656 - 'mwe-ok' => 'OK',
657 - 'mwe-cancel' => 'Avbryt',
658 -);
659 -
660 -/** Telugu (తెలుగు)
661 - * @author Veeven
662 - */
663 -$messages['te'] = array(
664 - 'mwe-ok' => 'సరే',
665 - 'mwe-cancel' => 'రద్దుచేయి',
666 -);
667 -
668 -/** Tagalog (Tagalog)
669 - * @author AnakngAraw
670 - */
671 -$messages['tl'] = array(
672 - 'mwe-loading_txt' => 'Ikinakarga...',
673 - 'mwe-error_load_lib' => 'Kamalian: hindi makukuha ang JavaScript na $1 o hindi nagbigay kahulugan sa $2',
674 - 'mwe-apiproxy-setup' => 'Nagtatalaga ng pamalit na API',
675 - 'mwe-load-drag-item' => 'Ikinakarga ang hinilang bagay',
676 - 'mwe-ok' => 'Okey',
677 - 'mwe-cancel' => 'Huwag ituloy',
678 - 'mwe-enable-gadget' => 'Paganahin ang betang multimidya (mwEmbed) para sa lahat ng mga pahina',
679 - 'mwe-enable-gadget-done' => 'Pinagana ang gadyet na pangbetang multimidya',
680 - 'mwe-must-login-gadget' => 'Upang mapagana ang gadyet dapat kang <a target="_new" href="$1">lumagda</a>',
681 - 'mwe-test-plural' => 'Nagpatakbo ako ng {{PLURAL:$1|$1 pagsusulit|$1 mga pagsusulit}}',
682 -);
683 -
684 -/** Turkish (Türkçe)
685 - * @author Joseph
686 - */
687 -$messages['tr'] = array(
688 - 'mwe-loading_txt' => 'yükleniyor ...',
689 - 'mwe-error_load_lib' => 'Hata: $1 JavaScripti erişilebilir değil ya da $2 tanımlı değil',
690 - 'mwe-apiproxy-setup' => 'API vekili ayarlanıyor',
691 - 'mwe-load-drag-item' => 'Sürüklenen öğe yükleniyor',
692 - 'mwe-ok' => 'Tamam',
693 - 'mwe-cancel' => 'İptal',
694 -);
695 -
696 -/** Urdu (اردو) */
697 -$messages['ur'] = array(
698 - 'mwe-cancel' => 'منسوخ',
699 -);
700 -
701 -/** Vèneto (Vèneto)
702 - * @author Candalua
703 - */
704 -$messages['vec'] = array(
705 - 'mwe-loading_txt' => "so' drio cargar ...",
706 - 'mwe-ok' => 'Va ben',
707 - 'mwe-cancel' => 'Anula',
708 -);
709 -
710 -/** Vietnamese (Tiếng Việt)
711 - * @author Minh Nguyen
712 - * @author Vinhtantran
713 - */
714 -$messages['vi'] = array(
715 - 'mwe-loading_txt' => 'đang tải …',
716 - 'mwe-size-kilobytes' => '$1 kB',
717 - 'mwe-error_load_lib' => 'Lỗi: JavaScript $1 không truy xuất được hoặc không định nghĩa $2',
718 - 'mwe-apiproxy-setup' => 'Đang thiết lập proxy API',
719 - 'mwe-load-drag-item' => 'Đang tải các mục đã kéo',
720 - 'mwe-ok' => 'OK',
721 - 'mwe-cancel' => 'Hủy bỏ',
722 - 'mwe-enable-gadget' => 'Kích hoạt đa phương tiện bản beta (mwEmbed) cho mọi trang',
723 - 'mwe-enable-gadget-done' => 'Công cụ đa năng đa phương tiện bản beta đã được kích hoạt',
724 - 'mwe-must-login-gadget' => 'Để kích hoạt công cụ đa năng bạn phải <a target="_new" href="$1">đăng nhập</a>',
725 - 'mwe-test-plural' => 'Tôi đã chạy {{PLURAL:$1|$1 mẫu thử|$1 mẫu thử}}',
726 -);
727 -
728 -/** Wu (吴语) */
729 -$messages['wuu'] = array(
730 - 'mwe-cancel' => '取消',
731 -);
732 -
733 -/** Simplified Chinese (‪中文(简体)‬) */
734 -$messages['zh-hans'] = array(
735 - 'mwe-loading_txt' => '载入中……',
736 - 'mwe-ok' => '确定',
737 - 'mwe-cancel' => '取消',
738 -);
739 -
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/mwEmbed.js
@@ -1,2800 +0,0 @@
2 -// Add support for html5 / mwEmbed elements to browsers that do not support the elements natively
3 -// For discussion and comments, see: http://ejohn.org/blog/html5-shiv/
4 -'video audio source track'.replace(/\w+/g, function(n){ document.createElement(n); });
5 -
6 -/**
7 - * @license mwEmbed Dual licensed under the MIT or GPL Version 2 licenses.
8 - *
9 - * @copyright (C) 2010 Kaltura
10 - * @author Michael Dale ( michael.dale at kaltura.com )
11 - *
12 - * @url http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library
13 - *
14 - * Libraries used include code license in headers
15 - */
16 -
17 -/**
18 - * Setup the "mw" global:
19 - */
20 -if ( typeof window.mw == 'undefined' ) {
21 - window.mw = { };
22 -}
23 -/**
24 - * Set the mwEmbedVersion
25 - */
26 -var MW_EMBED_VERSION = '1.1h';
27 -
28 -// Globals to pre-set ready functions in dynamic loading of mwEmbed
29 -if( typeof preMwEmbedReady == 'undefined'){
30 - var preMwEmbedReady = [];
31 -}
32 -// Globals to pre-set config values in dynamic loading of mwEmbed
33 -if( typeof preMwEmbedConfig == 'undefined') {
34 - var preMwEmbedConfig = [];
35 -}
36 -
37 -/**
38 - * The global mw object:
39 - */
40 -( function( mw ) {
41 - // The version of mwEmbed
42 - mw.version = MW_EMBED_VERSION;
43 -
44 - // List valid skins here:
45 - mw.validSkins = [ 'mvpcf', 'kskin' ];
46 -
47 - // Storage variable for loaded style sheet keys
48 - if( ! mw.style ){
49 - mw.style = { };
50 - }
51 -
52 - /**
53 - * Configuration System:
54 - */
55 -
56 - // Local scope configuration var:
57 - if( !mwConfig ){
58 - var mwConfig = { };
59 - }
60 -
61 - if( !mwNonDefaultConfigList ){
62 - var mwNonDefaultConfigList = [];
63 - }
64 -
65 - // mw scope mwUserConfig var. Stores user configuration
66 - var mwUserConfig = { };
67 -
68 - /**
69 - * Setter for configuration values
70 - *
71 - * @param [Mixed]
72 - * name Name of configuration value {Object} Will iderate through
73 - * each key and call setConfig {String} Will set configuration by
74 - * string name to value
75 - * @param {String}
76 - * value Value of configuration name {Object} value Set of values
77 - * to be merged
78 - */
79 - mw.setConfig = function ( name, value ) {
80 - if( typeof name == 'object' ) {
81 - for( var i in name ) {
82 - mw.setConfig( i, name[ i ] );
83 - }
84 - return ;
85 - }
86 - mwConfig[ name ] = value;
87 - mwNonDefaultConfigList.push( name );
88 - };
89 -
90 - // Apply any pre-setup config:
91 - mw.setConfig( preMwEmbedConfig );
92 -
93 - /**
94 - * Merge in a configuration value:
95 - */
96 - mw.mergeConfig = function( name, value ){
97 - if( typeof name == 'object' ) {
98 - $j.each( name, function( inx, val) {
99 - mw.setConfig( inx, val );
100 - });
101 - return ;
102 - }
103 - // Check if we should "merge" the config
104 - if( typeof value == 'object' && typeof mwConfig[ name ] == 'object' ) {
105 - if ( value.constructor.toString().indexOf("Array") != -1 &&
106 - mwConfig[ name ].constructor.toString().indexOf("Array") != -1 ){
107 - // merge in the array
108 - mwConfig[ name ] = $j.merge( mwConfig[ name ], value );
109 - } else {
110 - for( var i in value ){
111 - mwConfig[ name ][ i ] = value[ i ];
112 - }
113 - }
114 - return ;
115 - }
116 - // else do a normal setConfig
117 - mwConfig[ name ] = value;
118 - mwNonDefaultConfigList.push( name );
119 - };
120 -
121 - /**
122 - * Set a default config value Will only update configuration if no value is
123 - * present
124 - *
125 - * @param [Mixed]
126 - * value Set configuration name to value {Object} Will idorate
127 - * through each key and call setDefaultConfig {String} Will set
128 - * configuration by string name to value
129 - */
130 - mw.setDefaultConfig = function( name, value ) {
131 - if( typeof name == 'object' ) {
132 - for( var i in name ) {
133 - mw.setDefaultConfig( i, name[ i ] );
134 - }
135 - return ;
136 - }
137 - if( typeof mwConfig[ name ] == 'undefined' ) {
138 - mwConfig[ name ] = value;
139 - return ;
140 - }
141 - };
142 -
143 - /**
144 - * Getter for configuration values
145 - *
146 - * @param {String}
147 - * name of configuration value to get
148 - * @return {Mixed} value of configuration key returns "false" if key not
149 - * found
150 - */
151 - mw.getConfig = function ( name ) {
152 - if( mwConfig[ name ] )
153 - return mwConfig[ name ];
154 - return false;
155 - };
156 - /**
157 - * Get all the non-default configuration ( useful for passing state to
158 - * iframes in limited hash url length of a few K )
159 - */
160 - mw.getNonDefaultConfigObject = function(){
161 - var nonDefaultConfig = {};
162 - for( var i =0 ; i < mwNonDefaultConfigList.length; i ++){
163 - var configKey = mwNonDefaultConfigList[i];
164 - nonDefaultConfig[ configKey ] = mw.getConfig( configKey );
165 - }
166 - return nonDefaultConfig;
167 - }
168 -
169 - /**
170 - * Loads the mwUserConfig from a cookie.
171 - *
172 - * Modules that want to use "User Config" should call this setup function in
173 - * their moduleLoader code.
174 - *
175 - * For performance interfaces using "user config" should load '$j.cookie' &
176 - * 'JSON' in their module loader
177 - *
178 - * By abstracting user preference we could eventually integrate a persistent
179 - * per-account preference system on the server.
180 - *
181 - * @parma {Function} callback Function to be called once userPrefrences are
182 - * loaded
183 - */
184 - var setupUserConfigFlag = false;
185 - mw.setupUserConfig = function( callback ) {
186 - if( setupUserConfigFlag ) {
187 - if( callback ) {
188 - callback();
189 - }
190 - return ;
191 - }
192 - // Do Setup user config:
193 - mw.load( [ '$j.cookie', 'JSON' ], function() {
194 - if( $j.cookie( 'mwUserConfig' ) ) {
195 - mwUserConfig = JSON.parse( $j.cookie( 'mwUserConfig' ) );
196 - }
197 - setupUserConfigFlag = true;
198 - if( callback ) {
199 - callback();
200 - }
201 - });
202 - };
203 -
204 - /**
205 - * Save a user configuration var to a cookie & local global variable Loads
206 - * the cookie plugin if not already loaded
207 - *
208 - * @param {String}
209 - * name Name of user configuration value
210 - * @param {String}
211 - * value Value of configuration name
212 - */
213 - mw.setUserConfig = function ( name, value, cookieOptions ) {
214 - if( ! setupUserConfigFlag ) {
215 - mw.log( "Error: userConfig not setup" );
216 - return false;
217 - }
218 - // Update local value
219 - mwUserConfig[ name ] = value;
220 -
221 - // Update the cookie ( '$j.cookie' & 'JSON' should already be loaded )
222 - $j.cookie( 'mwUserConfig', JSON.stringify( mwUserConfig ) );
223 - };
224 -
225 - /**
226 - * Save a user configuration var to a cookie & local global variable
227 - *
228 - * @param {String}
229 - * name Name of user configuration value
230 - * @return value of the configuration name false if the configuration name
231 - * could not be found
232 - */
233 - mw.getUserConfig = function ( name ) {
234 - if( mwUserConfig[ name ] )
235 - return mwUserConfig[ name ];
236 - return false;
237 - };
238 -
239 - /**
240 - * Add a hook system for a target object / interface
241 - *
242 - * depricated you should instead use jQuery's bind and trigger
243 - *
244 - * @param {Object}
245 - * targetObj Interface Object to add hook system to.
246 - */
247 - mw.addHookSystem = function( targetObj ) {
248 -
249 - // Setup the target object hook holder:
250 - targetObj[ 'hooks' ] = { };
251 -
252 - /**
253 - * Adds a hook to the target object
254 - *
255 - * Should be called by clients to setup named hooks
256 - *
257 - * @param {String}
258 - * hookName Name of hook to be added
259 - * @param {Function}
260 - * hookFunction Function to be called at hook time
261 - */
262 - targetObj.addHook = function( hookName, hookFunction ) {
263 - if( ! this.hooks[ hookName ] ) {
264 - this.hooks[ hookName ] = [ ];
265 - }
266 - this.hooks[ hookName ].push( hookFunction );
267 - };
268 -
269 - /**
270 - * Runs all the hooks by a given name with reference to the host object
271 - *
272 - * Should be called by the host object at named execution points
273 - *
274 - * @param {String}
275 - * hookName Name of hook to be called
276 - * @return Value of hook result true interface should continue function
277 - * execution false interface should stop or return from method
278 - */
279 - targetObj.runHook = function( hookName, options ) {
280 - if( this.hooks[ hookName ] ) {
281 - for( var i =0; i < this.hooks[ hookName ].length; i ++ ) {
282 - if( typeof( this.hooks[ hookName ][ i ] ) == 'function' ) {
283 - this.hooks[ hookName ][ i ]( options );
284 - }
285 - }
286 - }
287 - };
288 - };
289 -
290 - // Add hooks system to the core "mw" object
291 - mw.addHookSystem( mw );
292 -
293 - // Stores callbacks for resource loader loading
294 - var mwLoadDoneCB = { };
295 -
296 -
297 - /**
298 - * Top level loader prototype:
299 - */
300 - mw.loader = {
301 - /**
302 - * Javascript Module Loader functions
303 - *
304 - * @key Name of Module
305 - * @value function code to load module
306 - */
307 - moduleLoaders : [],
308 -
309 - /**
310 - * Module resource list queue.
311 - *
312 - * @key Name of Module
313 - * @value .resourceList list of resources to be loaded .functionQueue
314 - * list of functions to be run once module is ready
315 - */
316 - moduleLoadQueue: { },
317 -
318 - /**
319 - * Javascript Class Paths
320 - *
321 - * @key Name of resource
322 - * @value Class file path
323 - */
324 - resourcePaths : { },
325 -
326 - /**
327 - * Stores resources that have been requested ( to avoid re-requesting
328 - * the same resources ) in concurrent requests )
329 - */
330 - requestedResourceQueue: { },
331 -
332 - /**
333 - * javascript Resource Paths
334 - *
335 - * @key Name of resource
336 - * @value Name of depenent style sheet
337 - */
338 - resourceStyleDependency: { },
339 -
340 - /**
341 - * Core load function:
342 - *
343 - * @param {Mixed}
344 - * loadRequest:
345 - *
346 - * {String} Name of a module to be loaded Modules are added via
347 - * addModuleLoader and can define custom code needed to check config and
348 - * return a list of resources to be loaded
349 - *
350 - * {String} Name of a resource to loaded. Resources are added via
351 - * addResourcePaths function Using defined resource names avoids loading
352 - * the same resource twice by first checking if the named resource is
353 - * defined in the global javascript scope variable
354 - *
355 - * {String} Absolute or relative to url path The same file won't be
356 - * loaded twice
357 - *
358 - * {Array} can be an array of any combination of the above strings. Will
359 - * be loaded in-order or in a single resource loader request if
360 - * scriptLoader is available.
361 - *
362 - * {Array} {Array} Can be a set of Arrays for loading. Some browsers
363 - * execute included scripts out of order. This lets you chain sets of
364 - * request for those browsers. If using the server side resource loader
365 - * order is preserved in output and a single request will be used.
366 - *
367 - * @param {Function}
368 - * callback Function called once loading is complete
369 - *
370 - */
371 - load: function( loadRequest, instanceCallback ) {
372 - // mw.log("mw.load:: " + loadRequest );
373 - var _this = this;
374 -
375 - // Throw out any loadRequests that are not strings
376 - loadRequest = this.cleanLoadRequest( loadRequest );
377 -
378 - // Ensure the callback is only called once per load instance
379 - var callback = function(){
380 - // mw.log( 'instanceCallback::running callback: ' +
381 - // instanceCallback );
382 - if( instanceCallback ){
383 - // We pass the loadRequest back to the callback for easy
384 - // debugging of concurrency issues.
385 - // ( normally its not used )
386 - instanceCallback( loadRequest );
387 - instanceCallback = null;
388 - }
389 - };
390 -
391 - // Check for empty loadRequest ( directly return the callback )
392 - if( mw.isEmpty( loadRequest ) ) {
393 - mw.log( 'Empty load request: ( ' + loadRequest + ' ) ' );
394 - callback( loadRequest );
395 - return ;
396 - }
397 -
398 -
399 - // Check if its a multi-part request:
400 - if( typeof loadRequest == 'object' ) {
401 - if( loadRequest.length > 1 ) {
402 - this.loadMany ( loadRequest, callback );
403 - return ;
404 - }else{
405 - // If an array of length 1 set as first element
406 - loadRequest = loadRequest[0];
407 - }
408 - }
409 -
410 - // Check for the module name loader function
411 - if( this.moduleLoaders[ loadRequest ] ) {
412 - var resourceSet = this.getModuleResourceSet( loadRequest );
413 - if( !resourceSet ){
414 - mw.log( "mw.load:: Error with module loader: " + loadRequest + ' ( no resource set defined )' );
415 - return ;
416 - }
417 -
418 - // xxx should use refactor "ready" stuff into a "domReady" class
419 - // So we would not have local scope globals like this:
420 - // if ( mwReadyFlag ) {
421 - // Load the module directly if load request is after
422 - // mw.ready has run
423 - this.load( resourceSet, callback );
424 - // } else {
425 - // this.addToModuleLoaderQueue(
426 - // loadRequest,
427 - // resourceSet,
428 - // callback
429 - // );
430 - // }
431 - return ;
432 - }
433 -
434 - // Check for javascript resource
435 - if( this.getResourcePath( loadRequest ) ) {
436 - this.loadResource( loadRequest, callback );
437 - return ;
438 - }
439 -
440 - // Try loading as a "file" or via ScriptLoader
441 - if( loadRequest ) {
442 - // Check if this resource was already requested
443 - if( typeof this.requestedResourceQueue[ loadRequest ] == 'object' ){
444 - this.requestedResourceQueue[ loadRequest ].push( callback );
445 - return ;
446 - } else {
447 - this.requestedResourceQueue[ loadRequest ] = [];
448 - }
449 -
450 - if( loadRequest.indexOf( '.js' ) == -1 && !mw.getResourceLoaderPath() ) {
451 - mw.log( 'Error: are you sure ' + loadRequest + ' is a file ( is it missing a resource path? ) ' );
452 - }
453 - mw.getScript( loadRequest, function(){
454 - // Check if we have requestedResources queue items:
455 - while( _this.requestedResourceQueue[ loadRequest ].length ){
456 - _this.requestedResourceQueue[ loadRequest ].shift()( loadRequest );
457 - }
458 - callback( loadRequest );
459 - // empty the load request queue:
460 - _this.requestedResourceQueue[ loadRequest ] = [];
461 - });
462 - return ;
463 - }
464 -
465 - // Possible error?
466 - mw.log( "Error could not handle load request: " + loadRequest );
467 - },
468 -
469 - getModuleResourceSet: function( moduleName ){
470 - // Check if the module loader is a function ~run that function~
471 - if( typeof ( this.moduleLoaders[ moduleName ] ) == 'function' ) {
472 - // Add the result of the module loader function
473 - return this.moduleLoaders[ moduleName ]();
474 - } else if( typeof ( this.moduleLoaders[ moduleName ] ) == 'object' ){
475 - // set resourceSet directly
476 - return this.moduleLoaders[ moduleName ];
477 - }
478 - return false;
479 - },
480 -
481 - /**
482 - * Clean the loadRequest ( throw out any non-string items )
483 - */
484 - cleanLoadRequest: function( loadRequest ){
485 - var cleanRequest = [];
486 - if( ! loadRequest ){
487 - return [];
488 - }
489 - if( typeof loadRequest == 'string' )
490 - return loadRequest;
491 - for( var i =0;i < loadRequest.length; i++ ){
492 - if( typeof loadRequest[i] == 'object' ) {
493 - cleanRequest[i] = this.cleanLoadRequest( loadRequest[i] );
494 - } else if( typeof loadRequest[i] == 'string' ){
495 - cleanRequest[i] = $j.trim( loadRequest[i] );
496 - } else{
497 - // bad request type skip
498 - }
499 - }
500 - return cleanRequest;
501 - },
502 -
503 - /**
504 - * Load a set of scripts. Will issue many load requests or package the
505 - * request for the resource loader
506 - *
507 - * @param {Object}
508 - * loadSet Set of scripts to be loaded
509 - * @param {Function}
510 - * callback Function to call once all scripts are loaded.
511 - */
512 - loadMany: function( loadSet, callback ) {
513 - var _this = this;
514 - // Setup up the local "loadStates"
515 - var loadStates = { };
516 -
517 - // Check if we can load via the "resource loader" ( mwEmbed was
518 - // included via scriptLoader )
519 - if( mw.getResourceLoaderPath() ) {
520 - // Get the grouped loadStates variable
521 - loadStates = this.getGroupLoadState( loadSet );
522 - if( mw.isEmpty( loadStates ) ) {
523 - // mw.log( 'loadMany:all resources already loaded');
524 - callback();
525 - return ;
526 - }
527 - }else{
528 - // Check if its a dependency set ( nested objects )
529 - if( typeof loadSet [ 0 ] == 'object' ) {
530 - _this.dependencyChainCallFlag[ loadSet ] = false;
531 - // Load sets of resources ( to preserver order for some
532 - // browsers )
533 - _this.loadDependencyChain( loadSet, callback );
534 - return ;
535 - }
536 -
537 - // Set the initial load state for every item in the loadSet
538 - for( var i = 0; i < loadSet.length ; i++ ) {
539 - var loadName = loadSet[ i ];
540 - loadStates[ loadName ] = 0;
541 - }
542 - }
543 -
544 - // We are infact loading many:
545 - // mw.log("mw.load: LoadMany:: " + loadSet );
546 -
547 - // Issue the load request check check loadStates to see if we are
548 - // "done"
549 - for( var loadName in loadStates ) {
550 - // mw.log("loadMany: load: " + loadName );
551 - this.load( loadName, function ( loadName ) {
552 - loadStates[ loadName ] = 1;
553 -
554 - /*
555 - * for( var i in loadStates ) { mw.log( loadName + '
556 - * finished of: ' + i + ' : ' + loadStates[i] ); }
557 - */
558 -
559 - // Check if all load request states are set 1
560 - var loadDone = true;
561 - for( var j in loadStates ) {
562 - if( loadStates[ j ] === 0 )
563 - loadDone = false;
564 - }
565 - // Run the parent scope callback for "loadMany"
566 - if( loadDone ) {
567 - callback( loadName );
568 - }
569 - } );
570 - }
571 - },
572 -
573 - /**
574 - * Get grouped load state for script loader
575 - *
576 - * Groups the scriptRequest where possible: Modules include "loader
577 - * code" so they are separated into pre-condition code to be run for
578 - * subsequent requests
579 - *
580 - * @param {Object}
581 - * loadSet Loadset to return grouped
582 - * @return {Object} grouped loadSet
583 - */
584 - getGroupLoadState: function( loadSet ) {
585 - var groupedLoadSet = [];
586 - var loadStates = { };
587 - // Merge load set into new groupedLoadSet
588 - if( typeof loadSet[0] == 'object' ) {
589 - for( var i = 0; i < loadSet.length ; i++ ) {
590 - for( var j = 0; j < loadSet[i].length ; j++ ) {
591 - // Make sure we have not already included it:
592 - groupedLoadSet.push( loadSet[i][j] );
593 - }
594 - }
595 - } else {
596 - // Use the loadSet directly:
597 - groupedLoadSet = loadSet;
598 - }
599 -
600 - // Setup grouped loadStates Set:
601 - var groupClassKey = '';
602 - var coma = '';
603 - var uniqueResourceName = {};
604 - for( var i=0; i < groupedLoadSet.length; i++ ) {
605 - var loadName = groupedLoadSet[ i ];
606 - if( this.getResourcePath( loadName ) ) {
607 - // Check if not already in request queue and not defined in
608 - // global namespace
609 - if( !mw.isset( loadName ) && ! uniqueResourceName[ loadName] ){
610 - groupClassKey += coma + loadName;
611 - coma = ',';
612 -
613 - // Check for style sheet dependencies
614 - if( this.resourceStyleDependency[ loadName ] ){
615 - groupClassKey += coma + this.resourceStyleDependency[ loadName ];
616 - }
617 - }
618 - } else if ( this.moduleLoaders[ loadName ] ) {
619 -
620 - // Module loaders break up grouped script requests ( add the
621 - // current groupClassKey )
622 - if( groupClassKey != '' ) {
623 - loadStates[ groupClassKey ] = 0;
624 - groupClassKey = coma = '';
625 - }
626 - if( ! uniqueResourceName[ loadName] ){
627 - // Add the module to the loadSate
628 - loadStates[ loadName ] = 0;
629 - }
630 - }
631 - uniqueResourceName[ loadName] = true;
632 - }
633 -
634 - // Add groupClassKey if set:
635 - if( groupClassKey != '' ) {
636 - loadStates [ groupClassKey ] = 0;
637 - }
638 -
639 - return loadStates;
640 - },
641 -
642 - // Array to register that a callback has been called
643 - dependencyChainCallFlag: { },
644 -
645 - /**
646 - * Load a sets of scripts satisfy dependency order for browsers that
647 - * execute dynamically included scripts out of order
648 - *
649 - * @param {Object}
650 - * loadChain A set of javascript arrays to be loaded. Sets
651 - * are requested in array order.
652 - */
653 - loadDependencyChain: function( loadChain, callback ) {
654 - var _this = this;
655 - // Load with dependency checks
656 - var callSet = loadChain.shift();
657 - this.load( callSet, function( cbname ) {
658 - if ( loadChain.length != 0 ) {
659 - _this.loadDependencyChain( loadChain, callback );
660 - } else {
661 - // NOTE: IE gets called twice so we have check the
662 - // dependencyChainCallFlag before calling the callback
663 - if( _this.dependencyChainCallFlag[ callSet ] == callback ) {
664 - mw.log("... already called this callback for " + callSet );
665 - return ;
666 - }
667 - _this.dependencyChainCallFlag[ callSet ] = callback;
668 - callback( );
669 - }
670 - } );
671 - },
672 -
673 - /**
674 - * Add to the module loader queue
675 - */
676 - addToModuleLoaderQueue: function( moduleName, resourceSet, callback ) {
677 - mw.log(" addToModuleLoaderQueue:: " + moduleName + ' resourceSet: ' + resourceSet );
678 - if( this.moduleLoadQueue[ moduleName ] ){
679 - // If the module is already in the queue just add its callback:
680 - this.moduleLoadQueue[ moduleName ].functionQueue.push( callback );
681 - } else {
682 - // create the moduleLoadQueue item
683 - this.moduleLoadQueue[ moduleName ] = {
684 - 'resourceSet' : resourceSet,
685 - 'functionQueue' : [ callback ],
686 - 'loaded' : false
687 - };
688 - }
689 - },
690 -
691 - /**
692 - * Loops over all modules in queue, builds request sets based on config
693 - * request type
694 - */
695 - runModuleLoadQueue: function(){
696 - var _this = this;
697 - mw.log( "mw.runModuleLoadQueue:: " );
698 - var runModuleFunctionQueue = function(){
699 - // Run all the callbacks
700 - for( var moduleName in _this.moduleLoadQueue ){
701 - while( _this.moduleLoadQueue[moduleName].functionQueue.length ) {
702 - _this.moduleLoadQueue[moduleName].functionQueue.shift()();
703 - }
704 - }
705 - };
706 -
707 - // Check for single request or javascript debug based loading:
708 - if( !mw.getResourceLoaderPath() || mw.getConfig( 'loader.groupStrategy' ) == 'single' ){
709 - // if not using the resource load just do a normal array merge
710 - // ( for browsers like IE that don't follow first append first
711 - // execute rule )
712 - var fullResourceList = [];
713 - for( var moduleName in this.moduleLoadQueue ) {
714 - var resourceSet = this.moduleLoadQueue[ moduleName ].resourceSet;
715 - // Lets try a global merge
716 - fullResourceList = $j.merge( fullResourceList, resourceSet );
717 - }
718 - mw.load( fullResourceList, function(){
719 - runModuleFunctionQueue();
720 - });
721 - return ;
722 - }
723 -
724 - // Else do per module group loading
725 - if( mw.getConfig( 'loader.groupStrategy' ) == 'module' ) {
726 - var fullResourceList = [];
727 - var sharedResourceList = [];
728 -
729 - for( var moduleName in this.moduleLoadQueue ) {
730 - // Build a shared dependencies list and load that separately
731 - // "first"
732 - // ( in IE we have to wait until its "ready" since it does
733 - // not follow dom order )
734 - var moduleResourceList = this.getFlatModuleResourceList( moduleName );
735 - // Build the sharedResourceList
736 - for( var i=0; i < moduleResourceList.length; i++ ){
737 - var moduleResource = moduleResourceList[i];
738 - // Check if already in the full resource list if so add
739 - // to shared.
740 - if( fullResourceList[ moduleResource ] ){
741 - if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){
742 - sharedResourceList.push( moduleResource );
743 - }
744 - }
745 - // Add to the fullResourceList
746 - fullResourceList[ moduleResource ] = true;
747 - }
748 - }
749 -
750 - // Local module request set ( stores the actual request we will
751 - // make after grouping shared resources
752 - var moduleRequestSet = {};
753 -
754 - // Only add non-shared to respective modules load requests
755 - for( var moduleName in this.moduleLoadQueue ) {
756 - moduleRequestSet[ moduleName ] = [];
757 - var moduleResourceList = this.getFlatModuleResourceList( moduleName );
758 - for( var i =0; i < moduleResourceList.length; i++ ){
759 - var moduleResource = moduleResourceList[i];
760 - if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){
761 - moduleRequestSet[ moduleName ].push( moduleResource );
762 - }
763 - }
764 - }
765 - var sharedResourceLoadDone = false;
766 - // Check if modules are done
767 - var checkModulesDone = function(){
768 - if( !sharedResourceLoadDone ){
769 - return false;
770 - }
771 - for( var moduleName in _this.moduleLoadQueue ) {
772 - if( ! _this.moduleLoadQueue[ moduleName ].loaded ){
773 - return false;
774 - }
775 - }
776 - runModuleFunctionQueue();
777 - };
778 - // Local instance of load requests to retain resourceSet
779 - // context:
780 - var localLoadCallInstance = function( moduleName, resourceSet ){
781 - mw.load( resourceSet, function(){
782 - _this.moduleLoadQueue[ moduleName ].loaded = true;
783 - checkModulesDone();
784 - });
785 - };
786 -
787 - // Load the shared resources
788 - mw.load( sharedResourceList, function(){
789 - // mw.log("Shared Resources loaded");
790 - // xxx check if we are in "IE" and dependencies need to be
791 - // loaded "first"
792 - sharedResourceLoadDone = true;
793 - checkModulesDone();
794 - });
795 - // Load all module Request Set
796 - for( var moduleName in moduleRequestSet ){
797 - localLoadCallInstance( moduleName, moduleRequestSet[ moduleName ] );
798 - }
799 - }
800 - // xxx Here we could also do some "intelligent" grouping
801 - },
802 -
803 - getFlatModuleResourceList: function( moduleName ){
804 - var moduleList = [];
805 - for( var j in this.moduleLoadQueue[moduleName].resourceSet ){
806 - // Check if we have a multi-set array:
807 - if( typeof this.moduleLoadQueue[moduleName].resourceSet[j] == 'object' ){
808 - moduleList = $j.merge( moduleList, this.moduleLoadQueue[moduleName].resourceSet[j] );
809 - } else {
810 - moduleList = $j.merge( moduleList, [ this.moduleLoadQueue[moduleName].resourceSet[j] ] );
811 - }
812 - }
813 - return moduleList;
814 - },
815 -
816 - /**
817 - * Loads javascript or css associated with a resourceName
818 - *
819 - * @param {String}
820 - * resourceName Name of resource to load
821 - * @param {Function}
822 - * callback Function to run once resource is loaded
823 - */
824 - loadResource: function( resourceName , callback) {
825 - // mw.log("LoadResource:" + resourceName );
826 - var _this = this;
827 -
828 - // Check for css dependency on resource name
829 - if( this.resourceStyleDependency[ resourceName ] ) {
830 - if( ! mw.isset( this.resourceStyleDependency[ resourceName ] )){
831 - mw.log("loadResource:: dependent css resource: " + this.resourceStyleDependency[ resourceName ] );
832 - _this.loadResource( this.resourceStyleDependency[ resourceName ] , function() {
833 - // Continue the original loadResource request.
834 - _this.loadResource( resourceName, callback );
835 - });
836 - return ;
837 - }
838 - }
839 -
840 - // Make sure the resource is not already defined:
841 - if ( mw.isset( resourceName ) ) {
842 - // mw.log( 'Class ( ' + resourceName + ' ) already defined ' );
843 - callback( resourceName );
844 - return ;
845 - }
846 -
847 - // Setup the Script Request var:
848 - var scriptRequest = null;
849 -
850 -
851 - // If the scriptloader is enabled use the resourceName as the
852 - // scriptRequest:
853 - if( mw.getResourceLoaderPath() ) {
854 - scriptRequest = resourceName;
855 - }else{
856 - // Get the resource url:
857 - var baseClassPath = this.getResourcePath( resourceName );
858 - // Add the mwEmbed path if not a root path or a full url
859 - if( baseClassPath.indexOf( '/' ) !== 0 &&
860 - baseClassPath.indexOf( '://' ) === -1 ) {
861 - scriptRequest = mw.getMwEmbedPath() + baseClassPath;
862 - }else{
863 - scriptRequest = baseClassPath;
864 - }
865 - if( ! scriptRequest ) {
866 - mw.log( "Error Could not get url for resource " + resourceName );
867 - return false;
868 - }
869 - }
870 - // Include resource defined check for older browsers
871 - var resourceDone = false;
872 -
873 - // Set the loadDone callback per the provided resourceName
874 - mw.setLoadDoneCB( resourceName, callback );
875 - // Issue the request to load the resource (include resource name in
876 - // result callback:
877 - mw.getScript( scriptRequest, function( scriptRequest ) {
878 - // If its a "style sheet" manually set its resource to true
879 - var ext = scriptRequest.substr( scriptRequest.split('?')[0].lastIndexOf( '.' ), 4 ).toLowerCase();
880 - if( ext == '.css' && resourceName.substr(0,8) == 'mw.style' ){
881 - mw.style[ resourceName.substr( 9 ) ] = true;
882 - }
883 -
884 - // Send warning if resourceName is not defined
885 - if(! mw.isset( resourceName )
886 - && mwLoadDoneCB[ resourceName ] != 'done' ) {
887 - // mw.log( 'Possible Error: ' + resourceName +' not set in
888 - // time, or not defined in:' + "\n"
889 - // + _this.getResourcePath( resourceName ) );
890 - }
891 -
892 - // If ( debug mode ) and the script include is missing resource
893 - // messages
894 - // do a separate request to retrieve the msgs
895 - if( mw.currentClassMissingMessages ) {
896 - mw.log( " resourceName " + resourceName + " is missing messages" );
897 - // Reset the currentClassMissingMessages flag
898 - mw.currentClassMissingMessages = false;
899 -
900 - // Load msgs for this resource:
901 - mw.loadResourceMessages( resourceName, function() {
902 - // Run the onDone callback
903 - mw.loadDone( resourceName );
904 - } );
905 - } else {
906 - // If not using the resource loader make sure the
907 - // resourceName is available before firing the loadDone
908 - if( !mw.getResourceLoaderPath() ) {
909 - mw.waitForObject( resourceName, function( resourceName ) {
910 - // Once object is ready run loadDone
911 - mw.loadDone( resourceName );
912 - } );
913 - } else {
914 - // loadDone should be appended to the bottom of the
915 - // resource loader response
916 - // mw.loadDone( resourceName );
917 - }
918 - }
919 - } );
920 - },
921 -
922 - /**
923 - * Adds a module to the mwLoader object
924 - *
925 - * @param {String}
926 - * name Name of module
927 - * @param {Function}
928 - * moduleLoader Function that loads dependencies for a module
929 - */
930 - addModuleLoader: function( name, moduleLoader ) {
931 - this.moduleLoaders [ name ] = moduleLoader;
932 - },
933 -
934 - /**
935 - * Adds resource file path key value pairs
936 - *
937 - * @param {Object}
938 - * resourceSet JSON formated list of resource name file path
939 - * pairs.
940 - *
941 - * resourceSet must be strict JSON to allow the php scriptLoader to
942 - * parse the file paths.
943 - */
944 - addResourcePaths: function( resourceSet ) {
945 - var prefix = ( mw.getConfig( 'loaderContext' ) )?
946 - mw.getConfig( 'loaderContext' ): '';
947 -
948 - for( var i in resourceSet ) {
949 - this.resourcePaths[ i ] = prefix + resourceSet[ i ];
950 - }
951 - },
952 -
953 - /*
954 - * Adds a named style sheet dependency to a named resource
955 - *
956 - * @parma {Object} resourceSet JSON formated list of resource names and
957 - * associated style sheet names
958 - */
959 - addStyleResourceDependency: function( resourceSet ){
960 - for( var i in resourceSet ){
961 - this.resourceStyleDependency[ i ] = resourceSet[i];
962 - }
963 - },
964 -
965 - /**
966 - * Get a resource path from a resourceName if no resource found return
967 - * false
968 - */
969 - getResourcePath: function( resourceName ) {
970 - if( this.resourcePaths[ resourceName ] )
971 - return this.resourcePaths[ resourceName ];
972 - return false;
973 - }
974 - };
975 -
976 - /**
977 - * Load done callback for script loader
978 - *
979 - * @param {String}
980 - * requestName Name of the load request
981 - */
982 - mw.loadDone = function( requestName ) {
983 - if( !mwLoadDoneCB[ requestName ] ) {
984 - return true;
985 - }
986 - while( mwLoadDoneCB[ requestName ].length ) {
987 - // check if mwLoadDoneCB is already "done"
988 - // the function list is not an object
989 - if( typeof mwLoadDoneCB[ requestName ] != 'object' )
990 - {
991 - break;
992 - }
993 - var func = mwLoadDoneCB[ requestName ].pop();
994 - if( typeof func == 'function' ) {
995 - // mw.log( "LoadDone: " + requestName + ' run callback::' +
996 - // func);
997 - func( requestName );
998 - }else{
999 - mw.log('mwLoadDoneCB: Error non callback function on stack');
1000 - }
1001 - }
1002 - // Set the load request name to done
1003 - mwLoadDoneCB[ requestName ] = 'done';
1004 - };
1005 -
1006 - /**
1007 - * Set a load done callback
1008 - *
1009 - * @param {String}
1010 - * requestName Name of resource or request set
1011 - * @param {Function}
1012 - * callback Function called once requestName is ready
1013 - */
1014 - mw.setLoadDoneCB = function( requestName, callback ) {
1015 - // If the requestName is already done loading just callback
1016 - if( mwLoadDoneCB[ requestName ] == 'done' ) {
1017 - callback( requestName );
1018 - }
1019 - // Setup the function queue if unset
1020 - if( typeof mwLoadDoneCB[ requestName ] != 'object' ) {
1021 - mwLoadDoneCB[ requestName ] = [];
1022 - }
1023 - mwLoadDoneCB[ requestName ].push( callback );
1024 - };
1025 -
1026 - /**
1027 - * Shortcut entry points / convenience functions: Lets you write mw.load()
1028 - * instead of mw.loader.load() only these entry points should be used.
1029 - *
1030 - * future closure optimizations could minify internal function names
1031 - */
1032 -
1033 - /**
1034 - * Load Object entry point: Loads a requested set of javascript
1035 - */
1036 - mw.load = function( loadRequest, callback ) {
1037 - return mw.loader.load( loadRequest, callback );
1038 - };
1039 -
1040 - /**
1041 - * Add module entry point: Adds a module to the mwLoader object
1042 - */
1043 - mw.addModuleLoader = function ( name, loaderFunction ) {
1044 - return mw.loader.addModuleLoader( name, loaderFunction );
1045 - };
1046 -
1047 - /**
1048 - * Add Class File Paths entry point:
1049 - */
1050 - mw.addResourcePaths = function ( resourceSet ) {
1051 - return mw.loader.addResourcePaths( resourceSet );
1052 - };
1053 -
1054 - mw.addStyleResourceDependency = function ( resourceSet ) {
1055 - return mw.loader.addStyleResourceDependency( resourceSet );
1056 - };
1057 -
1058 - /**
1059 - * Get Class File Path entry point:
1060 - */
1061 - mw.getResourcePath = function( resourceName ) {
1062 - return mw.loader.getResourcePath( resourceName );
1063 - };
1064 -
1065 -
1066 - /**
1067 - * Utility Functions
1068 - */
1069 -
1070 - /**
1071 - * addLoaderDialog small helper for displaying a loading dialog
1072 - *
1073 - * @param {String}
1074 - * dialogHtml text Html of the loader msg
1075 - */
1076 - mw.addLoaderDialog = function( dialogHtml ) {
1077 - if( typeof dialogHtml == 'undefined'){
1078 - dialogHtml ='';
1079 - }
1080 - var $dialog = mw.addDialog( {
1081 - 'title' : dialogHtml,
1082 - 'content' : dialogHtml + '<br>' +
1083 - $j('<div />')
1084 - .loadingSpinner()
1085 - .html()
1086 - });
1087 - return $dialog;
1088 - };
1089 -
1090 - /**
1091 - * Close the loader dialog created with addLoaderDialog
1092 - */
1093 - mw.closeLoaderDialog = function() {
1094 - // Make sure the dialog resource is present
1095 - if( !mw.isset( '$j.ui.dialog' ) ) {
1096 - return false;
1097 - }
1098 - // Close with timeout since jquery ui binds with timeout:
1099 - // ui dialog line 530
1100 - setTimeout( function(){
1101 - $j( '#mwTempLoaderDialog' )
1102 - .dialog( 'destroy' );
1103 - } , 10);
1104 - };
1105 -
1106 - /**
1107 - * Add a (temporary) dialog window:
1108 - *
1109 - * @param {Object}
1110 - * with following keys: title: {String} Title string for the
1111 - * dialog content: {String} to be inserted in msg box buttons:
1112 - * {Object} A button object for the dialog Can be a string for
1113 - * the close button any jquery.ui.dialog option
1114 - */
1115 - mw.addDialog = function ( options ) {
1116 - // Remove any other dialog
1117 - $j( '#mwTempLoaderDialog' ).remove();
1118 -
1119 - if( !options){
1120 - options = {};
1121 - }
1122 -
1123 - // Extend the default options with provided options
1124 - var options = $j.extend({
1125 - 'bgiframe': true,
1126 - 'draggable': true,
1127 - 'resizable': false,
1128 - 'modal': true,
1129 - 'position' : ['center', 'center']
1130 - }, options );
1131 -
1132 - if( ! options.title || ! options.content ){
1133 - mw.log("Error: mwEmbed addDialog missing required options ( title, content ) ");
1134 - return ;
1135 - }
1136 -
1137 - // Append the dialog div on top:
1138 - $j( 'body' ).append(
1139 - $j('<div />')
1140 - .attr( {
1141 - 'id' : "mwTempLoaderDialog",
1142 - 'title' : options.title
1143 - })
1144 - .hide()
1145 - .append( options.content )
1146 - );
1147 -
1148 - // Build the uiRequest
1149 - var uiRequest = [ '$j.ui.dialog' ];
1150 - if( options.draggable ){
1151 - uiRequest.push( '$j.ui.mouse' );
1152 - uiRequest.push( '$j.ui.draggable' );
1153 - }
1154 - if( options.resizable ){
1155 - uiRequest.push( '$j.ui.resizable' );
1156 - }
1157 -
1158 - // Special button string
1159 - if ( typeof options.buttons == 'string' ) {
1160 - var buttonMsg = options.buttons;
1161 - buttons = { };
1162 - options.buttons[ buttonMsg ] = function() {
1163 - $j( this ).dialog( 'close' );
1164 - };
1165 - }
1166 -
1167 - // Load the dialog resources
1168 - mw.load([
1169 - [
1170 - '$j.ui',
1171 - '$j.widget',
1172 - '$j.ui.mouse',
1173 - '$j.ui.position'
1174 - ],
1175 - uiRequest
1176 - ], function() {
1177 - var $dialog = $j( '#mwTempLoaderDialog' ).show().dialog( options );
1178 - } );
1179 - return $j( '#mwTempLoaderDialog' );
1180 - };
1181 -
1182 - mw.isIphone = function(){
1183 - return ( navigator.userAgent.indexOf('iPhone') != -1 && ! mw.isIpad() );
1184 - };
1185 - // Uses hack described at:
1186 - // http://www.bdoran.co.uk/2010/07/19/detecting-the-iphone4-and-resolution-with-javascript-or-php/
1187 - mw.isIphone4 = function(){
1188 - return ( mw.isIphone() && ( window.devicePixelRatio && window.devicePixelRatio >= 2 ) );
1189 - };
1190 - mw.isIpod = function(){
1191 - return ( navigator.userAgent.indexOf('iPod') != -1 );
1192 - };
1193 - mw.isIpad = function(){
1194 - return ( navigator.userAgent.indexOf('iPad') != -1 );
1195 - };
1196 - // Android 2 has some restrictions vs other mobile platforms
1197 - mw.isAndroid2 = function(){
1198 - return ( navigator.userAgent.indexOf( 'Android 2.') != -1 );
1199 - };
1200 -
1201 - /**
1202 - * Fallforward system by default prefers flash.
1203 - *
1204 - * This is separate from the EmbedPlayer library detection to provide
1205 - * package loading control NOTE: should be phased out in favor of browser
1206 - * feature detection where possible
1207 - *
1208 - */
1209 - mw.isHTML5FallForwardNative = function(){
1210 - if( mw.isMobileHTML5() ){
1211 - return true;
1212 - }
1213 - // Check for url flag to force html5:
1214 - if( document.URL.indexOf('forceMobileHTML5') != -1 ){
1215 - return true;
1216 - }
1217 - // Fall forward native:
1218 - // if the browser supports flash ( don't use html5 )
1219 - if( mw.supportsFlash() ){
1220 - return false;
1221 - }
1222 - // No flash return true if the browser supports html5 video tag with
1223 - // basic support for canPlayType:
1224 - if( mw.supportsHTML5() ){
1225 - return true;
1226 - }
1227 -
1228 - return false;
1229 - }
1230 -
1231 - mw.isMobileHTML5 = function(){
1232 - // Check for a mobile html5 user agent:
1233 - if ( mw.isIphone() ||
1234 - mw.isIpod() ||
1235 - mw.isIpad() ||
1236 - mw.isAndroid2()
1237 - ){
1238 - return true;
1239 - }
1240 - return false;
1241 - }
1242 - mw.supportsHTML5 = function(){
1243 - // Blackberry is evil in its response to canPlayType calls.
1244 - if( navigator.userAgent.indexOf('BlackBerry') != -1 ){
1245 - return false ;
1246 - }
1247 - var dummyvid = document.createElement( "video" );
1248 - if( dummyvid.canPlayType ) {
1249 - return true;
1250 - }
1251 - return false;
1252 - }
1253 -
1254 - mw.supportsFlash = function(){
1255 - // Check if the client does not have flash and has the video tag
1256 - if ( navigator.mimeTypes && navigator.mimeTypes.length > 0 ) {
1257 - for ( var i = 0; i < navigator.mimeTypes.length; i++ ) {
1258 - var type = navigator.mimeTypes[i].type;
1259 - var semicolonPos = type.indexOf( ';' );
1260 - if ( semicolonPos > -1 ) {
1261 - type = type.substr( 0, semicolonPos );
1262 - }
1263 - if (type == 'application/x-shockwave-flash' ) {
1264 - // flash is installed
1265 - return true;
1266 - }
1267 - }
1268 - }
1269 -
1270 - // for IE:
1271 - var hasObj = true;
1272 - if( typeof ActiveXObject != 'undefined' ){
1273 - try {
1274 - var obj = new ActiveXObject( 'ShockwaveFlash.ShockwaveFlash' );
1275 - } catch ( e ) {
1276 - hasObj = false;
1277 - }
1278 - if( hasObj ){
1279 - return true;
1280 - }
1281 - }
1282 - return false;
1283 - };
1284 - /**
1285 - * Similar to php isset function checks if the variable exists. Does a safe
1286 - * check of a descendant method or variable
1287 - *
1288 - * @param {String}
1289 - * objectPath
1290 - * @return {Boolean} true if objectPath exists false if objectPath is
1291 - * undefined
1292 - */
1293 - mw.isset = function( objectPath ) {
1294 - if ( !objectPath || typeof objectPath != 'string') {
1295 - return false;
1296 - }
1297 - var pathSet = objectPath.split( '.' );
1298 - var cur_path = '';
1299 -
1300 - for ( var p = 0; p < pathSet.length; p++ ) {
1301 - cur_path = ( cur_path == '' ) ? cur_path + pathSet[p] : cur_path + '.' + pathSet[p];
1302 - eval( 'var ptest = typeof ( ' + cur_path + ' ); ' );
1303 - if ( ptest == 'undefined' ) {
1304 - return false;
1305 - }
1306 - }
1307 - return true;
1308 - };
1309 -
1310 - /**
1311 - * Wait for a object to be defined and the call the callback
1312 - *
1313 - * @param {Object}
1314 - * objectName Name of object to be defined
1315 - * @param {Function}
1316 - * callback Function to call once object is defined
1317 - * @param {Null}
1318 - * callNumber Used internally to keep track of number of times
1319 - * waitForObject has been called
1320 - */
1321 - var waitTime = 1200; // About 30 seconds
1322 - mw.waitForObject = function( objectName, callback, _callNumber) {
1323 - // mw.log( 'waitForObject: ' + objectName + ' cn: ' + _callNumber);
1324 -
1325 - // Increment callNumber:
1326 - if( !_callNumber ) {
1327 - _callNumber = 1;
1328 - } else {
1329 - _callNumber++;
1330 - }
1331 -
1332 - if( _callNumber > waitTime ) {
1333 - mw.log( "Error: waiting for object: " + objectName + ' timeout ' );
1334 - callback( false );
1335 - return ;
1336 - }
1337 -
1338 - // If the object is defined ( or we are done loading from a callback )
1339 - if ( mw.isset( objectName ) || mwLoadDoneCB[ objectName ] == 'done' ) {
1340 - callback( objectName );
1341 - }else{
1342 - setTimeout( function( ) {
1343 - mw.waitForObject( objectName, callback, _callNumber);
1344 - }, 25);
1345 - }
1346 - };
1347 -
1348 - /**
1349 - * Check if an object is empty or if its an empty string.
1350 - *
1351 - * @param {Object}
1352 - * object Object to be checked
1353 - */
1354 - mw.isEmpty = function( object ) {
1355 - if( typeof object == 'string' ) {
1356 - if( object == '' ) return true;
1357 - // Non empty string:
1358 - return false;
1359 - }
1360 -
1361 - // If an array check length:
1362 - if( Object.prototype.toString.call( object ) === "[object Array]"
1363 - && object.length == 0 ) {
1364 - return true;
1365 - }
1366 -
1367 - // Else check as an object:
1368 - for( var i in object ) { return false; }
1369 -
1370 - // Else object is empty:
1371 - return true;
1372 - };
1373 -
1374 - /**
1375 - * Log a string msg to the console
1376 - *
1377 - * all mw.log statements will be removed on minification so lots of mw.log
1378 - * calls will not impact performance in non debug mode
1379 - *
1380 - * @param {String}
1381 - * string String to output to console
1382 - */
1383 - mw.log = function( string ) {
1384 - // Add any prepend debug strings if necessary
1385 - if ( mw.getConfig( 'Mw.LogPrepend' ) ){
1386 - string = mw.getConfig( 'Mw.LogPrepend' ) + string;
1387 - }
1388 - // To debug stack size ( useful for iPad / safari that have a 100 call
1389 - // stack limit
1390 - // string = mw.getCallStack().length -1 + ' : ' + string;
1391 -
1392 - if ( window.console ) {
1393 - window.console.log( string );
1394 - } else {
1395 - /**
1396 - * Old IE and non-Firebug debug: ( commented out for now )
1397 - */
1398 -
1399 - /*
1400 - * var log_elm = document.getElementById('mv_js_log'); if(!log_elm) {
1401 - * document.getElementsByTagName("body")[0].innerHTML += '<div ' +
1402 - * 'style="position:absolute;z-index:500;bottom:0px;left:0px;right:0px;height:200px;">' + '<textarea
1403 - * id="mv_js_log" cols="120" rows="12"></textarea>' + '</div>'; }
1404 - * var log_elm = document.getElementById('mv_js_log'); if(log_elm) {
1405 - * log_elm.value+=string+"\n"; // scroll to bottom:
1406 - * log_elm.scrollTop = log_elm.scrollHeight; }
1407 - */
1408 - }
1409 - };
1410 - mw.getCallStack = function(){
1411 - var stringifyArguments = function(args) {
1412 - for (var i = 0; i < args.length; ++i) {
1413 - var arg = args[i];
1414 - if (arg === undefined) {
1415 - args[i] = 'undefined';
1416 - } else if (arg === null) {
1417 - args[i] = 'null';
1418 - } else if (arg.constructor) {
1419 - if (arg.constructor === Array) {
1420 - if (arg.length < 3) {
1421 - args[i] = '[' + stringifyArguments(arg) + ']';
1422 - } else {
1423 - args[i] = '[' + stringifyArguments(Array.prototype.slice.call(arg, 0, 1)) + '...' + stringifyArguments(Array.prototype.slice.call(arg, -1)) + ']';
1424 - }
1425 - } else if (arg.constructor === Object) {
1426 - args[i] = '#object';
1427 - } else if (arg.constructor === Function) {
1428 - args[i] = '#function';
1429 - } else if (arg.constructor === String) {
1430 - args[i] = '"' + arg + '"';
1431 - }
1432 - }
1433 - }
1434 - return args.join(',');
1435 - };
1436 - var getStack = function(curr){
1437 - var ANON = '{anonymous}', fnRE = /function\s*([\w\-$]+)?\s*\(/i,
1438 - stack = [], fn, args, maxStackSize = 100;
1439 -
1440 - while (curr && stack.length < maxStackSize) {
1441 - fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON;
1442 - args = Array.prototype.slice.call(curr['arguments']);
1443 - stack[stack.length] = fn + '(' + stringifyArguments(args) + ')';
1444 - curr = curr.caller;
1445 - }
1446 - return stack;
1447 - }
1448 - // Add stack size ( iPad has 100 stack size limit )
1449 - var stack = getStack( arguments.callee );
1450 - return stack;
1451 - }
1452 -
1453 - // Setup the local mwOnLoadFunctions array:
1454 - var mwOnLoadFunctions = [];
1455 -
1456 - // mw Ready flag ( set once mwEmbed is ready )
1457 - var mwReadyFlag = false;
1458 -
1459 - /**
1460 - * Enables load hooks to run once mwEmbeed is "ready" Will ensure jQuery is
1461 - * available, is in the $j namespace and mw interfaces and configuration has
1462 - * been loaded and applied
1463 - *
1464 - * This is different from jQuery(document).ready() ( jQuery ready is not
1465 - * friendly with dynamic includes and not friendly with core interface
1466 - * asynchronous build out. )
1467 - *
1468 - * @param {Function}
1469 - * callback Function to run once DOM and jQuery are ready
1470 - */
1471 - mw.ready = function( callback ) {
1472 - if( mwReadyFlag === false ) {
1473 - // Add the callbcak to the onLoad function stack
1474 - mwOnLoadFunctions.push ( callback );
1475 - } else {
1476 - // If mwReadyFlag is already "true" issue the callback directly:
1477 - callback();
1478 - }
1479 - };
1480 -
1481 - /**
1482 - * Runs all the queued functions called by mwEmbedSetup
1483 - */
1484 - mw.runReadyFunctions = function ( ) {
1485 - mw.log('mw.runReadyFunctions: ' + mwOnLoadFunctions.length );
1486 - // Run any pre-setup ready functions
1487 - while( preMwEmbedReady.length ){
1488 - preMwEmbedReady.shift()();
1489 - }
1490 - // Run all the queued functions:
1491 - while( mwOnLoadFunctions.length ) {
1492 - mwOnLoadFunctions.shift()();
1493 - }
1494 - // Sets mwReadyFlag to true so that future mw.ready run the
1495 - // callback directly
1496 - mwReadyFlag = true;
1497 -
1498 - // Once we have run all the queued functions
1499 - setTimeout(function(){
1500 - mw.loader.runModuleLoadQueue();
1501 - },1);
1502 - };
1503 -
1504 -
1505 - /**
1506 - * Wrapper for jQuery getScript, Uses the scriptLoader if enabled
1507 - *
1508 - *
1509 - * @param {String}
1510 - * scriptRequest The requested path or resourceNames for the
1511 - * scriptLoader
1512 - * @param {Function}
1513 - * callback Function to call once script is loaded
1514 - */
1515 - mw.getScript = function( scriptRequest, callback ) {
1516 - // mw.log( "mw.getScript::" + scriptRequest );
1517 - // Setup the local scope callback instace
1518 - var myCallback = function(){
1519 - if( callback ) {
1520 - callback( scriptRequest );
1521 - }
1522 - };
1523 - // Set the base url based scriptLoader availability & type of
1524 - // scriptRequest
1525 - // ( presently script loader only handles "classes" not relative urls:
1526 - var scriptLoaderPath = mw.getResourceLoaderPath();
1527 -
1528 - // Check if its a resource name, ( ie does not start with "/" and does
1529 - // not include ://
1530 - var isResourceName = ( scriptRequest.indexOf('://') == -1 && scriptRequest.indexOf('/') !== 0 )? true : false;
1531 -
1532 - var ext = scriptRequest.substr( scriptRequest.lastIndexOf( '.' ), 4 ).toLowerCase();
1533 - var isCssFile = ( ext == '.css') ? true : false ;
1534 -
1535 - if( scriptLoaderPath && isResourceName ) {
1536 - url = scriptLoaderPath + '?class=' + scriptRequest ;
1537 - } else {
1538 - // Add the mwEmbed path if a relative path request
1539 - url = ( isResourceName ) ? mw.getMwEmbedPath() : '';
1540 - url+= scriptRequest;
1541 - }
1542 -
1543 - // Add on the request parameters to the url:
1544 - url += ( url.indexOf( '?' ) == -1 )? '?' : '&';
1545 - url += mw.getUrlParam();
1546 -
1547 - // Only log sciprts ( Css is logged via "add css" )
1548 - if( !isCssFile ){
1549 - mw.log( 'mw.getScript: ' + url );
1550 - }
1551 -
1552 - // If jQuery is available and debug is off load the script via jQuery
1553 - // ( will use XHR if on same domain )
1554 - if( mw.isset( 'window.jQuery' )
1555 - && mw.getConfig( 'debug' ) === false
1556 - && typeof $j != 'undefined'
1557 - && mw.parseUri( url ).protocal != 'file'
1558 - && !isCssFile )
1559 - {
1560 - $j.getScript( url, myCallback);
1561 - return ;
1562 - }
1563 -
1564 - /**
1565 - * No jQuery OR In debug mode OR Is css file :: inject the script
1566 - * instead of doing an XHR eval
1567 - */
1568 -
1569 - // load style sheet directly if requested loading css
1570 - if( isCssFile ){
1571 - mw.getStyleSheet( url, myCallback);
1572 - return ;
1573 - }
1574 -
1575 - // Load and bind manually: ( copied from jQuery ajax function )
1576 - var head = document.getElementsByTagName("head")[ 0 ];
1577 - var script = document.createElement("script");
1578 - script.setAttribute( 'src', url );
1579 -
1580 - // Attach handlers ( if using script loader it issues onDone callback as
1581 - // well )
1582 - script.onload = script.onreadystatechange = function() {
1583 - if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") {
1584 - myCallback();
1585 - }
1586 - };
1587 - // mw.log(" append script: " + script.src );
1588 - // Append the script to the DOM:
1589 - head.appendChild( script );
1590 - };
1591 -
1592 - /**
1593 - * Add a style sheet string to the document head
1594 - *
1595 - * @param {String}
1596 - * cssResourceName Name of style sheet that has been defined
1597 - * @param {String}
1598 - * cssString Css Payload to be added to head of document
1599 - */
1600 - mw.addStyleString = function( cssResourceName, cssString ) {
1601 - if( mw.style[ cssResourceName ] ) {
1602 - mw.log(" Style: ( " + cssResourceName + ' ) already set' );
1603 - return true;
1604 - }
1605 - // Set the style to true ( to not request it again )
1606 - mw.style[ cssResourceName ] = true;
1607 - // Add the spinner directly ( without jQuery in case we have to
1608 - // dynamically load jQuery )
1609 - mw.log( 'Adding style:' + cssResourceName + " to dom " );
1610 - var styleNode = document.createElement('style');
1611 - styleNode.type = "text/css";
1612 - // Use cssText or createTextNode depending on browser:
1613 - if( ( window.attachEvent && !window.opera ) ) {
1614 - styleNode.styleSheet.cssText = cssString;
1615 - } else {
1616 - var styleText = document.createTextNode( cssString );
1617 - styleNode.appendChild( styleText );
1618 - }
1619 - var head = document.getElementsByTagName("head")[0];
1620 - head.appendChild( styleNode );
1621 - };
1622 -
1623 - /**
1624 - * Get a style sheet and append the style sheet to the DOM
1625 - *
1626 - * @param {Mixed}
1627 - * {String} url Url of the style sheet to be loaded {Function}
1628 - * callback Function called once sheet is ready
1629 - */
1630 - mw.getStyleSheet = function( url , callback) {
1631 - // Add URL params ( if not already included )
1632 - if ( url.indexOf( '?' ) == -1 ) {
1633 - url += '?' + mw.getUrlParam();
1634 - }
1635 -
1636 - // Check if style sheet is already included:
1637 - var foundSheet = false;
1638 - $j( 'link' ).each( function() {
1639 - var currentSheet = $j( this) .attr( 'href' );
1640 - var sheetParts = currentSheet.split('?');
1641 - var urlParts = url.split('?');
1642 - // if the base url's match check the parameters:
1643 - if( sheetParts[0] == urlParts[0] && sheetParts[1]) {
1644 - // Check if url params match ( sort to do string compare )
1645 - if( sheetParts[1].split( '&' ).sort().join('') ==
1646 - urlParts[1].split('&').sort().join('') ) {
1647 - foundSheet = true;
1648 - }
1649 - }
1650 - } );
1651 - if( foundSheet ) {
1652 - mw.log( 'skiped sheet: ' + url);
1653 - if( callback) {
1654 - callback();
1655 - }
1656 - return ;
1657 - }
1658 -
1659 - mw.log( ' add css: ' + url );
1660 - $j( 'head' ).append(
1661 - $j('<link />').attr( {
1662 - 'rel' : 'stylesheet',
1663 - 'type' : 'text/css',
1664 - 'href' : url
1665 - } )
1666 - );
1667 - // No easy way to check css "onLoad" attribute
1668 - // In production sheets are loaded via resource loader and fire the
1669 - // onDone function call.
1670 - if( callback ) {
1671 - callback();
1672 - }
1673 - };
1674 -
1675 - mw.getRelativeMwEmbedPath = function(){
1676 - return mw.getMwEmbedPath(true);
1677 - };
1678 - /**
1679 - * Get the path to the mwEmbed folder
1680 - */
1681 - mw.getMwEmbedPath = function( relativePath ) {
1682 - // Get mwEmbed src:
1683 - var src = mw.getMwEmbedSrc();
1684 - var mwpath = null;
1685 -
1686 - // Check for direct include of the mwEmbed.js
1687 - if ( src.indexOf( 'mwEmbed.js' ) !== -1 ) {
1688 - alert( 'Direct Refrece to mwEmbed is no longer suported, please update to ResourceLoader.php?class=window.jQuery,mwEmbed& instead');
1689 - mwpath = src.substr( 0, src.indexOf( 'mwEmbed.js' ) );
1690 - }
1691 -
1692 - // Check for scriptLoader include of mwEmbed:
1693 - if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 ) {
1694 - // Script loader is in the root of MediaWiki, Include the default
1695 - // mwEmbed extension path:
1696 - mwpath = src.substr( 0, src.indexOf( 'mwResourceLoader.php' ) ) + mw.getConfig( 'mediaWikiEmbedPath' );
1697 - }
1698 -
1699 - // resource loader has ResourceLoader name when local:
1700 - if( src.indexOf( 'ResourceLoader.php' ) !== -1 ) {
1701 - mwpath = src.substr( 0, src.indexOf( 'ResourceLoader.php' ) );
1702 - }
1703 -
1704 - // For static packages mwEmbed packages start with: "mwEmbed-"
1705 - if( src.indexOf( 'mwEmbed-' ) !== -1 && src.indexOf( '-static' ) !== -1 ) {
1706 - mwpath = src.substr( 0, src.indexOf( 'mwEmbed-' ) );
1707 - }
1708 -
1709 - // Error out if we could not get the path:
1710 - if( mwpath === null ) {
1711 - mw.log( "Error could not get mwEmbed path " );
1712 - return ;
1713 - }
1714 -
1715 - // Update the cached var with the absolute path:
1716 - if( !relativePath ){
1717 - mwpath = mw.absoluteUrl( mwpath ) ;
1718 - }
1719 - return mwpath;
1720 - };
1721 -
1722 - /**
1723 - * Get Script loader path
1724 - *
1725 - * @returns {String}|{Boolean} Url of the scriptLodaer false if the
1726 - * scriptLoader is not used
1727 - */
1728 - mw.getResourceLoaderPath = function( ) {
1729 - var src = mw.getMwEmbedSrc();
1730 - if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 ||
1731 - src.indexOf( 'ResourceLoader.php' ) !== -1 )
1732 - {
1733 - // Return just the script part of the url
1734 - return src.split('?')[0];
1735 - }
1736 - return false;
1737 - };
1738 - /**
1739 - * Given a float number of seconds, returns npt format response. ( ignore
1740 - * days for now )
1741 - *
1742 - * @param {Float}
1743 - * sec Seconds
1744 - * @param {Boolean}
1745 - * verbose If hours and milliseconds should padded be displayed.
1746 - * @return {Float} String npt format
1747 - */
1748 - mw.seconds2npt = function( sec, verbose ) {
1749 - if ( isNaN( sec ) ) {
1750 - mw.log("Warning: trying to get npt time on NaN:" + sec);
1751 - return '0:00:00';
1752 - }
1753 -
1754 - var tm = mw.seconds2Measurements( sec );
1755 -
1756 - // Round the number of seconds to the required number of significant
1757 - // digits
1758 - if ( verbose ) {
1759 - tm.seconds = Math.round( tm.seconds * 1000 ) / 1000;
1760 - } else {
1761 - tm.seconds = Math.round( tm.seconds );
1762 - }
1763 - if ( tm.seconds < 10 ){
1764 - tm.seconds = '0' + tm.seconds;
1765 - }
1766 - if( tm.hours == 0 && !verbose ){
1767 - hoursStr = '';
1768 - } else {
1769 - if ( tm.minutes < 10 && verbose) {
1770 - tm.minutes = '0' + tm.minutes;
1771 - }
1772 -
1773 - if( tm.hours < 10 && verbose){
1774 - tm.hours = '0' + tm.hours;
1775 - }
1776 -
1777 - hoursStr = tm.hours + ':';
1778 - }
1779 - return hoursStr + tm.minutes + ":" + tm.seconds;
1780 - };
1781 - /**
1782 - * Given seconds return array with 'days', 'hours', 'min', 'seconds'
1783 - *
1784 - * @param {float}
1785 - * sec Seconds to be converted into time measurements
1786 - */
1787 - mw.seconds2Measurements = function ( sec ){
1788 - var tm = {};
1789 - tm.days = Math.floor( sec / ( 3600 * 24 ) );
1790 - tm.hours = Math.floor( sec / 3600 );
1791 - tm.minutes = Math.floor( ( sec / 60 ) % 60 );
1792 - tm.seconds = sec % 60;
1793 - return tm;
1794 - };
1795 -
1796 - /**
1797 - * Given a float number of seconds, returns npt format response. ( ignore
1798 - * days for now )
1799 - *
1800 - * @param {Float}
1801 - * sec Seconds
1802 - * @param {Boolean}
1803 - * verbose If hours and milliseconds should padded be displayed.
1804 - * @return {Float} String npt format
1805 - */
1806 - mw.npt2seconds = function ( npt_str ) {
1807 - if ( !npt_str ) {
1808 - // mw.log('npt2seconds:not valid ntp:'+ntp);
1809 - return false;
1810 - }
1811 - // Strip {npt:}01:02:20 or 32{s} from time if present
1812 - npt_str = npt_str.replace( /npt:|s/g, '' );
1813 -
1814 - var hour = 0;
1815 - var min = 0;
1816 - var sec = 0;
1817 -
1818 - times = npt_str.split( ':' );
1819 - if ( times.length == 3 ) {
1820 - sec = times[2];
1821 - min = times[1];
1822 - hour = times[0];
1823 - } else if ( times.length == 2 ) {
1824 - sec = times[1];
1825 - min = times[0];
1826 - } else {
1827 - sec = times[0];
1828 - }
1829 - // Sometimes a comma is used instead of period for ms
1830 - sec = sec.replace( /,\s?/, '.' );
1831 - // Return seconds float
1832 - return parseInt( hour * 3600 ) + parseInt( min * 60 ) + parseFloat( sec );
1833 - };
1834 -
1835 - // Local mwEmbedSrc variable ( for cache of mw.getMwEmbedSrc )
1836 - var mwEmbedSrc = null;
1837 -
1838 - /**
1839 - * Gets the mwEmbed script src attribute
1840 - */
1841 - mw.getMwEmbedSrc = function() {
1842 - if ( mwEmbedSrc ) {
1843 - return mwEmbedSrc;
1844 - }
1845 -
1846 - // Get all the javascript includes:
1847 - var js_elements = document.getElementsByTagName( "script" );
1848 - for ( var i = 0; i < js_elements.length; i++ ) {
1849 - // Check for mwEmbed.js and/or script loader
1850 - var src = js_elements[i].getAttribute( "src" );
1851 - if ( src ) {
1852 - if ( // Check for mwEmbed.js ( debug mode )
1853 - ( src.indexOf( 'mwEmbed.js' ) !== -1 && src.indexOf( 'MediaWiki:Gadget') == -1 )
1854 - || // Check for resource loader
1855 - (
1856 - ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || src.indexOf( 'ResourceLoader.php' ) !== -1 )
1857 - &&
1858 - src.indexOf( 'mwEmbed' ) !== -1
1859 - )
1860 - || // Check for static mwEmbed package
1861 - ( src.indexOf( 'mwEmbed' ) !== -1 && src.indexOf( 'static' ) !== -1 )
1862 - ) {
1863 - mwEmbedSrc = src;
1864 - return mwEmbedSrc;
1865 - }
1866 - }
1867 - }
1868 - mw.log( 'Error: getMwEmbedSrc failed to get script path' );
1869 - return false;
1870 - };
1871 -
1872 - // Local mwUrlParam variable ( for cache of mw.getUrlParam )
1873 - var mwUrlParam = null;
1874 -
1875 - /**
1876 - * Get URL Parameters per parameters in the host script include
1877 - */
1878 - mw.getUrlParam = function() {
1879 - if ( mwUrlParam ) {
1880 - return mwUrlParam;
1881 - }
1882 -
1883 - var mwEmbedSrc = mw.getMwEmbedSrc();
1884 - var req_param = '';
1885 -
1886 - // If we already have a URI, add it to the param request:
1887 - var urid = mw.parseUri( mwEmbedSrc ).queryKey['urid'];
1888 -
1889 - // If we're in debug mode, get a fresh unique request key and pass on
1890 - // "debug" param
1891 - if ( mw.parseUri( mwEmbedSrc ).queryKey['debug'] == 'true' ) {
1892 - mw.setConfig( 'debug', true );
1893 - var d = new Date();
1894 - req_param += 'urid=' + d.getTime() + '&debug=true';
1895 -
1896 - } else if ( urid ) {
1897 - // Just pass on the existing urid:
1898 - req_param += 'urid=' + urid;
1899 - } else {
1900 - // Otherwise, Use the mwEmbed version
1901 - req_param += 'urid=' + mw.version;
1902 - }
1903 -
1904 - // Add the language param if present:
1905 - var langKey = mw.parseUri( mwEmbedSrc ).queryKey['uselang'];
1906 - if ( langKey )
1907 - req_param += '&uselang=' + langKey;
1908 -
1909 - // Update the local cache and return the value
1910 - mwUrlParam = req_param;
1911 - return mwUrlParam;
1912 - };
1913 -
1914 - /**
1915 - * Replace url parameters via newParams key value pairs
1916 - *
1917 - * @param {String}
1918 - * url Source url to be updated
1919 - * @param {Object}
1920 - * newParams key, value paris to swap in
1921 - * @return {String} the updated url
1922 - */
1923 - mw.replaceUrlParams = function( url, newParams ) {
1924 - var parsedUrl = mw.parseUri( url );
1925 -
1926 - if ( parsedUrl.protocol != '' ) {
1927 - var new_url = parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.path + '?';
1928 - } else {
1929 - var new_url = parsedUrl.path + '?';
1930 - }
1931 -
1932 - // Merge new params:
1933 - for( var key in newParams ) {
1934 - parsedUrl.queryKey[ key ] = newParams[ key ];
1935 - }
1936 -
1937 - // Output to new_url
1938 - var amp = '';
1939 - for ( var key in parsedUrl.queryKey ) {
1940 - var val = parsedUrl.queryKey[ key ];
1941 - new_url += amp + key + '=' + val;
1942 - amp = '&';
1943 - }
1944 - return new_url;
1945 - };
1946 -
1947 - /**
1948 - * parseUri 1.2.2 (c) Steven Levithan <stevenlevithan.com> MIT License
1949 - */
1950 - mw.parseUri = function (str) {
1951 - var o = mw.parseUri.options,
1952 - m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
1953 - uri = {},
1954 - i = 14;
1955 -
1956 - while (i--) uri[o.key[i]] = m[i] || "";
1957 -
1958 - uri[o.q.name] = {};
1959 - uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
1960 - if ($1) uri[o.q.name][$1] = $2;
1961 - });
1962 -
1963 - return uri;
1964 - };
1965 -
1966 - /**
1967 - * Parse URI function
1968 - *
1969 - * For documentation on its usage see:
1970 - * http://stevenlevithan.com/demo/parseuri/js/
1971 - */
1972 - mw.parseUri.options = {
1973 - strictMode: false,
1974 - key: ["source", "protocol", "authority", "userInfo", "user", "password", "host",
1975 - "port", "relative", "path", "directory", "file", "query", "anchor"],
1976 - q: {
1977 - name: "queryKey",
1978 - parser: /(?:^|&)([^&=]*)=?([^&]*)/g
1979 - },
1980 - parser: {
1981 - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
1982 - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
1983 - }
1984 - };
1985 -
1986 - /**
1987 - * getAbsoluteUrl takes a src and returns the absolute location given the
1988 - * document.URL or a contextUrl param
1989 - *
1990 - * @param {String}
1991 - * src path or url
1992 - * @param {String}
1993 - * contextUrl The domain / context for creating an absolute url
1994 - * from a relative path
1995 - * @return {String} absolute url
1996 - */
1997 -mw.absoluteUrl = function( src, contextUrl ) {
1998 -
1999 - var parsedSrc = mw.parseUri( src );
2000 -
2001 - // Source is already absolute return:
2002 - if( parsedSrc.protocol != '') {
2003 - return src;
2004 - }
2005 -
2006 - // Get parent Url location the context URL
2007 - if( !contextUrl ) {
2008 - contextUrl = document.URL;
2009 - }
2010 - var parsedUrl = mw.parseUri( contextUrl );
2011 -
2012 - // Check for IE local file that does not flip the slashes
2013 - if( parsedUrl.directory == '' && parsedUrl.protocol == 'file' ){
2014 - // pop off the file
2015 - var fileUrl = contextUrl.split( '\\');
2016 - fileUrl.pop();
2017 - return fileUrl.join('\\') + '\\' + src;
2018 - }
2019 -
2020 - // Check for leading slash:
2021 - if( src.indexOf( '/' ) === 0 ) {
2022 - return parsedUrl.protocol + '://' + parsedUrl.authority + src;
2023 - }else{
2024 - return parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.directory + src;
2025 - }
2026 - };
2027 - /**
2028 - * Check if a given source string is likely a url
2029 - *
2030 - * @return {boolean} true if a url false if a string
2031 - */
2032 - mw.isUrl = function( src ){
2033 - var parsedSrc = mw.parseUri( src );
2034 - // if the url is just a string source and host will match
2035 - return ( parsedSrc.host != parsedSrc.source );
2036 - };
2037 -
2038 - /**
2039 - * Escape quotes in a text string
2040 - *
2041 - * @param {String}
2042 - * text String to be escaped
2043 - * @return {string} escaped text string
2044 - */
2045 - mw.escapeQuotes = function( text ) {
2046 - var re = new RegExp("'","g");
2047 - text = text.replace(re,"\\'");
2048 - re = new RegExp("\\n","g");
2049 - text = text.replace(re,"\\n");
2050 - return mw.escapeQuotesHTML(text);
2051 - };
2052 -
2053 - /**
2054 - * Escape an HTML text string
2055 - *
2056 - * @param {String}
2057 - * text String to be escaped
2058 - * @return {string} escaped text html string
2059 - */
2060 - mw.escapeQuotesHTML = function( text ) {
2061 - var replaceMap = {
2062 - "&" : "&amp;",
2063 - '"' : "&quot;",
2064 - '<' : "&lt;",
2065 - '>' : "&gt;"
2066 - };
2067 - for( var i in replaceMap ){
2068 - text = text.split(i).join( replaceMap[i]);
2069 - }
2070 - return text;
2071 - };
2072 -
2073 -
2074 - // Array of setup functions
2075 - var mwSetupFunctions = [];
2076 -
2077 - /**
2078 - * Add a function to be run during setup ( prior to mw.ready) this is useful
2079 - * for building out interfaces that should be ready before mw.ready is
2080 - * called.
2081 - *
2082 - * @param {callback}
2083 - * Function Callback function must accept a ready function
2084 - * callback to be called once setup is done
2085 - */
2086 - mw.addSetupHook = function( callback ) {
2087 - mwSetupFunctions.push ( callback ) ;
2088 - };
2089 -
2090 - /**
2091 - * One time "setup" for mwEmbed run onDomReady ( so calls to setConfg apply
2092 - * to setup )
2093 - */
2094 - // Flag to ensure setup is only run once:
2095 - var mwSetupFlag = false;
2096 - mw.setupMwEmbed = function ( ) {
2097 - // Only run the setup once:
2098 - if( mwSetupFlag ) {
2099 - return ;
2100 - }
2101 - mwSetupFlag = true;
2102 -
2103 - mw.log( 'mw:setupMwEmbed SRC:: ' + mw.getMwEmbedSrc() );
2104 -
2105 - // Check core mwEmbed loader.js file ( to get configuration and paths )
2106 - mw.checkCoreLoaderFile( function(){
2107 - // Make sure we have jQuery
2108 - mw.load( 'window.jQuery', function() {
2109 -
2110 - // Add jQuery to $j var.
2111 - if ( ! window[ '$j' ] ) {
2112 - window[ '$j' ] = jQuery.noConflict();
2113 - }
2114 -
2115 - // Set up mvEmbed utility jQuery bindings
2116 - mw.dojQueryBindings();
2117 -
2118 - // Setup user config:
2119 - mw.setupUserConfig( function(){
2120 - // Get module loader.js, and language files
2121 - // ( will hit callback directly if set via resource loader )
2122 - mw.checkModuleLoaderFiles( function() {
2123 -
2124 - // Set the User language
2125 - if( typeof wgUserLanguage != 'undefined' && mw.isValidLang( wgUserLanguage) ) {
2126 - mw.setConfig( 'userLanguage', wgUserLanguage );
2127 - }else{
2128 - // Grab it from the included url
2129 - var langKey = mw.parseUri( mw.getMwEmbedSrc() ).queryKey['uselang'];
2130 - if ( langKey && mw.isValidLang( langKey ) ) {
2131 - mw.setConfig( 'userLanguage', langKey);
2132 - }
2133 - }
2134 -
2135 - // Update the image path
2136 - mw.setConfig( 'imagesPath', mw.getMwEmbedPath() + 'skins/common/images/' );
2137 -
2138 - // Set up AJAX to not send dynamic URLs for loading
2139 - // scripts
2140 - $j.ajaxSetup( {
2141 - cache: true
2142 - } );
2143 -
2144 - // Update the magic keywords
2145 - mw.Language.magicSetup();
2146 -
2147 -
2148 - // Special Hack for conditional jquery ui inclusion (
2149 - // once
2150 - // Usability extension
2151 - // registers the jquery.ui skin in mw.style
2152 - if( mw.hasJQueryUiCss() ){
2153 - mw.style[ 'ui_' + mw.getConfig( 'jQueryUISkin' ) ] = true;
2154 - }
2155 -
2156 -
2157 - // Make sure style sheets are loaded:
2158 - mw.load( ['mw.style.mwCommon'] , function(){
2159 - // Run all the setup function hooks
2160 - // NOTE: setup functions are added via addSetupHook
2161 - // calls
2162 - // and must include a callback.
2163 - //
2164 - // Once complete we can run .ready() queued
2165 - // functions
2166 - function runSetupFunctions() {
2167 - if( mwSetupFunctions.length ) {
2168 - mwSetupFunctions.shift()( function() {
2169 - runSetupFunctions();
2170 - } );
2171 - }else{
2172 - mw.runReadyFunctions();
2173 - }
2174 - }
2175 - runSetupFunctions();
2176 - } );
2177 -
2178 - } );
2179 - });
2180 - });
2181 - });
2182 - };
2183 -
2184 - /**
2185 - * Checks for jquery ui css by name jquery-ui-1.7.2.css NOTE: this is a hack
2186 - * for usability jquery-ui in the future usability should register a
2187 - * resource in mw.skin
2188 - *
2189 - * @return true if found, return false if not found
2190 - */
2191 - mw.hasJQueryUiCss = function(){
2192 - var hasUiCss = false;
2193 - var cssStyleSheetNames = ['jquery-ui-1.7.2.css', 'jquery-ui.css'];
2194 - // Load the jQuery ui skin if usability skin not set
2195 - $j( 'link' ).each( function( na, linkNode ){
2196 - $j.each( cssStyleSheetNames, function(inx, sheetName ){
2197 - if( $j( linkNode ).attr( 'href' ).indexOf( sheetName ) != -1 ){
2198 - hasUiCss = true;
2199 - return true;
2200 - }
2201 - });
2202 - } );
2203 - // Check all the "style" nodes for @import for sheet name
2204 - // xxx Note: we could do this a bit cleaner with regEx
2205 - $j( 'style' ).each( function( na, styleNode ){
2206 - $j.each( cssStyleSheetNames, function(inx, sheetName ){
2207 - if( $j( styleNode ).text().indexOf( '@import' ) != -1
2208 - &&
2209 - $j( styleNode ).text().indexOf( sheetName ) != -1 )
2210 - {
2211 - hasUiCss=true;
2212 - return true;
2213 - }
2214 - });
2215 - });
2216 - return hasUiCss;
2217 - };
2218 -
2219 - /**
2220 - * Loads the core mwEmbed "loader.js" file config
2221 - *
2222 - * NOTE: if using the ScriptLoader all the loaders and localization
2223 - * converters are included automatically
2224 - *
2225 - * @param {Function}
2226 - * callback Function called once core loader file is loaded
2227 - */
2228 - mw.checkCoreLoaderFile = function( callback ) {
2229 - // Check if we are using scriptloader ( handles loader include
2230 - // automatically )
2231 - if( mw.getResourceLoaderPath() ) {
2232 - callback();
2233 - return ;
2234 - }
2235 -
2236 - // Check if we are using a static package ( mwEmbed path includes
2237 - // -static )
2238 - if( mw.isStaticPackge() ){
2239 - callback();
2240 - return ;
2241 - }
2242 -
2243 - // Add the Core loader to the request
2244 - // The follow code is ONLY RUN in debug / raw file mode
2245 - mw.load( 'loader.js', callback );
2246 - };
2247 -
2248 - /**
2249 - * Checks if the javascript is a static package ( not using resource loader )
2250 - *
2251 - * @return {boolean} true the included script is static false the included
2252 - * script
2253 - */
2254 - mw.isStaticPackge = function(){
2255 - var src = mw.getMwEmbedSrc();
2256 - if( src.indexOf('-static') !== -1 ){
2257 - return true;
2258 - }
2259 - return false;
2260 - };
2261 -
2262 - /**
2263 - * Check for resource loader module loaders, and localization files
2264 - *
2265 - * NOTE: if using the ScriptLoader all the loaders and localization
2266 - * converters are included automatically.
2267 - */
2268 - mw.checkModuleLoaderFiles = function( callback ) {
2269 - mw.log( 'doLoaderCheck::' );
2270 -
2271 - // Check if we are using scriptloader ( handles loader include
2272 - // automatically )
2273 - // Or if mwEmbed is a static package ( all resources are already loaded
2274 - // )
2275 - if( mw.getResourceLoaderPath() || mw.isStaticPackge() ) {
2276 - callback();
2277 - return ;
2278 - }
2279 -
2280 - // Load the configured modules / components
2281 - // The follow code is ONLY RUN in debug / raw file mode
2282 - var loaderRequest = [];
2283 -
2284 - // Load enabled components
2285 - var enabledComponents = mw.getConfig( 'coreComponents' );
2286 - function loadEnabledComponents( enabledComponents ){
2287 - if( ! enabledComponents.length ){
2288 - // If no more components load modules::
2289 -
2290 - // Add the enabledModules loaders:
2291 - var enabledModules = mw.getConfig( 'enabledModules' );
2292 - loadEnabledModules( enabledModules );
2293 - return ;
2294 - }
2295 - var componentName = enabledComponents.shift();
2296 - componentName = componentName.replace(/"/g,'');
2297 - mw.load( componentName, function(){
2298 - loadEnabledComponents( enabledComponents );
2299 - } );
2300 - }
2301 - loadEnabledComponents( enabledComponents );
2302 -
2303 -
2304 - // Set the loader context and get each loader individually
2305 - function loadEnabledModules( enabledModules ){
2306 - if( ! enabledModules.length ){
2307 - // If no more modules left load the LanguageFile
2308 - addLanguageFile();
2309 - return ;
2310 - }
2311 - var moduleName = enabledModules.shift();
2312 - moduleName = moduleName.replace(/"/g,'');
2313 - mw.setConfig( 'loaderContext', 'modules/' + moduleName + '/' );
2314 - mw.load( 'modules/' + moduleName + '/loader.js', function(){
2315 - loadEnabledModules( enabledModules );
2316 - } );
2317 - }
2318 -
2319 - function addLanguageFile(){
2320 - // Add the language file
2321 - var langLoaderRequest = [];
2322 -
2323 - if( mw.getConfig( 'userLanguage' ) ) {
2324 - var langCode = mw.getConfig( 'userLanguage' );
2325 -
2326 - // Load the language resource if not default 'en'
2327 - var transformKey = mw.getLangTransformKey( langCode );
2328 - if( transformKey != 'en' ){
2329 - // Upper case the first letter:
2330 - langCode = langCode.substr(0,1).toUpperCase() + langCode.substr( 1, langCode.length );
2331 - langLoaderRequest.push( 'languages/classes/Language' +
2332 - langCode + '.js' );
2333 - }
2334 -
2335 - }
2336 - if ( ! langLoaderRequest.length ) {
2337 - addLocalSettings();
2338 - return ;
2339 - }
2340 -
2341 - // Load the language if set
2342 - mw.load( langLoaderRequest, function(){
2343 - mw.log( 'Done moduleLoaderCheck request' );
2344 - addLocalSettings();
2345 - } );
2346 - }
2347 - function addLocalSettings(){
2348 - var continueCallback = function(){
2349 - // Set the mwModuleLoaderCheckFlag flag to true
2350 - mwModuleLoaderCheckFlag = true;
2351 - callback();
2352 - };
2353 - if( mw.getConfig( 'LoadLocalSettings') != true ){
2354 - continueCallback();
2355 - return;
2356 - }
2357 - mw.log("Load loacal settings");
2358 - mw.load( 'localSettings.js', function(){
2359 - continueCallback();
2360 - });
2361 - }
2362 -
2363 - };
2364 -
2365 - /**
2366 - * Checks if a css style rule exists
2367 - *
2368 - * On a page with lots of rules it can take some time so avoid calling this
2369 - * function where possible and cache its result
2370 - *
2371 - * NOTE: this only works for style sheets on the same domain :(
2372 - *
2373 - * @param {String}
2374 - * styleRule Style rule name to check
2375 - * @return {Boolean} true if the rule exists false if the rule does not
2376 - * exist
2377 - */
2378 - mw.styleRuleExists = function ( styleRule ) {
2379 - // Set up the skin paths configuration
2380 - for( var i=0 ; i < document.styleSheets.length ; i++ ) {
2381 - var rules = null;
2382 - try{
2383 - if ( document.styleSheets[i].cssRules )
2384 - rules = document.styleSheets[i].cssRules;
2385 - else if (document.styleSheets[0].rules)
2386 - rules = document.styleSheets[i].rules;
2387 - for(var j=0 ; j < rules.length ; j++ ) {
2388 - var rule = rules[j].selectorText;
2389 - if( rule && rule.indexOf( styleRule ) != -1 ) {
2390 - return true;
2391 - }
2392 - }
2393 - }catch ( e ) {
2394 - mw.log( 'Error: cant check rule on cross domain style sheet:' + document.styleSheets[i].href );
2395 - }
2396 - }
2397 - return false;
2398 - };
2399 -
2400 - // Flag to register the domReady has been called
2401 - var mwDomReadyFlag = false;
2402 -
2403 - // Flag to register if the domreadyHooks have been called
2404 - var mwModuleLoaderCheckFlag = false;
2405 -
2406 - /**
2407 - * This will get called when the DOM is ready Will check configuration and
2408 - * issue a mw.setupMwEmbed call if needed
2409 - */
2410 - mw.domReady = function ( ) {
2411 - if( mwDomReadyFlag ) {
2412 - return ;
2413 - }
2414 - mw.log( 'run:domReady:: ' + document.getElementsByTagName('video').length );
2415 - // Set the onDomReady Flag
2416 - mwDomReadyFlag = true;
2417 -
2418 - // Give us a chance to get to the bottom of the script.
2419 - // When loading mwEmbed asynchronously the dom ready gets called
2420 - // directly and in some browsers beets the $j = jQuery.noConflict();
2421 - // call
2422 - // and causes symbol undefined errors.
2423 - setTimeout(function(){
2424 - mw.setupMwEmbed();
2425 - },1);
2426 - };
2427 -
2428 - /**
2429 - * A version comparison utility function Handles version of types
2430 - * {Major}.{MinorN}.{Patch}
2431 - *
2432 - * Note this just handles version numbers not patch letters.
2433 - *
2434 - * @param {String}
2435 - * minVersion Minnium version needed
2436 - * @param {String}
2437 - * clientVersion Client version to be checked
2438 - *
2439 - * @return true if the version is at least of minVersion false if the
2440 - * version is less than minVersion
2441 - */
2442 - mw.versionIsAtLeast = function( minVersion, clientVersion ) {
2443 - var minVersionParts = minVersion.split('.');
2444 - var clientVersionParts = clientVersion.split('.');
2445 - for( var i =0; i < minVersionParts.length; i++ ) {
2446 - if( parseInt( clientVersionParts[i] ) > parseInt( minVersionParts[i] ) ) {
2447 - return true;
2448 - }
2449 - if( parseInt( clientVersionParts[i] ) < parseInt( minVersionParts[i] ) ) {
2450 - return false;
2451 - }
2452 - }
2453 - // Same version:
2454 - return true;
2455 - };
2456 -
2457 - /**
2458 - * Utility jQuery bindings Setup after jQuery is available ).
2459 - */
2460 - mw.dojQueryBindings = function() {
2461 - mw.log( 'mw.dojQueryBindings' );
2462 - ( function( $ ) {
2463 -
2464 - /**
2465 - * Runs all the triggers on all the named bindings of an object with
2466 - * a single callback
2467 - *
2468 - * NOTE THIS REQUIRES JQUERY 1.4.2 and above
2469 - *
2470 - * Normal jQuery tirgger calls will run the callback directly
2471 - * multiple times for every binded function.
2472 - *
2473 - * With triggerQueueCallback() callback is not called until all the
2474 - * binded events have been run.
2475 - *
2476 - * @param {string}
2477 - * triggerName Name of trigger to be run
2478 - * @param {object=}
2479 - * arguments Optional arguments object to be passed to
2480 - * the callback
2481 - * @param {function}
2482 - * callback Function called once all triggers have been
2483 - * run
2484 - *
2485 - */
2486 - $.fn.triggerQueueCallback = function( triggerName, triggerParam, callback ){
2487 - var targetObject = this;
2488 - // Support optional triggerParam data
2489 - if( !callback && typeof triggerParam == 'function' ){
2490 - callback = triggerParam;
2491 - triggerParam = null;
2492 - }
2493 - // Support namespaced event segmentation ( jQuery
2494 - var triggerBaseName = triggerName.split(".")[0];
2495 - var triggerNamespace = triggerName.split(".")[1];
2496 - // Get the callback set
2497 - var callbackSet = [];
2498 - if( ! triggerNamespace ){
2499 - callbackSet = $j( targetObject ).data( 'events' )[ triggerBaseName ];
2500 - } else{
2501 - $j.each( $j( targetObject ).data( 'events' )[ triggerBaseName ], function( inx, bindObject ){
2502 - if( bindObject.namespace == triggerNamespace ){
2503 - callbackSet.push( bindObject );
2504 - }
2505 - });
2506 - }
2507 -
2508 - if( !callbackSet || callbackSet.length === 0 ){
2509 - mw.log( '"mwEmbed::jQuery.triggerQueueCallback: No events run the callback directly: ' + triggerName );
2510 - // No events run the callback directly
2511 - callback();
2512 - return ;
2513 - }
2514 -
2515 - // Set the callbackCount
2516 - var callbackCount = ( callbackSet.length )? callbackSet.length : 1;
2517 - // mw.log("mwEmbed::jQuery.triggerQueueCallback: " + triggerName
2518 - // + ' number of queued functions:' + callbackCount );
2519 - var callInx = 0;
2520 - var doCallbackCheck = function() {
2521 - // mw.log( 'callback for: ' + mw.getCallStack()[0] +
2522 - // callInx);
2523 - callInx++;
2524 - if( callInx == callbackCount ){
2525 - callback();
2526 - }
2527 - };
2528 - if( triggerParam ){
2529 - $( this ).trigger( triggerName, [ triggerParam, doCallbackCheck ]);
2530 - } else {
2531 - $( this ).trigger( triggerName, [ doCallbackCheck ] );
2532 - }
2533 - };
2534 -
2535 - /**
2536 - * Set a given selector html to the loading spinner:
2537 - */
2538 - $.fn.loadingSpinner = function( ) {
2539 - if ( this ) {
2540 - $( this ).html(
2541 - $( '<div />' )
2542 - .addClass( "loadingSpinner" )
2543 - );
2544 - }
2545 - return this;
2546 - };
2547 -
2548 - /**
2549 - * Add an absolute overlay spinner useful for cases where the
2550 - * element does not display child elements, ( images, video )
2551 - */
2552 - $.fn.getAbsoluteOverlaySpinner = function(){
2553 - var pos = $j( this ).offset();
2554 - var posLeft = ( $j( this ).width() ) ?
2555 - parseInt( pos.left + ( .5 * $j( this ).width() ) -16 ) :
2556 - pos.left + 30;
2557 -
2558 - var posTop = ( $j( this ).height() ) ?
2559 - parseInt( pos.top + ( .5 * $j( this ).height() ) -16 ) :
2560 - pos.top + 30;
2561 -
2562 - var $spinner = $j('<div />')
2563 - .loadingSpinner()
2564 - .css({
2565 - 'width' : 32,
2566 - 'height' : 32,
2567 - 'position': 'absolute',
2568 - 'top' : posTop + 'px',
2569 - 'left' : posLeft + 'px'
2570 - });
2571 - $j('body').append( $spinner );
2572 - return $spinner;
2573 - };
2574 -
2575 - /**
2576 - * dragDrop file loader
2577 - */
2578 - $.fn.dragFileUpload = function ( conf ) {
2579 - if ( this.selector ) {
2580 - var _this = this;
2581 - // load the dragger and "setup"
2582 - mw.load( ['$j.fn.dragDropFile'], function() {
2583 - $j( _this.selector ).dragDropFile();
2584 - } );
2585 - }
2586 - };
2587 -
2588 - /**
2589 - * Shortcut to a themed button Should be depreciated for $.button
2590 - * bellow
2591 - */
2592 - $.btnHtml = function( msg, styleClass, iconId, opt ) {
2593 - if ( !opt )
2594 - opt = { };
2595 - var href = ( opt.href ) ? opt.href : '#';
2596 - var target_attr = ( opt.target ) ? ' target="' + opt.target + '" ' : '';
2597 - var style_attr = ( opt.style ) ? ' style="' + opt.style + '" ' : '';
2598 - return '<a href="' + href + '" ' + target_attr + style_attr +
2599 - ' class="ui-state-default ui-corner-all ui-icon_link ' +
2600 - styleClass + '"><span class="ui-icon ui-icon-' + iconId + '" ></span>' +
2601 - '<span class="btnText">' + msg + '</span></a>';
2602 - };
2603 -
2604 - // Shortcut to jQuery button ( should replace all btnHtml with
2605 - // button )
2606 - var mw_default_button_options = {
2607 - // The class name for the button link
2608 - 'class' : '',
2609 -
2610 - // The style properties for the button link
2611 - 'style' : { },
2612 -
2613 - // The text of the button link
2614 - 'text' : '',
2615 -
2616 - // The icon id that precedes the button link:
2617 - 'icon' : 'carat-1-n'
2618 - };
2619 -
2620 - $.button = function( options ) {
2621 - var options = $j.extend( {}, mw_default_button_options, options);
2622 -
2623 - // Button:
2624 - var $button = $j('<a />')
2625 - .attr('href', '#')
2626 - .addClass( 'ui-state-default ui-corner-all ui-icon_link' );
2627 - // Add css if set:
2628 - if( options.css ) {
2629 - $button.css( options.css );
2630 - }
2631 -
2632 - if( options['class'] ) {
2633 - $button.addClass( options['class'] );
2634 - }
2635 -
2636 - // return the button:
2637 - $button.append(
2638 - $j('<span />').addClass( 'ui-icon ui-icon-' + options.icon ),
2639 - $j('<span />').addClass( 'btnText' )
2640 - )
2641 - .buttonHover(); // add buttonHover binding;
2642 -
2643 - if( options.text ){
2644 - $button.find('.btnText').text( options.text );
2645 - } else {
2646 - $button.css('padding', '1em');
2647 - }
2648 - return $button;
2649 - };
2650 -
2651 - // Shortcut to bind hover state
2652 - $.fn.buttonHover = function() {
2653 - $j( this ).hover(
2654 - function() {
2655 - $j( this ).addClass( 'ui-state-hover' );
2656 - },
2657 - function() {
2658 - $j( this ).removeClass( 'ui-state-hover' );
2659 - }
2660 - );
2661 - return this;
2662 - };
2663 -
2664 - /**
2665 - * Resize a dialog to fit the window
2666 - *
2667 - * @param {Object}
2668 - * options horizontal and vertical space ( default 50 )
2669 - */
2670 - $.fn.dialogFitWindow = function( options ) {
2671 - var opt_default = { 'hspace':50, 'vspace':50 };
2672 - if ( !options )
2673 - var options = { };
2674 - options = $j.extend( opt_default, options );
2675 - $j( this.selector ).dialog( 'option', 'width', $j( window ).width() - options.hspace );
2676 - $j( this.selector ).dialog( 'option', 'height', $j( window ).height() - options.vspace );
2677 - $j( this.selector ).dialog( 'option', 'position', 'center' );
2678 - // update the child position: (some of this should be pushed
2679 - // up-stream via dialog config options
2680 - $j( this.selector + '~ .ui-dialog-buttonpane' ).css( {
2681 - 'position':'absolute',
2682 - 'left':'0px',
2683 - 'right':'0px',
2684 - 'bottom':'0px'
2685 - } );
2686 - };
2687 -
2688 - } )( jQuery );
2689 - };
2690 -
2691 -} )( window.mw );
2692 -
2693 -
2694 -/**
2695 - * Set DOM-ready call We copy jQuery( document ).ready here since sometimes
2696 - * mwEmbed.js is included without jQuery and we need our own "ready" system so
2697 - * that mwEmbed interfaces can support async built out and the include of
2698 - * jQuery.
2699 - */
2700 -// Check if already ready:
2701 -if ( document.readyState === "complete" ) {
2702 - mw.domReady();
2703 -}
2704 -
2705 -// Cleanup functions for the document ready method
2706 -if ( document.addEventListener ) {
2707 - DOMContentLoaded = function() {
2708 - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
2709 - mw.domReady();
2710 - };
2711 -
2712 -} else if ( document.attachEvent ) {
2713 - DOMContentLoaded = function() {
2714 - // Make sure body exists, at least, in case IE gets a little overzealous
2715 - // (ticket #5443).
2716 - if ( document.readyState === "complete" ) {
2717 - document.detachEvent( "onreadystatechange", DOMContentLoaded );
2718 - mw.domReady();
2719 - }
2720 - };
2721 -}
2722 -// Mozilla, Opera and webkit nightlies currently support this event
2723 -if ( document.addEventListener ) {
2724 - // Use the handy event callback
2725 - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
2726 -
2727 - // A fallback to window.onload, that will always work
2728 - window.addEventListener( "load", mw.domReady, false );
2729 -
2730 -// If IE event model is used
2731 -} else if ( document.attachEvent ) {
2732 - // ensure firing before onload,
2733 - // maybe late but safe also for iframes
2734 - document.attachEvent("onreadystatechange", DOMContentLoaded);
2735 -
2736 - // A fallback to window.onload, that will always work
2737 - window.attachEvent( "onload", mw.domReady );
2738 -
2739 - // If IE and not a frame
2740 - // continually check to see if the document is ready
2741 - var toplevel = false;
2742 -
2743 - try {
2744 - toplevel = window.frameElement == null;
2745 - } catch(e) {}
2746 -
2747 - if ( document.documentElement.doScroll && toplevel ) {
2748 - doScrollCheck();
2749 - }
2750 -}
2751 -// The DOM ready check for Internet Explorer
2752 -function doScrollCheck() {
2753 - try {
2754 - // If IE is used, use the trick by Diego Perini
2755 - // http://javascript.nwbox.com/IEContentLoaded/
2756 - document.documentElement.doScroll("left");
2757 - } catch( error ) {
2758 - setTimeout( doScrollCheck, 1 );
2759 - return;
2760 - }
2761 - mw.domReady();
2762 -}
2763 -
2764 -// If using the resource loader and jQuery has not been set give a warning to
2765 -// the user:
2766 -// (this is needed because packaged loader.js files could refrence jQuery )
2767 -if( mw.getResourceLoaderPath() && !window.jQuery ) {
2768 - mw.log( 'Error: jQuery is required for mwEmbed, please update your resource loader request' );
2769 -}
2770 -
2771 -if( mw.isStaticPackge() && !window.jQuery ){
2772 - alert( 'Error: jQuery is required for mwEmbed ');
2773 -}
2774 -
2775 -/**
2776 - * Hack to keep jQuery in $ when its already there, but also use noConflict to
2777 - * get $j = jQuery
2778 - *
2779 - * This way sites that use $ for jQuery continue to work after including mwEmbed
2780 - * javascript.
2781 - *
2782 - * Also if jQuery is included prior to mwEmbed we ensure $j is set
2783 - */
2784 -
2785 -if( window.jQuery ){
2786 - if( ! mw.versionIsAtLeast( '1.4.2', jQuery.fn.jquery ) ){
2787 - if( window.console && window.console.log ) {
2788 - console.log( 'Error mwEmbed requires jQuery 1.4 or above' );
2789 - }
2790 - }
2791 - var dollarFlag = false;
2792 - if( $ && $.fn && $.fn.jquery ) {
2793 - // NOTE we could check the version of
2794 - // jQuery and do a removal call if too old
2795 - dollarFlag = true;
2796 - }
2797 - window[ '$j' ] = jQuery.noConflict();
2798 - if( dollarFlag ) {
2799 - window[ '$' ] = jQuery.noConflict();
2800 - }
2801 -}
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/load.php
@@ -26,7 +26,7 @@
2727 *
2828 */
2929
30 -require ( dirname( __FILE__ ) . '/includes/MwEmbedWebStart.php' );
 30+require ( dirname( __FILE__ ) . '/includes/MwEmbedWebStartSetup.php' );
3131
3232 // Respond to resource loading request
3333 $resourceLoader = new MwEmbedResourceLoader();
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedWebStart.php
@@ -1,79 +0,0 @@
2 -<?php
3 -/**
4 - * This does the initial setup for a web request.
5 - * It does some security checks, and loads the
6 - * configuration
7 - *
8 - * @file
9 - */
10 -
11 -# Protect against register_globals
12 -# This must be done before any globals are set by the code
13 -if ( ini_get( 'register_globals' ) ) {
14 - if ( isset( $_REQUEST['GLOBALS'] ) ) {
15 - die( '<a href="http://www.hardened-php.net/globals-problem">$GLOBALS overwrite vulnerability</a>');
16 - }
17 - $verboten = array(
18 - 'GLOBALS',
19 - '_SERVER',
20 - 'HTTP_SERVER_VARS',
21 - '_GET',
22 - 'HTTP_GET_VARS',
23 - '_POST',
24 - 'HTTP_POST_VARS',
25 - '_COOKIE',
26 - 'HTTP_COOKIE_VARS',
27 - '_FILES',
28 - 'HTTP_POST_FILES',
29 - '_ENV',
30 - 'HTTP_ENV_VARS',
31 - '_REQUEST',
32 - '_SESSION',
33 - 'HTTP_SESSION_VARS'
34 - );
35 - foreach ( $_REQUEST as $name => $value ) {
36 - if( in_array( $name, $verboten ) ) {
37 - header( "HTTP/1.x 500 Internal Server Error" );
38 - echo "register_globals security paranoia: trying to overwrite superglobals, aborting.";
39 - die( -1 );
40 - }
41 - unset( $GLOBALS[$name] );
42 - }
43 -}
44 -
45 -# Valid web server entry point, enable includes.
46 -# Please don't move this line to includes/Defines.php. This line essentially
47 -# defines a valid entry point. If you put it in includes/Defines.php, then
48 -# any script that includes it becomes an entry point, thereby defeating
49 -# its purpose.
50 -define( 'MEDIAWIKI', true );
51 -
52 -# Full path to working directory.
53 -# Makes it possible to for example to have effective exclude path in apc.
54 -# Also doesn't break installations using symlinked includes, like
55 -# dirname( __FILE__ ) would do.
56 -$IP = getenv( 'MW_INSTALL_PATH' );
57 -if ( $IP === false ) {
58 - $IP = realpath( '.' );
59 -}
60 -
61 -
62 -# Start the autoloader, so that extensions can derive classes from core files
63 -require_once( "$IP/includes/mwEmbedAutoLoader.php" );
64 -
65 -# Load default settings
66 -require_once( "$IP/includes/DefaultSettings.php" );
67 -
68 -
69 -if ( !defined('MW_CONFIG_FILE') )
70 - define('MW_CONFIG_FILE', "$IP/LocalSettings.php");
71 -
72 -# LocalSettings.php is the per site customization file. If it does not exist
73 -# error out
74 -if( !file_exists( MW_CONFIG_FILE ) ) {
75 - print "alert('your mwEmbed install is missing a localSettings.php');";
76 - die();
77 -}
78 -
79 -# Load local settings
80 -require_once( "$IP/LocalSettings.php" );
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/WebRequest.php
@@ -1,1016 +0,0 @@
2 -<?php
3 -/**
4 - * Deal with importing all those nasssty globals and things
5 - *
6 - * Copyright © 2003 Brion Vibber <brion@pobox.com>
7 - * http://www.mediawiki.org/
8 - *
9 - * This program is free software; you can redistribute it and/or modify
10 - * it under the terms of the GNU General Public License as published by
11 - * the Free Software Foundation; either version 2 of the License, or
12 - * (at your option) any later version.
13 - *
14 - * This program is distributed in the hope that it will be useful,
15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 - * GNU General Public License for more details.
18 - *
19 - * You should have received a copy of the GNU General Public License along
20 - * with this program; if not, write to the Free Software Foundation, Inc.,
21 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 - * http://www.gnu.org/copyleft/gpl.html
23 - *
24 - * @file
25 - */
26 -
27 -/**
28 - * The WebRequest class encapsulates getting at data passed in the
29 - * URL or via a POSTed form, handling remove of "magic quotes" slashes,
30 - * stripping illegal input characters and normalizing Unicode sequences.
31 - *
32 - * Usually this is used via a global singleton, $wgRequest. You should
33 - * not create a second WebRequest object; make a FauxRequest object if
34 - * you want to pass arbitrary data to some function in place of the web
35 - * input.
36 - *
37 - * @ingroup HTTP
38 - */
39 -class WebRequest {
40 - protected $data, $headers = array();
41 -
42 - /**
43 - * Lazy-init response object
44 - * @var WebResponse
45 - */
46 - private $response;
47 -
48 - public function __construct() {
49 - /// @todo Fixme: this preemptive de-quoting can interfere with other web libraries
50 - /// and increases our memory footprint. It would be cleaner to do on
51 - /// demand; but currently we have no wrapper for $_SERVER etc.
52 - $this->checkMagicQuotes();
53 -
54 - // POST overrides GET data
55 - // We don't use $_REQUEST here to avoid interference from cookies...
56 - $this->data = $_POST + $_GET;
57 - }
58 -
59 - /**
60 - * Check for title, action, and/or variant data in the URL
61 - * and interpolate it into the GET variables.
62 - * This should only be run after $wgContLang is available,
63 - * as we may need the list of language variants to determine
64 - * available variant URLs.
65 - */
66 - public function interpolateTitle() {
67 - global $wgUsePathInfo;
68 -
69 - // bug 16019: title interpolation on API queries is useless and sometimes harmful
70 - if ( defined( 'MW_API' ) ) {
71 - return;
72 - }
73 -
74 - if ( $wgUsePathInfo ) {
75 - // PATH_INFO is mangled due to http://bugs.php.net/bug.php?id=31892
76 - // And also by Apache 2.x, double slashes are converted to single slashes.
77 - // So we will use REQUEST_URI if possible.
78 - $matches = array();
79 -
80 - if ( !empty( $_SERVER['REQUEST_URI'] ) ) {
81 - // Slurp out the path portion to examine...
82 - $url = $_SERVER['REQUEST_URI'];
83 - if ( !preg_match( '!^https?://!', $url ) ) {
84 - $url = 'http://unused' . $url;
85 - }
86 - $a = parse_url( $url );
87 - if( $a ) {
88 - $path = isset( $a['path'] ) ? $a['path'] : '';
89 -
90 - global $wgScript;
91 - if( $path == $wgScript ) {
92 - // Script inside a rewrite path?
93 - // Abort to keep from breaking...
94 - return;
95 - }
96 - // Raw PATH_INFO style
97 - $matches = $this->extractTitle( $path, "$wgScript/$1" );
98 -
99 - global $wgArticlePath;
100 - if( !$matches && $wgArticlePath ) {
101 - $matches = $this->extractTitle( $path, $wgArticlePath );
102 - }
103 -
104 - global $wgActionPaths;
105 - if( !$matches && $wgActionPaths ) {
106 - $matches = $this->extractTitle( $path, $wgActionPaths, 'action' );
107 - }
108 -
109 - global $wgVariantArticlePath, $wgContLang;
110 - if( !$matches && $wgVariantArticlePath ) {
111 - $variantPaths = array();
112 - foreach( $wgContLang->getVariants() as $variant ) {
113 - $variantPaths[$variant] =
114 - str_replace( '$2', $variant, $wgVariantArticlePath );
115 - }
116 - $matches = $this->extractTitle( $path, $variantPaths, 'variant' );
117 - }
118 - }
119 - } elseif ( isset( $_SERVER['ORIG_PATH_INFO'] ) && $_SERVER['ORIG_PATH_INFO'] != '' ) {
120 - // Mangled PATH_INFO
121 - // http://bugs.php.net/bug.php?id=31892
122 - // Also reported when ini_get('cgi.fix_pathinfo')==false
123 - $matches['title'] = substr( $_SERVER['ORIG_PATH_INFO'], 1 );
124 -
125 - } elseif ( isset( $_SERVER['PATH_INFO'] ) && ($_SERVER['PATH_INFO'] != '') ) {
126 - // Regular old PATH_INFO yay
127 - $matches['title'] = substr( $_SERVER['PATH_INFO'], 1 );
128 - }
129 - foreach( $matches as $key => $val) {
130 - $this->data[$key] = $_GET[$key] = $_REQUEST[$key] = $val;
131 - }
132 - }
133 - }
134 -
135 - /**
136 - * Internal URL rewriting function; tries to extract page title and,
137 - * optionally, one other fixed parameter value from a URL path.
138 - *
139 - * @param $path string: the URL path given from the client
140 - * @param $bases array: one or more URLs, optionally with $1 at the end
141 - * @param $key string: if provided, the matching key in $bases will be
142 - * passed on as the value of this URL parameter
143 - * @return array of URL variables to interpolate; empty if no match
144 - */
145 - private function extractTitle( $path, $bases, $key=false ) {
146 - foreach( (array)$bases as $keyValue => $base ) {
147 - // Find the part after $wgArticlePath
148 - $base = str_replace( '$1', '', $base );
149 - $baseLen = strlen( $base );
150 - if( substr( $path, 0, $baseLen ) == $base ) {
151 - $raw = substr( $path, $baseLen );
152 - if( $raw !== '' ) {
153 - $matches = array( 'title' => rawurldecode( $raw ) );
154 - if( $key ) {
155 - $matches[$key] = $keyValue;
156 - }
157 - return $matches;
158 - }
159 - }
160 - }
161 - return array();
162 - }
163 -
164 - /**
165 - * Recursively strips slashes from the given array;
166 - * used for undoing the evil that is magic_quotes_gpc.
167 - *
168 - * @param $arr array: will be modified
169 - * @return array the original array
170 - */
171 - private function &fix_magic_quotes( &$arr ) {
172 - foreach( $arr as $key => $val ) {
173 - if( is_array( $val ) ) {
174 - $this->fix_magic_quotes( $arr[$key] );
175 - } else {
176 - $arr[$key] = stripslashes( $val );
177 - }
178 - }
179 - return $arr;
180 - }
181 -
182 - /**
183 - * If magic_quotes_gpc option is on, run the global arrays
184 - * through fix_magic_quotes to strip out the stupid slashes.
185 - * WARNING: This should only be done once! Running a second
186 - * time could damage the values.
187 - */
188 - private function checkMagicQuotes() {
189 - $mustFixQuotes = function_exists( 'get_magic_quotes_gpc' )
190 - && get_magic_quotes_gpc();
191 - if( $mustFixQuotes ) {
192 - $this->fix_magic_quotes( $_COOKIE );
193 - $this->fix_magic_quotes( $_ENV );
194 - $this->fix_magic_quotes( $_GET );
195 - $this->fix_magic_quotes( $_POST );
196 - $this->fix_magic_quotes( $_REQUEST );
197 - $this->fix_magic_quotes( $_SERVER );
198 - }
199 - }
200 -
201 - /**
202 - * Recursively normalizes UTF-8 strings in the given array.
203 - *
204 - * @param $data string or array
205 - * @return cleaned-up version of the given
206 - * @private
207 - */
208 - function normalizeUnicode( $data ) {
209 - if( is_array( $data ) ) {
210 - foreach( $data as $key => $val ) {
211 - $data[$key] = $this->normalizeUnicode( $val );
212 - }
213 - } else {
214 - global $wgContLang;
215 - $data = $wgContLang->normalize( $data );
216 - }
217 - return $data;
218 - }
219 -
220 - /**
221 - * Fetch a value from the given array or return $default if it's not set.
222 - *
223 - * @param $arr Array
224 - * @param $name String
225 - * @param $default Mixed
226 - * @return mixed
227 - */
228 - private function getGPCVal( $arr, $name, $default ) {
229 - # PHP is so nice to not touch input data, except sometimes:
230 - # http://us2.php.net/variables.external#language.variables.external.dot-in-names
231 - # Work around PHP *feature* to avoid *bugs* elsewhere.
232 - $name = strtr( $name, '.', '_' );
233 - if( isset( $arr[$name] ) ) {
234 - global $wgContLang;
235 - $data = $arr[$name];
236 - if( isset( $_GET[$name] ) && !is_array( $data ) ) {
237 - # Check for alternate/legacy character encoding.
238 - if( isset( $wgContLang ) ) {
239 - $data = $wgContLang->checkTitleEncoding( $data );
240 - }
241 - }
242 - $data = $this->normalizeUnicode( $data );
243 - return $data;
244 - } else {
245 - taint( $default );
246 - return $default;
247 - }
248 - }
249 -
250 - /**
251 - * Fetch a scalar from the input or return $default if it's not set.
252 - * Returns a string. Arrays are discarded. Useful for
253 - * non-freeform text inputs (e.g. predefined internal text keys
254 - * selected by a drop-down menu). For freeform input, see getText().
255 - *
256 - * @param $name String
257 - * @param $default String: optional default (or NULL)
258 - * @return String
259 - */
260 - public function getVal( $name, $default = null ) {
261 - $val = $this->getGPCVal( $this->data, $name, $default );
262 - if( is_array( $val ) ) {
263 - $val = $default;
264 - }
265 - if( is_null( $val ) ) {
266 - return $val;
267 - } else {
268 - return (string)$val;
269 - }
270 - }
271 -
272 - /**
273 - * Set an aribtrary value into our get/post data.
274 - *
275 - * @param $key String: key name to use
276 - * @param $value Mixed: value to set
277 - * @return Mixed: old value if one was present, null otherwise
278 - */
279 - public function setVal( $key, $value ) {
280 - $ret = isset( $this->data[$key] ) ? $this->data[$key] : null;
281 - $this->data[$key] = $value;
282 - return $ret;
283 - }
284 -
285 - /**
286 - * Fetch an array from the input or return $default if it's not set.
287 - * If source was scalar, will return an array with a single element.
288 - * If no source and no default, returns NULL.
289 - *
290 - * @param $name String
291 - * @param $default Array: optional default (or NULL)
292 - * @return Array
293 - */
294 - public function getArray( $name, $default = null ) {
295 - $val = $this->getGPCVal( $this->data, $name, $default );
296 - if( is_null( $val ) ) {
297 - return null;
298 - } else {
299 - return (array)$val;
300 - }
301 - }
302 -
303 - /**
304 - * Fetch an array of integers, or return $default if it's not set.
305 - * If source was scalar, will return an array with a single element.
306 - * If no source and no default, returns NULL.
307 - * If an array is returned, contents are guaranteed to be integers.
308 - *
309 - * @param $name String
310 - * @param $default Array: option default (or NULL)
311 - * @return Array of ints
312 - */
313 - public function getIntArray( $name, $default = null ) {
314 - $val = $this->getArray( $name, $default );
315 - if( is_array( $val ) ) {
316 - $val = array_map( 'intval', $val );
317 - }
318 - return $val;
319 - }
320 -
321 - /**
322 - * Fetch an integer value from the input or return $default if not set.
323 - * Guaranteed to return an integer; non-numeric input will typically
324 - * return 0.
325 - *
326 - * @param $name String
327 - * @param $default Integer
328 - * @return Integer
329 - */
330 - public function getInt( $name, $default = 0 ) {
331 - return intval( $this->getVal( $name, $default ) );
332 - }
333 -
334 - /**
335 - * Fetch an integer value from the input or return null if empty.
336 - * Guaranteed to return an integer or null; non-numeric input will
337 - * typically return null.
338 - *
339 - * @param $name String
340 - * @return Integer
341 - */
342 - public function getIntOrNull( $name ) {
343 - $val = $this->getVal( $name );
344 - return is_numeric( $val )
345 - ? intval( $val )
346 - : null;
347 - }
348 -
349 - /**
350 - * Fetch a boolean value from the input or return $default if not set.
351 - * Guaranteed to return true or false, with normal PHP semantics for
352 - * boolean interpretation of strings.
353 - *
354 - * @param $name String
355 - * @param $default Boolean
356 - * @return Boolean
357 - */
358 - public function getBool( $name, $default = false ) {
359 - return (bool)$this->getVal( $name, $default );
360 - }
361 -
362 - /**
363 - * Fetch a boolean value from the input or return $default if not set.
364 - * Unlike getBool, the string "false" will result in boolean false, which is
365 - * useful when interpreting information sent from JavaScript.
366 - *
367 - * @param $name String
368 - * @param $default Boolean
369 - * @return Boolean
370 - */
371 - public function getFuzzyBool( $name, $default = false ) {
372 - return $this->getBool( $name, $default ) && strcasecmp( $this->getVal( $name ), 'false' ) !== 0;
373 - }
374 -
375 - /**
376 - * Return true if the named value is set in the input, whatever that
377 - * value is (even "0"). Return false if the named value is not set.
378 - * Example use is checking for the presence of check boxes in forms.
379 - *
380 - * @param $name String
381 - * @return Boolean
382 - */
383 - public function getCheck( $name ) {
384 - # Checkboxes and buttons are only present when clicked
385 - # Presence connotes truth, abscense false
386 - $val = $this->getVal( $name, null );
387 - return isset( $val );
388 - }
389 -
390 - /**
391 - * Fetch a text string from the given array or return $default if it's not
392 - * set. Carriage returns are stripped from the text, and with some language
393 - * modules there is an input transliteration applied. This should generally
394 - * be used for form <textarea> and <input> fields. Used for user-supplied
395 - * freeform text input (for which input transformations may be required - e.g.
396 - * Esperanto x-coding).
397 - *
398 - * @param $name String
399 - * @param $default String: optional
400 - * @return String
401 - */
402 - public function getText( $name, $default = '' ) {
403 - global $wgContLang;
404 - $val = $this->getVal( $name, $default );
405 - return str_replace( "\r\n", "\n",
406 - $wgContLang->recodeInput( $val ) );
407 - }
408 -
409 - /**
410 - * Extracts the given named values into an array.
411 - * If no arguments are given, returns all input values.
412 - * No transformation is performed on the values.
413 - */
414 - public function getValues() {
415 - $names = func_get_args();
416 - if ( count( $names ) == 0 ) {
417 - $names = array_keys( $this->data );
418 - }
419 -
420 - $retVal = array();
421 - foreach ( $names as $name ) {
422 - $value = $this->getVal( $name );
423 - if ( !is_null( $value ) ) {
424 - $retVal[$name] = $value;
425 - }
426 - }
427 - return $retVal;
428 - }
429 -
430 - /**
431 - * Returns true if the present request was reached by a POST operation,
432 - * false otherwise (GET, HEAD, or command-line).
433 - *
434 - * Note that values retrieved by the object may come from the
435 - * GET URL etc even on a POST request.
436 - *
437 - * @return Boolean
438 - */
439 - public function wasPosted() {
440 - return $_SERVER['REQUEST_METHOD'] == 'POST';
441 - }
442 -
443 - /**
444 - * Returns true if there is a session cookie set.
445 - * This does not necessarily mean that the user is logged in!
446 - *
447 - * If you want to check for an open session, use session_id()
448 - * instead; that will also tell you if the session was opened
449 - * during the current request (in which case the cookie will
450 - * be sent back to the client at the end of the script run).
451 - *
452 - * @return Boolean
453 - */
454 - public function checkSessionCookie() {
455 - return isset( $_COOKIE[ session_name() ] );
456 - }
457 -
458 - /**
459 - * Get a cookie from the $_COOKIE jar
460 - *
461 - * @param $key String: the name of the cookie
462 - * @param $prefix String: a prefix to use for the cookie name, if not $wgCookiePrefix
463 - * @param $default Mixed: what to return if the value isn't found
464 - * @return Mixed: cookie value or $default if the cookie not set
465 - */
466 - public function getCookie( $key, $prefix = null, $default = null ) {
467 - if( $prefix === null ) {
468 - global $wgCookiePrefix;
469 - $prefix = $wgCookiePrefix;
470 - }
471 - return $this->getGPCVal( $_COOKIE, $prefix . $key , $default );
472 - }
473 -
474 - /**
475 - * Return the path portion of the request URI.
476 - *
477 - * @return String
478 - */
479 - public function getRequestURL() {
480 - if( isset( $_SERVER['REQUEST_URI']) && strlen($_SERVER['REQUEST_URI']) ) {
481 - $base = $_SERVER['REQUEST_URI'];
482 - } elseif( isset( $_SERVER['SCRIPT_NAME'] ) ) {
483 - // Probably IIS; doesn't set REQUEST_URI
484 - $base = $_SERVER['SCRIPT_NAME'];
485 - if( isset( $_SERVER['QUERY_STRING'] ) && $_SERVER['QUERY_STRING'] != '' ) {
486 - $base .= '?' . $_SERVER['QUERY_STRING'];
487 - }
488 - } else {
489 - // This shouldn't happen!
490 - throw new MWException( "Web server doesn't provide either " .
491 - "REQUEST_URI or SCRIPT_NAME. Report details of your " .
492 - "web server configuration to http://bugzilla.wikimedia.org/" );
493 - }
494 - // User-agents should not send a fragment with the URI, but
495 - // if they do, and the web server passes it on to us, we
496 - // need to strip it or we get false-positive redirect loops
497 - // or weird output URLs
498 - $hash = strpos( $base, '#' );
499 - if( $hash !== false ) {
500 - $base = substr( $base, 0, $hash );
501 - }
502 - if( $base{0} == '/' ) {
503 - return $base;
504 - } else {
505 - // We may get paths with a host prepended; strip it.
506 - return preg_replace( '!^[^:]+://[^/]+/!', '/', $base );
507 - }
508 - }
509 -
510 - /**
511 - * Return the request URI with the canonical service and hostname.
512 - *
513 - * @return String
514 - */
515 - public function getFullRequestURL() {
516 - global $wgServer;
517 - return $wgServer . $this->getRequestURL();
518 - }
519 -
520 - /**
521 - * Take an arbitrary query and rewrite the present URL to include it
522 - * @param $query String: query string fragment; do not include initial '?'
523 - *
524 - * @return String
525 - */
526 - public function appendQuery( $query ) {
527 - global $wgTitle;
528 - $basequery = '';
529 - foreach( $_GET as $var => $val ) {
530 - if ( $var == 'title' ) {
531 - continue;
532 - }
533 - if ( is_array( $val ) ) {
534 - /* This will happen given a request like
535 - * http://en.wikipedia.org/w/index.php?title[]=Special:Userlogin&returnto[]=Main_Page
536 - */
537 - continue;
538 - }
539 - $basequery .= '&' . urlencode( $var ) . '=' . urlencode( $val );
540 - }
541 - $basequery .= '&' . $query;
542 -
543 - # Trim the extra &
544 - $basequery = substr( $basequery, 1 );
545 - return $wgTitle->getLocalURL( $basequery );
546 - }
547 -
548 - /**
549 - * HTML-safe version of appendQuery().
550 - *
551 - * @param $query String: query string fragment; do not include initial '?'
552 - * @return String
553 - */
554 - public function escapeAppendQuery( $query ) {
555 - return htmlspecialchars( $this->appendQuery( $query ) );
556 - }
557 -
558 - public function appendQueryValue( $key, $value, $onlyquery = false ) {
559 - return $this->appendQueryArray( array( $key => $value ), $onlyquery );
560 - }
561 -
562 - /**
563 - * Appends or replaces value of query variables.
564 - *
565 - * @param $array Array of values to replace/add to query
566 - * @param $onlyquery Bool: whether to only return the query string and not
567 - * the complete URL
568 - * @return String
569 - */
570 - public function appendQueryArray( $array, $onlyquery = false ) {
571 - global $wgTitle;
572 - $newquery = $_GET;
573 - unset( $newquery['title'] );
574 - $newquery = array_merge( $newquery, $array );
575 - $query = wfArrayToCGI( $newquery );
576 - return $onlyquery ? $query : $wgTitle->getLocalURL( $query );
577 - }
578 -
579 - /**
580 - * Check for limit and offset parameters on the input, and return sensible
581 - * defaults if not given. The limit must be positive and is capped at 5000.
582 - * Offset must be positive but is not capped.
583 - *
584 - * @param $deflimit Integer: limit to use if no input and the user hasn't set the option.
585 - * @param $optionname String: to specify an option other than rclimit to pull from.
586 - * @return array first element is limit, second is offset
587 - */
588 - public function getLimitOffset( $deflimit = 50, $optionname = 'rclimit' ) {
589 - global $wgUser;
590 -
591 - $limit = $this->getInt( 'limit', 0 );
592 - if( $limit < 0 ) {
593 - $limit = 0;
594 - }
595 - if( ( $limit == 0 ) && ( $optionname != '' ) ) {
596 - $limit = (int)$wgUser->getOption( $optionname );
597 - }
598 - if( $limit <= 0 ) {
599 - $limit = $deflimit;
600 - }
601 - if( $limit > 5000 ) {
602 - $limit = 5000; # We have *some* limits...
603 - }
604 -
605 - $offset = $this->getInt( 'offset', 0 );
606 - if( $offset < 0 ) {
607 - $offset = 0;
608 - }
609 -
610 - return array( $limit, $offset );
611 - }
612 -
613 - /**
614 - * Return the path to the temporary file where PHP has stored the upload.
615 - *
616 - * @param $key String:
617 - * @return string or NULL if no such file.
618 - */
619 - public function getFileTempname( $key ) {
620 - $file = new WebRequestUpload( $this, $key );
621 - return $file->getTempName();
622 - }
623 -
624 - /**
625 - * Return the size of the upload, or 0.
626 - *
627 - * @deprecated
628 - * @param $key String:
629 - * @return integer
630 - */
631 - public function getFileSize( $key ) {
632 - $file = new WebRequestUpload( $this, $key );
633 - return $file->getSize();
634 - }
635 -
636 - /**
637 - * Return the upload error or 0
638 - *
639 - * @param $key String:
640 - * @return integer
641 - */
642 - public function getUploadError( $key ) {
643 - $file = new WebRequestUpload( $this, $key );
644 - return $file->getError();
645 - }
646 -
647 - /**
648 - * Return the original filename of the uploaded file, as reported by
649 - * the submitting user agent. HTML-style character entities are
650 - * interpreted and normalized to Unicode normalization form C, in part
651 - * to deal with weird input from Safari with non-ASCII filenames.
652 - *
653 - * Other than this the name is not verified for being a safe filename.
654 - *
655 - * @param $key String:
656 - * @return string or NULL if no such file.
657 - */
658 - public function getFileName( $key ) {
659 - $file = new WebRequestUpload( $this, $key );
660 - return $file->getName();
661 - }
662 -
663 - /**
664 - * Return a WebRequestUpload object corresponding to the key
665 - *
666 - * @param @key string
667 - * @return WebRequestUpload
668 - */
669 - public function getUpload( $key ) {
670 - return new WebRequestUpload( $this, $key );
671 - }
672 -
673 - /**
674 - * Return a handle to WebResponse style object, for setting cookies,
675 - * headers and other stuff, for Request being worked on.
676 - *
677 - * @return WebResponse
678 - */
679 - public function response() {
680 - /* Lazy initialization of response object for this request */
681 - if ( !is_object( $this->response ) ) {
682 - $class = ( $this instanceof FauxRequest ) ? 'FauxResponse' : 'WebResponse';
683 - $this->response = new $class();
684 - }
685 - return $this->response;
686 - }
687 -
688 - /**
689 - * Get a request header, or false if it isn't set
690 - * @param $name String: case-insensitive header name
691 - */
692 - public function getHeader( $name ) {
693 - $name = strtoupper( $name );
694 - if ( function_exists( 'apache_request_headers' ) ) {
695 - if ( !$this->headers ) {
696 - foreach ( apache_request_headers() as $tempName => $tempValue ) {
697 - $this->headers[ strtoupper( $tempName ) ] = $tempValue;
698 - }
699 - }
700 - if ( isset( $this->headers[$name] ) ) {
701 - return $this->headers[$name];
702 - } else {
703 - return false;
704 - }
705 - } else {
706 - $name = 'HTTP_' . str_replace( '-', '_', $name );
707 - if ( $name === 'HTTP_CONTENT_LENGTH' && !isset( $_SERVER[$name] ) ) {
708 - $name = 'CONTENT_LENGTH';
709 - }
710 - if ( isset( $_SERVER[$name] ) ) {
711 - return $_SERVER[$name];
712 - } else {
713 - return false;
714 - }
715 - }
716 - }
717 -
718 - /**
719 - * Get data from $_SESSION
720 - *
721 - * @param $key String: name of key in $_SESSION
722 - * @return Mixed
723 - */
724 - public function getSessionData( $key ) {
725 - if( !isset( $_SESSION[$key] ) ) {
726 - return null;
727 - }
728 - return $_SESSION[$key];
729 - }
730 -
731 - /**
732 - * Set session data
733 - *
734 - * @param $key String: name of key in $_SESSION
735 - * @param $data Mixed
736 - */
737 - public function setSessionData( $key, $data ) {
738 - $_SESSION[$key] = $data;
739 - }
740 -
741 - /**
742 - * Returns true if the PATH_INFO ends with an extension other than a script
743 - * extension. This could confuse IE for scripts that send arbitrary data which
744 - * is not HTML but may be detected as such.
745 - *
746 - * Various past attempts to use the URL to make this check have generally
747 - * run up against the fact that CGI does not provide a standard method to
748 - * determine the URL. PATH_INFO may be mangled (e.g. if cgi.fix_pathinfo=0),
749 - * but only by prefixing it with the script name and maybe some other stuff,
750 - * the extension is not mangled. So this should be a reasonably portable
751 - * way to perform this security check.
752 - */
753 - public function isPathInfoBad() {
754 - global $wgScriptExtension;
755 -
756 - if ( !isset( $_SERVER['PATH_INFO'] ) ) {
757 - return false;
758 - }
759 - $pi = $_SERVER['PATH_INFO'];
760 - $dotPos = strrpos( $pi, '.' );
761 - if ( $dotPos === false ) {
762 - return false;
763 - }
764 - $ext = substr( $pi, $dotPos );
765 - return !in_array( $ext, array( $wgScriptExtension, '.php', '.php5' ) );
766 - }
767 -
768 - /**
769 - * Parse the Accept-Language header sent by the client into an array
770 - * @return array( languageCode => q-value ) sorted by q-value in descending order
771 - * May contain the "language" '*', which applies to languages other than those explicitly listed.
772 - * This is aligned with rfc2616 section 14.4
773 - */
774 - public function getAcceptLang() {
775 - // Modified version of code found at http://www.thefutureoftheweb.com/blog/use-accept-language-header
776 - $acceptLang = $this->getHeader( 'Accept-Language' );
777 - if ( !$acceptLang ) {
778 - return array();
779 - }
780 -
781 - // Return the language codes in lower case
782 - $acceptLang = strtolower( $acceptLang );
783 -
784 - // Break up string into pieces (languages and q factors)
785 - $lang_parse = null;
786 - preg_match_all( '/([a-z]{1,8}(-[a-z]{1,8})?|\*)\s*(;\s*q\s*=\s*(1|0(\.[0-9]+)?)?)?/',
787 - $acceptLang, $lang_parse );
788 -
789 - if ( !count( $lang_parse[1] ) ) {
790 - return array();
791 - }
792 -
793 - // Create a list like "en" => 0.8
794 - $langs = array_combine( $lang_parse[1], $lang_parse[4] );
795 - // Set default q factor to 1
796 - foreach ( $langs as $lang => $val ) {
797 - if ( $val === '' ) {
798 - $langs[$lang] = 1;
799 - } else if ( $val == 0 ) {
800 - unset($langs[$lang]);
801 - }
802 - }
803 -
804 - // Sort list
805 - arsort( $langs, SORT_NUMERIC );
806 - return $langs;
807 - }
808 -}
809 -
810 -/**
811 - * Object to access the $_FILES array
812 - */
813 -class WebRequestUpload {
814 - protected $request;
815 - protected $doesExist;
816 - protected $fileInfo;
817 -
818 - /**
819 - * Constructor. Should only be called by WebRequest
820 - *
821 - * @param $request WebRequest The associated request
822 - * @param $key string Key in $_FILES array (name of form field)
823 - */
824 - public function __construct( $request, $key ) {
825 - $this->request = $request;
826 - $this->doesExist = isset( $_FILES[$key] );
827 - if ( $this->doesExist ) {
828 - $this->fileInfo = $_FILES[$key];
829 - }
830 - }
831 -
832 - /**
833 - * Return whether a file with this name was uploaded.
834 - *
835 - * @return bool
836 - */
837 - public function exists() {
838 - return $this->doesExist;
839 - }
840 -
841 - /**
842 - * Return the original filename of the uploaded file
843 - *
844 - * @return mixed Filename or null if non-existent
845 - */
846 - public function getName() {
847 - if ( !$this->exists() ) {
848 - return null;
849 - }
850 -
851 - global $wgContLang;
852 - $name = $this->fileInfo['name'];
853 -
854 - # Safari sends filenames in HTML-encoded Unicode form D...
855 - # Horrid and evil! Let's try to make some kind of sense of it.
856 - $name = Sanitizer::decodeCharReferences( $name );
857 - $name = $wgContLang->normalize( $name );
858 - wfDebug( __METHOD__ . ": {$this->fileInfo['name']} normalized to '$name'\n" );
859 - return $name;
860 - }
861 -
862 - /**
863 - * Return the file size of the uploaded file
864 - *
865 - * @return int File size or zero if non-existent
866 - */
867 - public function getSize() {
868 - if ( !$this->exists() ) {
869 - return 0;
870 - }
871 -
872 - return $this->fileInfo['size'];
873 - }
874 -
875 - /**
876 - * Return the path to the temporary file
877 - *
878 - * @return mixed Path or null if non-existent
879 - */
880 - public function getTempName() {
881 - if ( !$this->exists() ) {
882 - return null;
883 - }
884 -
885 - return $this->fileInfo['tmp_name'];
886 - }
887 -
888 - /**
889 - * Return the upload error. See link for explanation
890 - * http://www.php.net/manual/en/features.file-upload.errors.php
891 - *
892 - * @return int One of the UPLOAD_ constants, 0 if non-existent
893 - */
894 - public function getError() {
895 - if ( !$this->exists() ) {
896 - return 0; # UPLOAD_ERR_OK
897 - }
898 -
899 - return $this->fileInfo['error'];
900 - }
901 -
902 - /**
903 - * Returns whether this upload failed because of overflow of a maximum set
904 - * in php.ini
905 - *
906 - * @return bool
907 - */
908 - public function isIniSizeOverflow() {
909 - if ( $this->getError() == UPLOAD_ERR_INI_SIZE ) {
910 - # PHP indicated that upload_max_filesize is exceeded
911 - return true;
912 - }
913 -
914 - $contentLength = $this->request->getHeader( 'CONTENT_LENGTH' );
915 - if ( $contentLength > wfShorthandToInteger( ini_get( 'post_max_size' ) ) ) {
916 - # post_max_size is exceeded
917 - return true;
918 - }
919 -
920 - return false;
921 - }
922 -}
923 -
924 -/**
925 - * WebRequest clone which takes values from a provided array.
926 - *
927 - * @ingroup HTTP
928 - */
929 -class FauxRequest extends WebRequest {
930 - private $wasPosted = false;
931 - private $session = array();
932 -
933 - /**
934 - * @param $data Array of *non*-urlencoded key => value pairs, the
935 - * fake GET/POST values
936 - * @param $wasPosted Bool: whether to treat the data as POST
937 - * @param $session Mixed: session array or null
938 - */
939 - public function __construct( $data, $wasPosted = false, $session = null ) {
940 - if( is_array( $data ) ) {
941 - $this->data = $data;
942 - } else {
943 - throw new MWException( "FauxRequest() got bogus data" );
944 - }
945 - $this->wasPosted = $wasPosted;
946 - if( $session )
947 - $this->session = $session;
948 - }
949 -
950 - private function notImplemented( $method ) {
951 - throw new MWException( "{$method}() not implemented" );
952 - }
953 -
954 - public function getText( $name, $default = '' ) {
955 - # Override; don't recode since we're using internal data
956 - return (string)$this->getVal( $name, $default );
957 - }
958 -
959 - public function getValues() {
960 - return $this->data;
961 - }
962 -
963 - public function wasPosted() {
964 - return $this->wasPosted;
965 - }
966 -
967 - public function checkSessionCookie() {
968 - return false;
969 - }
970 -
971 - public function getRequestURL() {
972 - $this->notImplemented( __METHOD__ );
973 - }
974 -
975 - public function appendQuery( $query ) {
976 - global $wgTitle;
977 - $basequery = '';
978 - foreach( $this->data as $var => $val ) {
979 - if ( $var == 'title' ) {
980 - continue;
981 - }
982 - if ( is_array( $val ) ) {
983 - /* This will happen given a request like
984 - * http://en.wikipedia.org/w/index.php?title[]=Special:Userlogin&returnto[]=Main_Page
985 - */
986 - continue;
987 - }
988 - $basequery .= '&' . urlencode( $var ) . '=' . urlencode( $val );
989 - }
990 - $basequery .= '&' . $query;
991 -
992 - # Trim the extra &
993 - $basequery = substr( $basequery, 1 );
994 - return $wgTitle->getLocalURL( $basequery );
995 - }
996 -
997 - public function getHeader( $name ) {
998 - return isset( $this->headers[$name] ) ? $this->headers[$name] : false;
999 - }
1000 -
1001 - public function setHeader( $name, $val ) {
1002 - $this->headers[$name] = $val;
1003 - }
1004 -
1005 - public function getSessionData( $key ) {
1006 - if( isset( $this->session[$key] ) )
1007 - return $this->session[$key];
1008 - }
1009 -
1010 - public function setSessionData( $key, $data ) {
1011 - $this->session[$key] = $data;
1012 - }
1013 -
1014 - public function isPathInfoBad() {
1015 - return false;
1016 - }
1017 -}
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedWebStartSetup.php
@@ -0,0 +1,92 @@
 2+<?php
 3+/**
 4+ * This does the initial setup for a web request.
 5+ * It does some security checks, and loads the
 6+ * configuration
 7+ *
 8+ * @file
 9+ */
 10+
 11+# Protect against register_globals
 12+# This must be done before any globals are set by the code
 13+if ( ini_get( 'register_globals' ) ) {
 14+ if ( isset( $_REQUEST['GLOBALS'] ) ) {
 15+ die( '<a href="http://www.hardened-php.net/globals-problem">$GLOBALS overwrite vulnerability</a>');
 16+ }
 17+ $verboten = array(
 18+ 'GLOBALS',
 19+ '_SERVER',
 20+ 'HTTP_SERVER_VARS',
 21+ '_GET',
 22+ 'HTTP_GET_VARS',
 23+ '_POST',
 24+ 'HTTP_POST_VARS',
 25+ '_COOKIE',
 26+ 'HTTP_COOKIE_VARS',
 27+ '_FILES',
 28+ 'HTTP_POST_FILES',
 29+ '_ENV',
 30+ 'HTTP_ENV_VARS',
 31+ '_REQUEST',
 32+ '_SESSION',
 33+ 'HTTP_SESSION_VARS'
 34+ );
 35+ foreach ( $_REQUEST as $name => $value ) {
 36+ if( in_array( $name, $verboten ) ) {
 37+ header( "HTTP/1.x 500 Internal Server Error" );
 38+ echo "register_globals security paranoia: trying to overwrite superglobals, aborting.";
 39+ die( -1 );
 40+ }
 41+ unset( $GLOBALS[$name] );
 42+ }
 43+}
 44+
 45+# Valid web server entry point, enable includes.
 46+# Please don't move this line to includes/Defines.php. This line essentially
 47+# defines a valid entry point. If you put it in includes/Defines.php, then
 48+# any script that includes it becomes an entry point, thereby defeating
 49+# its purpose.
 50+define( 'MEDIAWIKI', true );
 51+
 52+# Full path to working directory.
 53+# Makes it possible to for example to have effective exclude path in apc.
 54+# Also doesn't break installations using symlinked includes, like
 55+# dirname( __FILE__ ) would do.
 56+$IP = getenv( 'MW_INSTALL_PATH' );
 57+if ( $IP === false ) {
 58+ $IP = realpath( '.' );
 59+}
 60+
 61+
 62+# Start the autoloader, so that extensions can derive classes from core files
 63+require_once( "$IP/includes/MwEmbedAutoLoader.php" );
 64+
 65+# Include the mediaWiki stubs.php file ( will stub out un-needed functionality from mediaWiki
 66+require_once( "$IP/includes/MwEmbedMediaWikiStubs.php" );
 67+
 68+# Include global mediaWiki functions
 69+require_once( "$IP/includes/MwEmbedMediaWikiGlobalFunctions.php" );
 70+
 71+# Load default settings
 72+require_once( "$IP/includes/DefaultSettings.php" );
 73+
 74+
 75+if ( !defined('MW_CONFIG_FILE') )
 76+ define('MW_CONFIG_FILE', "$IP/LocalSettings.php");
 77+
 78+# LocalSettings.php is the per site customization file. If it does not exist
 79+# error out
 80+if( !file_exists( MW_CONFIG_FILE ) ) {
 81+ print "alert('your mwEmbed install is missing a localSettings.php');";
 82+ die();
 83+}
 84+
 85+# Load local settings
 86+require_once( "$IP/LocalSettings.php" );
 87+
 88+# Include utility files:
 89+require_once( "$IP/includes/Hooks.php");
 90+
 91+# Create the wgRequest global:
 92+$wgRequest = new WebRequest;
 93+
Property changes on: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedWebStartSetup.php
___________________________________________________________________
Added: svn:executable
194 + *
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedMediaWikiGlobalFunctions.php
@@ -0,0 +1,255 @@
 2+<?php
 3+/**
 4+ * Includes a subset of functions used for mwEmbed found in mediaWiki GlobalFunctions.php
 5+ * and some mwEmbed specific global functions
 6+ */
 7+
 8+# Autodetect, convert and provide timestamps of various types
 9+
 10+/**
 11+ * Unix time - the number of seconds since 1970-01-01 00:00:00 UTC
 12+ */
 13+define( 'TS_UNIX', 0 );
 14+
 15+/**
 16+ * MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS)
 17+ */
 18+define( 'TS_MW', 1 );
 19+
 20+/**
 21+ * MySQL DATETIME (YYYY-MM-DD HH:MM:SS)
 22+ */
 23+define( 'TS_DB', 2 );
 24+
 25+/**
 26+ * RFC 2822 format, for E-mail and HTTP headers
 27+ */
 28+define( 'TS_RFC2822', 3 );
 29+
 30+/**
 31+ * ISO 8601 format with no timezone: 1986-02-09T20:00:00Z
 32+ *
 33+ * This is used by Special:Export
 34+ */
 35+define( 'TS_ISO_8601', 4 );
 36+
 37+/**
 38+ * An Exif timestamp (YYYY:MM:DD HH:MM:SS)
 39+ *
 40+ * @see http://exif.org/Exif2-2.PDF The Exif 2.2 spec, see page 28 for the
 41+ * DateTime tag and page 36 for the DateTimeOriginal and
 42+ * DateTimeDigitized tags.
 43+ */
 44+define( 'TS_EXIF', 5 );
 45+
 46+/**
 47+ * Oracle format time.
 48+ */
 49+define( 'TS_ORACLE', 6 );
 50+
 51+/**
 52+ * Postgres format time.
 53+ */
 54+define( 'TS_POSTGRES', 7 );
 55+
 56+/**
 57+ * DB2 format time
 58+ */
 59+define( 'TS_DB2', 8 );
 60+
 61+/**
 62+ * ISO 8601 basic format with no timezone: 19860209T200000Z
 63+ *
 64+ * This is used by ResourceLoader
 65+ */
 66+define( 'TS_ISO_8601_BASIC', 9 );
 67+
 68+
 69+/**@{
 70+ * Cache type
 71+ */
 72+define( 'CACHE_ANYTHING', -1 ); // Use anything, as long as it works
 73+
 74+/**
 75+ * @param $outputtype Mixed: A timestamp in one of the supported formats, the
 76+ * function will autodetect which format is supplied and act
 77+ * accordingly.
 78+ * @param $ts Mixed: the timestamp to convert or 0 for the current timestamp
 79+ * @return Mixed: String / false The same date in the format specified in $outputtype or false
 80+ */
 81+function wfTimestamp( $outputtype = TS_UNIX, $ts = 0 ) {
 82+ $uts = 0;
 83+ $da = array();
 84+ $strtime = '';
 85+
 86+ if ( !$ts ) { // We want to catch 0, '', null... but not date strings starting with a letter.
 87+ $uts = time();
 88+ $strtime = "@$uts";
 89+ } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/D', $ts, $da ) ) {
 90+ # TS_DB
 91+ } elseif ( preg_match( '/^(\d{4}):(\d\d):(\d\d) (\d\d):(\d\d):(\d\d)$/D', $ts, $da ) ) {
 92+ # TS_EXIF
 93+ } elseif ( preg_match( '/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/D', $ts, $da ) ) {
 94+ # TS_MW
 95+ } elseif ( preg_match( '/^-?\d{1,13}$/D', $ts ) ) {
 96+ # TS_UNIX
 97+ $uts = $ts;
 98+ $strtime = "@$ts"; // Undocumented?
 99+ } elseif ( preg_match( '/^\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}.\d{6}$/', $ts ) ) {
 100+ # TS_ORACLE // session altered to DD-MM-YYYY HH24:MI:SS.FF6
 101+ $strtime = preg_replace( '/(\d\d)\.(\d\d)\.(\d\d)(\.(\d+))?/', "$1:$2:$3",
 102+ str_replace( '+00:00', 'UTC', $ts ) );
 103+ } elseif ( preg_match( '/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.*\d*)?Z$/', $ts, $da ) ) {
 104+ # TS_ISO_8601
 105+ } elseif ( preg_match( '/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(?:\.*\d*)?Z$/', $ts, $da ) ) {
 106+ #TS_ISO_8601_BASIC
 107+ } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d*[\+\- ](\d\d)$/', $ts, $da ) ) {
 108+ # TS_POSTGRES
 109+ } elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d* GMT$/', $ts, $da ) ) {
 110+ # TS_POSTGRES
 111+ } elseif (preg_match('/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.\d\d\d$/',$ts,$da)) {
 112+ # TS_DB2
 113+ } elseif ( preg_match( '/^[ \t\r\n]*([A-Z][a-z]{2},[ \t\r\n]*)?' . # Day of week
 114+ '\d\d?[ \t\r\n]*[A-Z][a-z]{2}[ \t\r\n]*\d{2}(?:\d{2})?' . # dd Mon yyyy
 115+ '[ \t\r\n]*\d\d[ \t\r\n]*:[ \t\r\n]*\d\d[ \t\r\n]*:[ \t\r\n]*\d\d/S', $ts ) ) { # hh:mm:ss
 116+ # TS_RFC2822, accepting a trailing comment. See http://www.squid-cache.org/mail-archive/squid-users/200307/0122.html / r77171
 117+ # The regex is a superset of rfc2822 for readability
 118+ $strtime = strtok( $ts, ';' );
 119+ } elseif ( preg_match( '/^[A-Z][a-z]{5,8}, \d\d-[A-Z][a-z]{2}-\d{2} \d\d:\d\d:\d\d/', $ts ) ) {
 120+ # TS_RFC850
 121+ $strtime = $ts;
 122+ } elseif ( preg_match( '/^[A-Z][a-z]{2} [A-Z][a-z]{2} +\d{1,2} \d\d:\d\d:\d\d \d{4}/', $ts ) ) {
 123+ # asctime
 124+ $strtime = $ts;
 125+ } else {
 126+ # Bogus value...
 127+ wfDebug("wfTimestamp() fed bogus time value: TYPE=$outputtype; VALUE=$ts\n");
 128+
 129+ return false;
 130+ }
 131+
 132+
 133+
 134+ static $formats = array(
 135+ TS_UNIX => 'U',
 136+ TS_MW => 'YmdHis',
 137+ TS_DB => 'Y-m-d H:i:s',
 138+ TS_ISO_8601 => 'Y-m-d\TH:i:s\Z',
 139+ TS_ISO_8601_BASIC => 'Ymd\THis\Z',
 140+ TS_EXIF => 'Y:m:d H:i:s', // This shouldn't ever be used, but is included for completeness
 141+ TS_RFC2822 => 'D, d M Y H:i:s',
 142+ TS_ORACLE => 'd-m-Y H:i:s.000000', // Was 'd-M-y h.i.s A' . ' +00:00' before r51500
 143+ TS_POSTGRES => 'Y-m-d H:i:s',
 144+ TS_DB2 => 'Y-m-d H:i:s',
 145+ );
 146+
 147+ if ( !isset( $formats[$outputtype] ) ) {
 148+ throw new MWException( 'wfTimestamp() called with illegal output type.' );
 149+ }
 150+
 151+ if ( function_exists( "date_create" ) ) {
 152+ if ( count( $da ) ) {
 153+ $ds = sprintf("%04d-%02d-%02dT%02d:%02d:%02d.00+00:00",
 154+ (int)$da[1], (int)$da[2], (int)$da[3],
 155+ (int)$da[4], (int)$da[5], (int)$da[6]);
 156+
 157+ $d = date_create( $ds, new DateTimeZone( 'GMT' ) );
 158+ } elseif ( $strtime ) {
 159+ $d = date_create( $strtime, new DateTimeZone( 'GMT' ) );
 160+ } else {
 161+ return false;
 162+ }
 163+
 164+ if ( !$d ) {
 165+ wfDebug("wfTimestamp() fed bogus time value: $outputtype; $ts\n");
 166+ return false;
 167+ }
 168+
 169+ $output = $d->format( $formats[$outputtype] );
 170+ } else {
 171+ if ( count( $da ) ) {
 172+ // Warning! gmmktime() acts oddly if the month or day is set to 0
 173+ // We may want to handle that explicitly at some point
 174+ $uts = gmmktime( (int)$da[4], (int)$da[5], (int)$da[6],
 175+ (int)$da[2], (int)$da[3], (int)$da[1] );
 176+ } elseif ( $strtime ) {
 177+ $uts = strtotime( $strtime );
 178+ }
 179+
 180+ if ( $uts === false ) {
 181+ wfDebug("wfTimestamp() can't parse the timestamp (non 32-bit time? Update php): $outputtype; $ts\n");
 182+ return false;
 183+ }
 184+
 185+ if ( TS_UNIX == $outputtype ) {
 186+ return $uts;
 187+ }
 188+ $output = gmdate( $formats[$outputtype], $uts );
 189+ }
 190+
 191+ if ( ( $outputtype == TS_RFC2822 ) || ( $outputtype == TS_POSTGRES ) ) {
 192+ $output .= ' GMT';
 193+ }
 194+
 195+ return $output;
 196+}
 197+
 198+// Memcached stubs:
 199+/**
 200+ * Get a cache key
 201+ */
 202+function wfMemcKey( /*... */ ) {
 203+ $args = func_get_args();
 204+ $key = implode( ':', $args );
 205+ $key = str_replace( ' ', '_', $key );
 206+ return $key;
 207+}
 208+function wfGetCache( ){
 209+ return new mwEmbedSimpleFileCache();
 210+}
 211+class mwEmbedSimpleFileCache{
 212+ public static function get( $key ){
 213+ return mweGetFromFileCache( $key );
 214+ }
 215+ public static function set( $key, $data){
 216+ return mweSaveFileToCache( $key, $data);
 217+ }
 218+}
 219+
 220+# MwEmbed specific functions
 221+/*
 222+ * Retrive a file from cache key
 223+ *
 224+ */
 225+function mweGetFromFileCache( $key ){
 226+ global $IP;
 227+ $filePath = mwGetFilePathFromKey( $key );
 228+ $rawResult = @file_get_contents( $filePath );
 229+ if( $rawResult === false ){
 230+ return null;
 231+ }
 232+ return unserialize( $rawResult );
 233+};
 234+/**
 235+ * Save a file to cache key
 236+ * @param $key String
 237+ * @param $data {Object|String}
 238+ */
 239+function mweSaveFileToCache ( $key, $data){
 240+ global $IP;
 241+ $filePath = mwGetFilePathFromKey( $key );
 242+ $path = dirname( $filePath );
 243+ $ok = mkdir( $path, 0777, true ); // PHP5 <3
 244+ if( !$ok ){
 245+ return false;
 246+ }
 247+ return @file_put_contents( $filePath, serialize( $data ) );
 248+}
 249+function mwGetFilePathFromKey( $key ){
 250+ global $IP;
 251+ $hash = md5( $key );
 252+ // Pretty darn unlikely cache missmatch:
 253+ return "$IP/cache/". substr( $hash, 0, 1) . '/' . substr( $hash, 1, 1) .
 254+ '/' . substr( $key, 0, 48 );
 255+}
 256+?>
\ No newline at end of file
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedResourceLoader.php
@@ -6,5 +6,67 @@
77 * http://www.mediawiki.org/wiki/ResourceLoader
88 */
99
 10+class MwEmbedResourceLoader extends ResourceLoader {
 11+ /**
 12+ * Registers core modules and runs registration hooks.
 13+ */
 14+ public function __construct() {
 15+ global $IP, $wgResourceModules;
 16+
 17+ wfProfileIn( __METHOD__ );
 18+
 19+ // Register modules shared between mwEmbed and mediaWiki:
 20+ $this->register( include( "$IP/resources/MwEmbedSharedResources.php" ) );
 21+ // Register extension modules
 22+ wfRunHooks( 'ResourceLoaderRegisterModules', array( &$this ) );
 23+ $this->register( $wgResourceModules );
 24+
 25+ wfProfileOut( __METHOD__ );
 26+ }
 27+ /**
 28+ * Stubs out preLoadModuleInfo call in mwEmbed we always get info from
 29+ * php resource description files
 30+ */
 31+ public function preloadModuleInfo( array $modules, ResourceLoaderContext $context ) {
 32+ // Note it maybe nice to read searlized per module info. We will want to
 33+ // run this rarely and have an outer file cache respond to requests.
 34+
 35+ // Since we don't have user scripts and frequently changing modules we could read a 'release'
 36+ // version global or svn version
 37+ return ;
 38+ }
 39+
 40+ /**
 41+ * Get the ResourceLoaderModule object for a given module name.
 42+ *
 43+ * @param $name String: Module name
 44+ * @return Mixed: ResourceLoaderModule if module has been registered, null otherwise
 45+ */
 46+ public function getModule( $name ) {
 47+ if ( !isset( $this->modules[$name] ) ) {
 48+ if ( !isset( $this->moduleInfos[$name] ) ) {
 49+ // No such module
 50+ return null;
 51+ }
 52+ // Construct the requested object
 53+ $info = $this->moduleInfos[$name];
 54+ if ( isset( $info['object'] ) ) {
 55+ // Object given in info array
 56+ $object = $info['object'];
 57+ } else {
 58+ if ( !isset( $info['class'] ) ) {
 59+ $class = 'MwEmbedResourceLoaderFileModule';
 60+ } else {
 61+ $class = $info['class'];
 62+ }
 63+ $object = new $class( $info );
 64+ }
 65+ $object->setName( $name );
 66+ $this->modules[$name] = $object;
 67+ }
1068
 69+ return $this->modules[$name];
 70+ }
 71+}
 72+
1173 ?>
\ No newline at end of file
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedAutoLoader.php
@@ -1,6 +1,6 @@
22 <?php
33 /**
4 - * This defines autoloading handler for whole MediaWiki framework
 4+ * This defines autoloading handler for ( mwEmbed ) framework
55 *
66 * @file
77 */
@@ -14,12 +14,22 @@
1515
1616 $wgAutoloadLocalClasses = array(
1717
 18+ # Files copied without modification from mediaWiki
1819 'ResourceLoader' => 'includes/resourceloader/ResourceLoader.php',
1920 'ResourceLoaderContext' => 'includes/resourceloader/ResourceLoaderContext.php',
2021 'ResourceLoaderModule' => 'includes/resourceloader/ResourceLoaderModule.php',
2122 'ResourceLoaderFileModule' => 'includes/resourceloader/ResourceLoaderFileModule.php',
2223 'ResourceLoaderStartUpModule' => 'includes/resourceloader/ResourceLoaderStartUpModule.php',
2324
 25+ 'CSSJanus' => 'includes/libs/CSSJanus.php',
 26+ 'CSSMin' => 'includes/libs/CSSMin.php',
 27+ 'JSMin' => 'includes/libs/JSMin.php',
 28+
 29+ # MwEmbed files ( that get autoloaded ):
 30+ 'MwEmbedResourceLoader' => 'includes/MwEmbedResourceLoader.php',
 31+ 'MwEmbedResourceLoaderFileModule' => 'includes/MwEmbedResourceLoaderFileModule.php',
 32+ 'MwEmbedResourceLoaderStartUpModule' => 'includes/MwEmbedResourceLoaderStartUpModule.php',
 33+
2434 );
2535
2636 class AutoLoader {
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/Hooks.php
@@ -0,0 +1,206 @@
 2+<?php
 3+/**
 4+ * A tool for running hook functions.
 5+ *
 6+ * Copyright 2004, 2005 Evan Prodromou <evan@wikitravel.org>.
 7+ *
 8+ * This program is free software; you can redistribute it and/or modify
 9+ * it under the terms of the GNU General Public License as published by
 10+ * the Free Software Foundation; either version 2 of the License, or
 11+ * (at your option) any later version.
 12+ *
 13+ * This program is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 16+ * GNU General Public License for more details.
 17+ *
 18+ * You should have received a copy of the GNU General Public License
 19+ * along with this program; if not, write to the Free Software
 20+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 21+ *
 22+ * @author Evan Prodromou <evan@wikitravel.org>
 23+ * @see hooks.txt
 24+ * @file
 25+ */
 26+
 27+
 28+/**
 29+ * Call hook functions defined in $wgHooks
 30+ *
 31+ * Because programmers assign to $wgHooks, we need to be very
 32+ * careful about its contents. So, there's a lot more error-checking
 33+ * in here than would normally be necessary.
 34+ *
 35+ * @param $event String: event name
 36+ * @param $args Array: parameters passed to hook functions
 37+ * @return Boolean
 38+ */
 39+function wfRunHooks($event, $args = array()) {
 40+
 41+ global $wgHooks;
 42+
 43+ // Return quickly in the most common case
 44+ if ( !isset( $wgHooks[$event] ) ) {
 45+ return true;
 46+ }
 47+
 48+ if (!is_array($wgHooks)) {
 49+ throw new MWException("Global hooks array is not an array!\n");
 50+ }
 51+
 52+ if (!is_array($wgHooks[$event])) {
 53+ throw new MWException("Hooks array for event '$event' is not an array!\n");
 54+ }
 55+
 56+ foreach ($wgHooks[$event] as $index => $hook) {
 57+
 58+ $object = null;
 59+ $method = null;
 60+ $func = null;
 61+ $data = null;
 62+ $have_data = false;
 63+ $closure = false;
 64+ $badhookmsg = false;
 65+
 66+ /* $hook can be: a function, an object, an array of $function and $data,
 67+ * an array of just a function, an array of object and method, or an
 68+ * array of object, method, and data.
 69+ */
 70+
 71+ if ( is_array( $hook ) ) {
 72+ if ( count( $hook ) < 1 ) {
 73+ throw new MWException("Empty array in hooks for " . $event . "\n");
 74+ } else if ( is_object( $hook[0] ) ) {
 75+ $object = $wgHooks[$event][$index][0];
 76+ if ( $object instanceof Closure ) {
 77+ $closure = true;
 78+ if ( count( $hook ) > 1 ) {
 79+ $data = $hook[1];
 80+ $have_data = true;
 81+ }
 82+ } else {
 83+ if ( count( $hook ) < 2 ) {
 84+ $method = "on" . $event;
 85+ } else {
 86+ $method = $hook[1];
 87+ if ( count( $hook ) > 2 ) {
 88+ $data = $hook[2];
 89+ $have_data = true;
 90+ }
 91+ }
 92+ }
 93+ } else if ( is_string( $hook[0] ) ) {
 94+ $func = $hook[0];
 95+ if ( count( $hook ) > 1) {
 96+ $data = $hook[1];
 97+ $have_data = true;
 98+ }
 99+ } else {
 100+ throw new MWException( "Unknown datatype in hooks for " . $event . "\n" );
 101+ }
 102+ } else if ( is_string( $hook ) ) { # functions look like strings, too
 103+ $func = $hook;
 104+ } else if ( is_object( $hook ) ) {
 105+ $object = $wgHooks[$event][$index];
 106+ if ( $object instanceof Closure ) {
 107+ $closure = true;
 108+ } else {
 109+ $method = "on" . $event;
 110+ }
 111+ } else {
 112+ throw new MWException( "Unknown datatype in hooks for " . $event . "\n" );
 113+ }
 114+
 115+ /* We put the first data element on, if needed. */
 116+
 117+ if ( $have_data ) {
 118+ $hook_args = array_merge(array($data), $args);
 119+ } else {
 120+ $hook_args = $args;
 121+ }
 122+
 123+ if ( $closure ) {
 124+ $callback = $object;
 125+ $func = "hook-$event-closure";
 126+ } elseif ( isset( $object ) ) {
 127+ $func = get_class( $object ) . '::' . $method;
 128+ $callback = array( $object, $method );
 129+ } elseif ( false !== ( $pos = strpos( $func, '::' ) ) ) {
 130+ $callback = array( substr( $func, 0, $pos ), substr( $func, $pos + 2 ) );
 131+ } else {
 132+ $callback = $func;
 133+ }
 134+
 135+ // Run autoloader (workaround for call_user_func_array bug)
 136+ is_callable( $callback );
 137+
 138+ /* Call the hook. The documentation of call_user_func_array clearly
 139+ * states that FALSE is returned on failure. However this is not
 140+ * case always. In some version of PHP if the function signature
 141+ * does not match the call signature, PHP will issue an warning:
 142+ * Param y in x expected to be a reference, value given.
 143+ *
 144+ * In that case the call will also return null. The following code
 145+ * catches that warning and provides better error message. The
 146+ * function documentation also says that:
 147+ * In other words, it does not depend on the function signature
 148+ * whether the parameter is passed by a value or by a reference.
 149+ * There is also PHP bug http://bugs.php.net/bug.php?id=47554 which
 150+ * is unsurprisingly marked as bogus. In short handling of failures
 151+ * with call_user_func_array is a failure, the documentation for that
 152+ * function is wrong and misleading and PHP developers don't see any
 153+ * problem here.
 154+ */
 155+ $retval = null;
 156+ set_error_handler( 'hookErrorHandler' );
 157+ wfProfileIn( $func );
 158+ try {
 159+ $retval = call_user_func_array( $callback, $hook_args );
 160+ } catch ( MWHookException $e ) {
 161+ $badhookmsg = $e->getMessage();
 162+ }
 163+ wfProfileOut( $func );
 164+ restore_error_handler();
 165+
 166+ /* String return is an error; false return means stop processing. */
 167+ if ( is_string( $retval ) ) {
 168+ global $wgOut;
 169+ $wgOut->showFatalError( $retval );
 170+ return false;
 171+ } elseif( $retval === null ) {
 172+ if ( $closure ) {
 173+ $prettyFunc = "$event closure";
 174+ } elseif( is_array( $callback ) ) {
 175+ if( is_object( $callback[0] ) ) {
 176+ $prettyClass = get_class( $callback[0] );
 177+ } else {
 178+ $prettyClass = strval( $callback[0] );
 179+ }
 180+ $prettyFunc = $prettyClass . '::' . strval( $callback[1] );
 181+ } else {
 182+ $prettyFunc = strval( $callback );
 183+ }
 184+ if ( $badhookmsg ) {
 185+ throw new MWException( "Detected bug in an extension! " .
 186+ "Hook $prettyFunc has invalid call signature; " . $badhookmsg );
 187+ } else {
 188+ throw new MWException( "Detected bug in an extension! " .
 189+ "Hook $prettyFunc failed to return a value; " .
 190+ "should return true to continue hook processing or false to abort." );
 191+ }
 192+ } else if ( !$retval ) {
 193+ return false;
 194+ }
 195+ }
 196+
 197+ return true;
 198+}
 199+
 200+function hookErrorHandler( $errno, $errstr ) {
 201+ if ( strpos( $errstr, 'expected to be a reference, value given' ) !== false ) {
 202+ throw new MWHookException( $errstr );
 203+ }
 204+ return false;
 205+}
 206+
 207+class MWHookException extends MWException {}
\ No newline at end of file
Property changes on: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/Hooks.php
___________________________________________________________________
Added: svn:executable
1208 + *
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/libs/CSSJanus.php
@@ -0,0 +1,323 @@
 2+<?php
 3+/**
 4+ * This program is free software; you can redistribute it and/or modify
 5+ * it under the terms of the GNU General Public License as published by
 6+ * the Free Software Foundation; either version 2 of the License, or
 7+ * (at your option) any later version.
 8+ *
 9+ * This program is distributed in the hope that it will be useful,
 10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 12+ * GNU General Public License for more details.
 13+ *
 14+ * You should have received a copy of the GNU General Public License along
 15+ * with this program; if not, write to the Free Software Foundation, Inc.,
 16+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 17+ * http://www.gnu.org/copyleft/gpl.html
 18+ *
 19+ */
 20+
 21+/**
 22+ * This is a PHP port of CSSJanus, a utility that transforms CSS style sheets
 23+ * written for LTR to RTL.
 24+ *
 25+ * The original Python version of CSSJanus is Copyright 2008 by Google Inc. and
 26+ * is distributed under the Apache license.
 27+ *
 28+ * Original code: http://code.google.com/p/cssjanus/source/browse/trunk/cssjanus.py
 29+ * License of original code: http://code.google.com/p/cssjanus/source/browse/trunk/LICENSE
 30+ * @author Roan Kattouw
 31+ *
 32+ */
 33+class CSSJanus {
 34+ // Patterns defined as null are built dynamically by buildPatterns()
 35+ private static $patterns = array(
 36+ 'tmpToken' => '`TMP`',
 37+ 'nonAscii' => '[\200-\377]',
 38+ 'unicode' => '(?:(?:\\[0-9a-f]{1,6})(?:\r\n|\s)?)',
 39+ 'num' => '(?:[0-9]*\.[0-9]+|[0-9]+)',
 40+ 'unit' => '(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)',
 41+ 'body_selector' => 'body\s*{\s*',
 42+ 'direction' => 'direction\s*:\s*',
 43+ 'escape' => null,
 44+ 'nmstart' => null,
 45+ 'nmchar' => null,
 46+ 'ident' => null,
 47+ 'quantity' => null,
 48+ 'possibly_negative_quantity' => null,
 49+ 'color' => null,
 50+ 'url_special_chars' => '[!#$%&*-~]',
 51+ 'valid_after_uri_chars' => '[\'\"]?\s*',
 52+ 'url_chars' => null,
 53+ 'lookahead_not_open_brace' => null,
 54+ 'lookahead_not_closing_paren' => null,
 55+ 'lookahead_for_closing_paren' => null,
 56+ 'lookbehind_not_letter' => '(?<![a-zA-Z])',
 57+ 'chars_within_selector' => '[^\}]*?',
 58+ 'noflip_annotation' => '\/\*\s*@noflip\s*\*\/',
 59+ 'noflip_single' => null,
 60+ 'noflip_class' => null,
 61+ 'comment' => '/\/\*[^*]*\*+([^\/*][^*]*\*+)*\//',
 62+ 'direction_ltr' => null,
 63+ 'direction_rtl' => null,
 64+ 'left' => null,
 65+ 'right' => null,
 66+ 'left_in_url' => null,
 67+ 'right_in_url' => null,
 68+ 'ltr_in_url' => null,
 69+ 'rtl_in_url' => null,
 70+ 'cursor_east' => null,
 71+ 'cursor_west' => null,
 72+ 'four_notation_quantity' => null,
 73+ 'four_notation_color' => null,
 74+ 'bg_horizontal_percentage' => null,
 75+ 'bg_horizontal_percentage_x' => null,
 76+ );
 77+
 78+ /**
 79+ * Build patterns we can't define above because they depend on other patterns.
 80+ */
 81+ private static function buildPatterns() {
 82+ if ( !is_null( self::$patterns['escape'] ) ) {
 83+ // Patterns have already been built
 84+ return;
 85+ }
 86+
 87+ $patterns =& self::$patterns;
 88+ $patterns['escape'] = "(?:{$patterns['unicode']}|\\[^\r\n\f0-9a-f])";
 89+ $patterns['nmstart'] = "(?:[_a-z]|{$patterns['nonAscii']}|{$patterns['escape']})";
 90+ $patterns['nmchar'] = "(?:[_a-z0-9-]|{$patterns['nonAscii']}|{$patterns['escape']})";
 91+ $patterns['ident'] = "-?{$patterns['nmstart']}{$patterns['nmchar']}*";
 92+ $patterns['quantity'] = "{$patterns['num']}(?:\s*{$patterns['unit']}|{$patterns['ident']})?";
 93+ $patterns['possibly_negative_quantity'] = "((?:-?{$patterns['quantity']})|(?:inherit|auto))";
 94+ $patterns['color'] = "(#?{$patterns['nmchar']}+)";
 95+ $patterns['url_chars'] = "(?:{$patterns['url_special_chars']}|{$patterns['nonAscii']}|{$patterns['escape']})*";
 96+ $patterns['lookahead_not_open_brace'] = "(?!({$patterns['nmchar']}|\r?\n|\s|#|\:|\.|\,|\+|>)*?{)";
 97+ $patterns['lookahead_not_closing_paren'] = "(?!{$patterns['url_chars']}?{$patterns['valid_after_uri_chars']}\))";
 98+ $patterns['lookahead_for_closing_paren'] = "(?={$patterns['url_chars']}?{$patterns['valid_after_uri_chars']}\))";
 99+ $patterns['noflip_single'] = "/({$patterns['noflip_annotation']}{$patterns['lookahead_not_open_brace']}[^;}]+;?)/i";
 100+ $patterns['noflip_class'] = "/({$patterns['noflip_annotation']}{$patterns['chars_within_selector']}})/i";
 101+ $patterns['direction_ltr'] = "/({$patterns['direction']})ltr/i";
 102+ $patterns['direction_rtl'] = "/({$patterns['direction']})rtl/i";
 103+ $patterns['left'] = "/{$patterns['lookbehind_not_letter']}(left){$patterns['lookahead_not_closing_paren']}{$patterns['lookahead_not_open_brace']}/i";
 104+ $patterns['right'] = "/{$patterns['lookbehind_not_letter']}(right){$patterns['lookahead_not_closing_paren']}{$patterns['lookahead_not_open_brace']}/i";
 105+ $patterns['left_in_url'] = "/{$patterns['lookbehind_not_letter']}(left){$patterns['lookahead_for_closing_paren']}/i";
 106+ $patterns['right_in_url'] = "/{$patterns['lookbehind_not_letter']}(right){$patterns['lookahead_for_closing_paren']}/i";
 107+ $patterns['ltr_in_url'] = "/{$patterns['lookbehind_not_letter']}(ltr){$patterns['lookahead_for_closing_paren']}/i";
 108+ $patterns['rtl_in_url'] = "/{$patterns['lookbehind_not_letter']}(rtl){$patterns['lookahead_for_closing_paren']}/i";
 109+ $patterns['cursor_east'] = "/{$patterns['lookbehind_not_letter']}([ns]?)e-resize/";
 110+ $patterns['cursor_west'] = "/{$patterns['lookbehind_not_letter']}([ns]?)w-resize/";
 111+ $patterns['four_notation_quantity'] = "/{$patterns['possibly_negative_quantity']}(\s+){$patterns['possibly_negative_quantity']}(\s+){$patterns['possibly_negative_quantity']}(\s+){$patterns['possibly_negative_quantity']}/i";
 112+ $patterns['four_notation_color'] = "/(-color\s*:\s*){$patterns['color']}(\s+){$patterns['color']}(\s+){$patterns['color']}(\s+){$patterns['color']}/i";
 113+ // The two regexes below are parenthesized differently then in the original implementation to make the
 114+ // callback's job more straightforward
 115+ $patterns['bg_horizontal_percentage'] = "/(background(?:-position)?\s*:\s*[^%]*?)({$patterns['num']})(%\s*(?:{$patterns['quantity']}|{$patterns['ident']}))/";
 116+ $patterns['bg_horizontal_percentage_x'] = "/(background-position-x\s*:\s*)({$patterns['num']})(%)/";
 117+ }
 118+
 119+ /**
 120+ * Transform an LTR stylesheet to RTL
 121+ * @param $css String: stylesheet to transform
 122+ * @param $swapLtrRtlInURL Boolean: If true, swap 'ltr' and 'rtl' in URLs
 123+ * @param $swapLeftRightInURL Boolean: If true, swap 'left' and 'right' in URLs
 124+ * @return Transformed stylesheet
 125+ */
 126+ public static function transform( $css, $swapLtrRtlInURL = false, $swapLeftRightInURL = false ) {
 127+ // We wrap tokens in ` , not ~ like the original implementation does.
 128+ // This was done because ` is not a legal character in CSS and can only
 129+ // occur in URLs, where we escape it to %60 before inserting our tokens.
 130+ $css = str_replace( '`', '%60', $css );
 131+
 132+ self::buildPatterns();
 133+
 134+ // Tokenize single line rules with /* @noflip */
 135+ $noFlipSingle = new CSSJanus_Tokenizer( self::$patterns['noflip_single'], '`NOFLIP_SINGLE`' );
 136+ $css = $noFlipSingle->tokenize( $css );
 137+
 138+ // Tokenize class rules with /* @noflip */
 139+ $noFlipClass = new CSSJanus_Tokenizer( self::$patterns['noflip_class'], '`NOFLIP_CLASS`' );
 140+ $css = $noFlipClass->tokenize( $css );
 141+
 142+ // Tokenize comments
 143+ $comments = new CSSJanus_Tokenizer( self::$patterns['comment'], '`C`' );
 144+ $css = $comments->tokenize( $css );
 145+
 146+ // LTR->RTL fixes start here
 147+ $css = self::fixDirection( $css );
 148+ if ( $swapLtrRtlInURL ) {
 149+ $css = self::fixLtrRtlInURL( $css );
 150+ }
 151+
 152+ if ( $swapLeftRightInURL ) {
 153+ $css = self::fixLeftRightInURL( $css );
 154+ }
 155+ $css = self::fixLeftAndRight( $css );
 156+ $css = self::fixCursorProperties( $css );
 157+ $css = self::fixFourPartNotation( $css );
 158+ $css = self::fixBackgroundPosition( $css );
 159+
 160+ // Detokenize stuff we tokenized before
 161+ $css = $comments->detokenize( $css );
 162+ $css = $noFlipClass->detokenize( $css );
 163+ $css = $noFlipSingle->detokenize( $css );
 164+
 165+ return $css;
 166+ }
 167+
 168+ /**
 169+ * Replace direction: ltr; with direction: rtl; and vice versa.
 170+ *
 171+ * The original implementation only does this inside body selectors
 172+ * and misses "body\n{\ndirection:ltr;\n}". This function does not have
 173+ * these problems.
 174+ *
 175+ * See http://code.google.com/p/cssjanus/issues/detail?id=15 and
 176+ * TODO: URL
 177+ */
 178+ private static function fixDirection( $css ) {
 179+ $css = preg_replace( self::$patterns['direction_ltr'],
 180+ '$1' . self::$patterns['tmpToken'], $css );
 181+ $css = preg_replace( self::$patterns['direction_rtl'], '$1ltr', $css );
 182+ $css = str_replace( self::$patterns['tmpToken'], 'rtl', $css );
 183+
 184+ return $css;
 185+ }
 186+
 187+ /**
 188+ * Replace 'ltr' with 'rtl' and vice versa in background URLs
 189+ */
 190+ private static function fixLtrRtlInURL( $css ) {
 191+ $css = preg_replace( self::$patterns['ltr_in_url'], self::$patterns['tmpToken'], $css );
 192+ $css = preg_replace( self::$patterns['rtl_in_url'], 'ltr', $css );
 193+ $css = str_replace( self::$patterns['tmpToken'], 'rtl', $css );
 194+
 195+ return $css;
 196+ }
 197+
 198+ /**
 199+ * Replace 'left' with 'right' and vice versa in background URLs
 200+ */
 201+ private static function fixLeftRightInURL( $css ) {
 202+ $css = preg_replace( self::$patterns['left_in_url'], self::$patterns['tmpToken'], $css );
 203+ $css = preg_replace( self::$patterns['right_in_url'], 'left', $css );
 204+ $css = str_replace( self::$patterns['tmpToken'], 'right', $css );
 205+
 206+ return $css;
 207+ }
 208+
 209+ /**
 210+ * Flip rules like left: , padding-right: , etc.
 211+ */
 212+ private static function fixLeftAndRight( $css ) {
 213+ $css = preg_replace( self::$patterns['left'], self::$patterns['tmpToken'], $css );
 214+ $css = preg_replace( self::$patterns['right'], 'left', $css );
 215+ $css = str_replace( self::$patterns['tmpToken'], 'right', $css );
 216+
 217+ return $css;
 218+ }
 219+
 220+ /**
 221+ * Flip East and West in rules like cursor: nw-resize;
 222+ */
 223+ private static function fixCursorProperties( $css ) {
 224+ $css = preg_replace( self::$patterns['cursor_east'],
 225+ '$1' . self::$patterns['tmpToken'], $css );
 226+ $css = preg_replace( self::$patterns['cursor_west'], '$1e-resize', $css );
 227+ $css = str_replace( self::$patterns['tmpToken'], 'w-resize', $css );
 228+
 229+ return $css;
 230+ }
 231+
 232+ /**
 233+ * Swap the second and fourth parts in four-part notation rules like
 234+ * padding: 1px 2px 3px 4px;
 235+ *
 236+ * Unlike the original implementation, this function doesn't suffer from
 237+ * the bug where whitespace is not preserved when flipping four-part rules
 238+ * and four-part color rules with multiple whitespace characters between
 239+ * colors are not recognized.
 240+ * See http://code.google.com/p/cssjanus/issues/detail?id=16
 241+ */
 242+ private static function fixFourPartNotation( $css ) {
 243+ $css = preg_replace( self::$patterns['four_notation_quantity'], '$1$2$7$4$5$6$3', $css );
 244+ $css = preg_replace( self::$patterns['four_notation_color'], '$1$2$3$8$5$6$7$4', $css );
 245+
 246+ return $css;
 247+ }
 248+
 249+ /**
 250+ * Flip horizontal background percentages.
 251+ */
 252+ private static function fixBackgroundPosition( $css ) {
 253+ $css = preg_replace_callback( self::$patterns['bg_horizontal_percentage'],
 254+ array( 'self', 'calculateNewBackgroundPosition' ), $css );
 255+ $css = preg_replace_callback( self::$patterns['bg_horizontal_percentage_x'],
 256+ array( 'self', 'calculateNewBackgroundPosition' ), $css );
 257+
 258+ return $css;
 259+ }
 260+
 261+ /**
 262+ * Callback for calculateNewBackgroundPosition()
 263+ */
 264+ private static function calculateNewBackgroundPosition( $matches ) {
 265+ return $matches[1] . ( 100 - $matches[2] ) . $matches[3];
 266+ }
 267+}
 268+
 269+/**
 270+ * Utility class used by CSSJanus that tokenizes and untokenizes things we want
 271+ * to protect from being janused.
 272+ * @author Roan Kattouw
 273+ */
 274+class CSSJanus_Tokenizer {
 275+ private $regex, $token;
 276+ private $originals;
 277+
 278+ /**
 279+ * Constructor
 280+ * @param $regex string Regular expression whose matches to replace by a token.
 281+ * @param $token string Token
 282+ */
 283+ public function __construct( $regex, $token ) {
 284+ $this->regex = $regex;
 285+ $this->token = $token;
 286+ $this->originals = array();
 287+ }
 288+
 289+ /**
 290+ * Replace all occurrences of $regex in $str with a token and remember
 291+ * the original strings.
 292+ * @param $str String to tokenize
 293+ * @return string Tokenized string
 294+ */
 295+ public function tokenize( $str ) {
 296+ return preg_replace_callback( $this->regex, array( $this, 'tokenizeCallback' ), $str );
 297+ }
 298+
 299+ private function tokenizeCallback( $matches ) {
 300+ $this->originals[] = $matches[0];
 301+ return $this->token;
 302+ }
 303+
 304+ /**
 305+ * Replace tokens with their originals. If multiple strings were tokenized, it's important they be
 306+ * detokenized in exactly the SAME ORDER.
 307+ * @param $str String: previously run through tokenize()
 308+ * @return string Original string
 309+ */
 310+ public function detokenize( $str ) {
 311+ // PHP has no function to replace only the first occurrence or to
 312+ // replace occurrences of the same string with different values,
 313+ // so we use preg_replace_callback() even though we don't really need a regex
 314+ return preg_replace_callback( '/' . preg_quote( $this->token, '/' ) . '/',
 315+ array( $this, 'detokenizeCallback' ), $str );
 316+ }
 317+
 318+ private function detokenizeCallback( $matches ) {
 319+ $retval = current( $this->originals );
 320+ next( $this->originals );
 321+
 322+ return $retval;
 323+ }
 324+}
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/libs/CSSMin.php
@@ -0,0 +1,179 @@
 2+<?php
 3+/*
 4+ * Copyright 2010 Wikimedia Foundation
 5+ *
 6+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
 7+ * not use this file except in compliance with the License.
 8+ * You may obtain a copy of the License at
 9+ *
 10+ * http://www.apache.org/licenses/LICENSE-2.0
 11+ *
 12+ * Unless required by applicable law or agreed to in writing, software distributed
 13+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
 14+ * OF ANY KIND, either express or implied. See the License for the
 15+ * specific language governing permissions and limitations under the License.
 16+ */
 17+
 18+/**
 19+ * Transforms CSS data
 20+ *
 21+ * This class provides minification, URL remapping, URL extracting, and data-URL embedding.
 22+ *
 23+ * @file
 24+ * @version 0.1.1 -- 2010-09-11
 25+ * @author Trevor Parscal <tparscal@wikimedia.org>
 26+ * @copyright Copyright 2010 Wikimedia Foundation
 27+ * @license http://www.apache.org/licenses/LICENSE-2.0
 28+ */
 29+class CSSMin {
 30+
 31+ /* Constants */
 32+
 33+ /**
 34+ * Maximum file size to still qualify for in-line embedding as a data-URI
 35+ *
 36+ * 24,576 is used because Internet Explorer has a 32,768 byte limit for data URIs,
 37+ * which when base64 encoded will result in a 1/3 increase in size.
 38+ */
 39+ const EMBED_SIZE_LIMIT = 24576;
 40+ const URL_REGEX = 'url\(\s*[\'"]?(?P<file>[^\?\)\:\'"]*)\??[^\)\'"]*[\'"]?\s*\)';
 41+
 42+ /* Protected Static Members */
 43+
 44+ /** @var array List of common image files extensions and mime-types */
 45+ protected static $mimeTypes = array(
 46+ 'gif' => 'image/gif',
 47+ 'jpe' => 'image/jpeg',
 48+ 'jpeg' => 'image/jpeg',
 49+ 'jpg' => 'image/jpeg',
 50+ 'png' => 'image/png',
 51+ 'tif' => 'image/tiff',
 52+ 'tiff' => 'image/tiff',
 53+ 'xbm' => 'image/x-xbitmap',
 54+ );
 55+
 56+ /* Static Methods */
 57+
 58+ /**
 59+ * Gets a list of local file paths which are referenced in a CSS style sheet
 60+ *
 61+ * @param $source string CSS data to remap
 62+ * @param $path string File path where the source was read from (optional)
 63+ * @return array List of local file references
 64+ */
 65+ public static function getLocalFileReferences( $source, $path = null ) {
 66+ $files = array();
 67+ $rFlags = PREG_OFFSET_CAPTURE | PREG_SET_ORDER;
 68+ if ( preg_match_all( '/' . self::URL_REGEX . '/', $source, $matches, $rFlags ) ) {
 69+ foreach ( $matches as $match ) {
 70+ $file = ( isset( $path )
 71+ ? rtrim( $path, '/' ) . '/'
 72+ : '' ) . "{$match['file'][0]}";
 73+
 74+ // Only proceed if we can access the file
 75+ if ( !is_null( $path ) && file_exists( $file ) ) {
 76+ $files[] = $file;
 77+ }
 78+ }
 79+ }
 80+ return $files;
 81+ }
 82+
 83+ /**
 84+ * Remaps CSS URL paths and automatically embeds data URIs for URL rules
 85+ * preceded by an /* @embed * / comment
 86+ *
 87+ * @param $source string CSS data to remap
 88+ * @param $local string File path where the source was read from
 89+ * @param $remote string URL path to the file
 90+ * @param $embed ???
 91+ * @return string Remapped CSS data
 92+ */
 93+ public static function remap( $source, $local, $remote, $embed = true ) {
 94+ $pattern = '/((?P<embed>\s*\/\*\s*\@embed\s*\*\/)(?P<pre>[^\;\}]*))?' .
 95+ self::URL_REGEX . '(?P<post>[^;]*)[\;]?/';
 96+ $offset = 0;
 97+ while ( preg_match( $pattern, $source, $match, PREG_OFFSET_CAPTURE, $offset ) ) {
 98+ // Shortcuts
 99+ $embed = $match['embed'][0];
 100+ $pre = $match['pre'][0];
 101+ $post = $match['post'][0];
 102+ $file = "{$local}/{$match['file'][0]}";
 103+ $url = "{$remote}/{$match['file'][0]}";
 104+ // Only proceed if we can access the file
 105+ if ( file_exists( $file ) ) {
 106+ // Add version parameter as a time-stamp in ISO 8601 format,
 107+ // using Z for the timezone, meaning GMT
 108+ $url .= '?' . gmdate( 'Y-m-d\TH:i:s\Z', round( filemtime( $file ), -2 ) );
 109+ // If we the mime-type can't be determined, no embedding will take place
 110+ $type = false;
 111+ $realpath = realpath( $file );
 112+ // Try a couple of different ways to get the mime-type of a file,
 113+ // in order of preference
 114+ if ( $realpath
 115+ && function_exists( 'finfo_file' ) && function_exists( 'finfo_open' )
 116+ && defined( 'FILEINFO_MIME_TYPE' ) )
 117+ {
 118+ // As of PHP 5.3, this is how you get the mime-type of a file;
 119+ // it uses the Fileinfo PECL extension
 120+ $type = finfo_file( finfo_open( FILEINFO_MIME_TYPE ), $realpath );
 121+ } else if ( function_exists( 'mime_content_type' ) ) {
 122+ // Before this was deprecated in PHP 5.3,
 123+ // this used to be how you get the mime-type of a file
 124+ $type = mime_content_type( $file );
 125+ } else {
 126+ // Worst-case scenario has happened,
 127+ // use the file extension to infer the mime-type
 128+ $ext = strtolower( pathinfo( $file, PATHINFO_EXTENSION ) );
 129+ if ( isset( self::$mimeTypes[$ext] ) ) {
 130+ $type = self::$mimeTypes[$ext];
 131+ }
 132+ }
 133+ // Detect when URLs were preceeded with embed tags,
 134+ // and also verify file size is below the limit
 135+ if ( $embed && $type && $match['embed'][1] > 0
 136+ && filesize( $file ) < self::EMBED_SIZE_LIMIT )
 137+ {
 138+ // Strip off any trailing = symbols (makes browsers freak out)
 139+ $data = base64_encode( file_get_contents( $file ) );
 140+ // Build 2 CSS properties; one which uses a base64 encoded data URI
 141+ // in place of the @embed comment to try and retain line-number integrity,
 142+ // and the other with a remapped an versioned URL and an Internet Explorer
 143+ // hack making it ignored in all browsers that support data URIs
 144+ $replacement = "{$pre}url(data:{$type};base64,{$data}){$post};";
 145+ $replacement .= "{$pre}url({$url}){$post}!ie;";
 146+ } else {
 147+ // Build a CSS property with a remapped and versioned URL,
 148+ // preserving comment for debug mode
 149+ $replacement = "{$embed}{$pre}url({$url}){$post};";
 150+ }
 151+
 152+ // Perform replacement on the source
 153+ $source = substr_replace( $source,
 154+ $replacement, $match[0][1], strlen( $match[0][0] ) );
 155+ // Move the offset to the end of the replacement in the source
 156+ $offset = $match[0][1] + strlen( $replacement );
 157+ continue;
 158+ }
 159+ // Move the offset to the end of the match, leaving it alone
 160+ $offset = $match[0][1] + strlen( $match[0][0] );
 161+ }
 162+ return $source;
 163+ }
 164+
 165+ /**
 166+ * Removes whitespace from CSS data
 167+ *
 168+ * @param $css string CSS data to minify
 169+ * @return string Minified CSS data
 170+ */
 171+ public static function minify( $css ) {
 172+ return trim(
 173+ str_replace(
 174+ array( '; ', ': ', ' {', '{ ', ', ', '} ', ';}' ),
 175+ array( ';', ':', '{', '{', ',', '}', '}' ),
 176+ preg_replace( array( '/\s+/', '/\/\*.*?\*\//s' ), array( ' ', '' ), $css )
 177+ )
 178+ );
 179+ }
 180+}
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/libs/JSMin.php
@@ -0,0 +1,283 @@
 2+<?php
 3+/**
 4+ * jsmin.php - PHP implementation of Douglas Crockford's JSMin.
 5+ *
 6+ * This is pretty much a direct port of jsmin.c to PHP with just a few
 7+ * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
 8+ * outputs to stdout, this library accepts a string as input and returns another
 9+ * string as output.
 10+ *
 11+ * PHP 5 or higher is required.
 12+ *
 13+ * Permission is hereby granted to use this version of the library under the
 14+ * same terms as jsmin.c, which has the following license:
 15+ *
 16+ * --
 17+ * Copyright (c) 2002 Douglas Crockford (www.crockford.com)
 18+ *
 19+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
 20+ * this software and associated documentation files (the "Software"), to deal in
 21+ * the Software without restriction, including without limitation the rights to
 22+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 23+ * of the Software, and to permit persons to whom the Software is furnished to do
 24+ * so, subject to the following conditions:
 25+ *
 26+ * The above copyright notice and this permission notice shall be included in all
 27+ * copies or substantial portions of the Software.
 28+ *
 29+ * The Software shall be used for Good, not Evil.
 30+ *
 31+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 32+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 33+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 34+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 35+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 36+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 37+ * SOFTWARE.
 38+ * --
 39+ *
 40+ * @file
 41+ * @author Ryan Grove <ryan@wonko.com>
 42+ * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
 43+ * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
 44+ * @license http://opensource.org/licenses/mit-license.php MIT License
 45+ * @version 1.1.1 (2008-03-02)
 46+ * @link http://github.com/rgrove/jsmin-php/
 47+ */
 48+
 49+class JSMin {
 50+ const ORD_LF = 10;
 51+ const ORD_SPACE = 32;
 52+
 53+ // Action constants
 54+ const OUTPUT = 1;
 55+ const DELETE_A = 2;
 56+ const DELETE_B = 3;
 57+
 58+ /** Current character */
 59+ protected $a = '';
 60+
 61+ /** Next character */
 62+ protected $b = '';
 63+
 64+ protected $input = '';
 65+ protected $inputIndex = 0;
 66+ protected $inputLength = 0;
 67+ protected $lookAhead = null;
 68+ protected $output = '';
 69+
 70+ // -- Public Static Methods --------------------------------------------------
 71+
 72+ public static function minify( $js ) {
 73+ $jsmin = new self( $js );
 74+ $ret = $jsmin->min();
 75+ return $ret;
 76+ }
 77+
 78+ // -- Public Instance Methods ------------------------------------------------
 79+
 80+ public function __construct( $input ) {
 81+ // Fix line endings
 82+ $this->input = str_replace( "\r\n", "\n", $input );
 83+ // Replace tabs and other control characters (except LF) with spaces
 84+ $this->input = preg_replace( '/[\x00-\x09\x0b-\x1f]/', ' ', $this->input );
 85+ $this->inputLength = strlen( $this->input );
 86+ }
 87+
 88+ // -- Protected Instance Methods ---------------------------------------------
 89+
 90+ /**
 91+ * Do something! What you do is determined by the argument:
 92+ * - self::OUTPUT Output A. Copy B to A. Get the next B.
 93+ * - self::DELETE_A Copy B to A. Get the next B. (Delete A).
 94+ * - self::DELETE_B Get the next B. (Delete B).
 95+ * action treats a string as a single character. Wow!
 96+ * action recognizes a regular expression if it is preceded by ( or , or =.
 97+ */
 98+ protected function action( $d ) {
 99+ switch( $d ) {
 100+ case self::OUTPUT:
 101+ $this->output .= $this->a;
 102+
 103+ case self::DELETE_A:
 104+ $this->a = $this->b;
 105+
 106+ if ( $this->a === "'" || $this->a === '"' ) {
 107+ $interestingChars = $this->a . "\\\n";
 108+ $this->output .= $this->a;
 109+ for ( ; ; ) {
 110+ $runLength = strcspn( $this->input, $interestingChars, $this->inputIndex );
 111+ $this->output .= substr( $this->input, $this->inputIndex, $runLength );
 112+ $this->inputIndex += $runLength;
 113+ $c = $this->get();
 114+
 115+ if ( $c === $this->b ) {
 116+ break;
 117+ }
 118+
 119+ if ( $c === "\n" || $c === null ) {
 120+ throw new JSMinException( 'Unterminated string literal.' );
 121+ }
 122+
 123+ if ( $c === '\\' ) {
 124+ $this->output .= $c . $this->get();
 125+ }
 126+ }
 127+ }
 128+
 129+ case self::DELETE_B:
 130+ $this->b = $this->next();
 131+
 132+ if ( $this->b === '/' && (
 133+ $this->a === '(' || $this->a === ',' || $this->a === '=' ||
 134+ $this->a === ':' || $this->a === '[' || $this->a === '!' ||
 135+ $this->a === '&' || $this->a === '|' || $this->a === '?' ) ) {
 136+
 137+ $this->output .= $this->a . $this->b;
 138+
 139+ for ( ; ; ) {
 140+ $runLength = strcspn( $this->input, "/\\\n", $this->inputIndex );
 141+ $this->output .= substr( $this->input, $this->inputIndex, $runLength );
 142+ $this->inputIndex += $runLength;
 143+ $this->a = $this->get();
 144+
 145+ if ( $this->a === '/' ) {
 146+ break;
 147+ } elseif ( $this->a === '\\' ) {
 148+ $this->output .= $this->a;
 149+ $this->a = $this->get();
 150+ } elseif ( $this->a === "\n" || $this->a === null ) {
 151+ throw new JSMinException( 'Unterminated regular expression ' .
 152+ 'literal.' );
 153+ }
 154+
 155+ $this->output .= $this->a;
 156+ }
 157+
 158+ $this->b = $this->next();
 159+ }
 160+ }
 161+ }
 162+
 163+ /**
 164+ * Return the next character from the input. Watch out for lookahead. If
 165+ * the character is a control character, translate it to a space or
 166+ * linefeed.
 167+ */
 168+ protected function get() {
 169+ if ( $this->inputIndex < $this->inputLength ) {
 170+ return $this->input[$this->inputIndex++];
 171+ } else {
 172+ return null;
 173+ }
 174+ }
 175+
 176+ /**
 177+ * Return true if the character is a letter, digit, underscore,
 178+ * dollar sign, or non-ASCII character.
 179+ */
 180+ protected function isAlphaNum( $c ) {
 181+ return ord( $c ) > 126 || $c === '\\' || preg_match( '/^[\w\$]$/', $c ) === 1;
 182+ }
 183+
 184+ /**
 185+ * Copy the input to the output, deleting the characters which are
 186+ * insignificant to JavaScript. Comments will be removed. Tabs will be
 187+ * replaced with spaces. Carriage returns will be replaced with linefeeds.
 188+ * Most spaces and linefeeds will be removed.
 189+ */
 190+ protected function min() {
 191+ $this->a = "\n";
 192+ $this->action( self::DELETE_B );
 193+
 194+ while ( $this->a !== null ) {
 195+ switch ( $this->a ) {
 196+ case ' ':
 197+ if ( $this->isAlphaNum( $this->b ) ) {
 198+ $this->action( self::OUTPUT );
 199+ } else {
 200+ $this->action( self::DELETE_A );
 201+ }
 202+ break;
 203+
 204+ case "\n":
 205+ switch ( $this->b ) {
 206+ case ' ':
 207+ $this->action( self::DELETE_B );
 208+ break;
 209+
 210+ default:
 211+ $this->action( self::OUTPUT );
 212+ }
 213+ break;
 214+
 215+ default:
 216+ switch ( $this->b ) {
 217+ case ' ':
 218+ if ( $this->isAlphaNum( $this->a ) ) {
 219+ $this->action( self::OUTPUT );
 220+ break;
 221+ }
 222+
 223+ $this->action( self::DELETE_B );
 224+ break;
 225+ default:
 226+ $this->action( self::OUTPUT );
 227+ break;
 228+ }
 229+ }
 230+ }
 231+
 232+ // Remove initial line break
 233+ if ( $this->output[0] !== "\n" ) {
 234+ throw new JSMinException( 'Unexpected lack of line break.' );
 235+ }
 236+ if ( $this->output === "\n" ) {
 237+ return '';
 238+ } else {
 239+ return substr( $this->output, 1 );
 240+ }
 241+ }
 242+
 243+ /**
 244+ * Get the next character, excluding comments.
 245+ */
 246+ protected function next() {
 247+ if ( $this->inputIndex >= $this->inputLength ) {
 248+ return null;
 249+ }
 250+ $c = $this->input[$this->inputIndex++];
 251+
 252+ if ( $this->inputIndex >= $this->inputLength ) {
 253+ return $c;
 254+ }
 255+
 256+ if ( $c === '/' ) {
 257+ switch( $this->input[$this->inputIndex] ) {
 258+ case '/':
 259+ $this->inputIndex += strcspn( $this->input, "\n", $this->inputIndex ) + 1;
 260+ return "\n";
 261+ case '*':
 262+ $endPos = strpos( $this->input, '*/', $this->inputIndex + 1 );
 263+ if ( $endPos === false ) {
 264+ throw new JSMinException( 'Unterminated comment.' );
 265+ }
 266+ $numLines = substr_count( $this->input, "\n", $this->inputIndex,
 267+ $endPos - $this->inputIndex );
 268+ $this->inputIndex = $endPos + 2;
 269+ if ( $numLines ) {
 270+ return str_repeat( "\n", $numLines );
 271+ } else {
 272+ return ' ';
 273+ }
 274+ default:
 275+ return $c;
 276+ }
 277+ }
 278+
 279+ return $c;
 280+ }
 281+}
 282+
 283+// -- Exceptions ---------------------------------------------------------------
 284+class JSMinException extends Exception {}
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/libs/README
@@ -0,0 +1,4 @@
 2+The classes in this directory ./includes/libs are considered standalone
 3+from the remainder of the MediaWiki/ mwEmbed codebase. They do not call on any other
 4+portions of MediaWiki code, and can be used in other projects without
 5+dependency issues.
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/DefaultSettings.php
@@ -14,15 +14,13 @@
1515 * Guess at URL to resource loader load.php
1616 */
1717 $wgResourceLoaderUrl = ( isset( $_SERVER['HTTPS'] ) )? 'https' : 'http';
18 -$wgResourceLoaderUrl.= 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PATH_INFO'] . '/load.php';
19 -
 18+$wgResourceLoaderUrl.= '://' . $_SERVER['SERVER_NAME'] . dirname( $_SERVER['SCRIPT_NAME'] ) . '/load.php';
 19+$wgLoadScript = $wgResourceLoaderUrl;
2020 // The list of enabled modules
2121 $wgMwEmbedEnabledModules = array();
22 -
2322 // By default we enable every module in the "modules" folder
24 -// We include /modules/{moduleName}/{moduleName}.php after localsettings.php to give a chance
 23+// Modules are registered after localsettings.php to give a chance
2524 // for local configuration to override the set of enabled modules
26 -
2725 $d = dir( realpath( dirname( __FILE__ ) ) . '/../modules' );
2826 while (false !== ($entry = $d->read())) {
2927 if( substr( $entry, 0, 1 ) != '.' ){
@@ -30,6 +28,22 @@
3129 }
3230 }
3331
 32+/**
 33+ * Client-side resource modules. Extensions should add their module definitions
 34+ * here. The mwEmbed
 35+ *
 36+ * Example:
 37+ * $wgResourceModules['ext.myExtension'] = array(
 38+ * 'scripts' => 'myExtension.js',
 39+ * 'styles' => 'myExtension.css',
 40+ * 'dependencies' => array( 'jquery.cookie', 'jquery.tabIndex' ),
 41+ * 'localBasePath' => dirname( __FILE__ ),
 42+ * 'remoteExtPath' => 'MyExtension',
 43+ * );
 44+ */
 45+$wgResourceModules = array();
 46+
 47+
3448 /*********************************************************
3549 * Default Kaltura Configuration:
3650 * TODO move kaltura configuration to KalturaSupport module ( part of ResourceLoader update )
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedMediaWikiStubs.php
@@ -4,5 +4,270 @@
55 * ( it stubs mediaWiki function and class calls where needed )
66 */
77
 8+/**
 9+ * global functions
 10+ */
 11+function wfProfileIn($na){
 12+ return ;
 13+}
 14+function wfProfileOut($na){
 15+ return ;
 16+}
 17+function wfDebug( $text, $logonly = false ) {
 18+ return ;
 19+}
820
 21+// MWException stub:
 22+class MWException extends Exception {
 23+}
 24+
 25+// Stub xml functions:
 26+class Xml {
 27+ /**
 28+ * Encode a variable of unknown type to JavaScript.
 29+ * Arrays are converted to JS arrays, objects are converted to JS associative
 30+ * arrays (objects). So cast your PHP associative arrays to objects before
 31+ * passing them to here.
 32+ */
 33+ public static function encodeJsVar( $value ) {
 34+ if ( is_bool( $value ) ) {
 35+ $s = $value ? 'true' : 'false';
 36+ } elseif ( is_null( $value ) ) {
 37+ $s = 'null';
 38+ } elseif ( is_int( $value ) ) {
 39+ $s = $value;
 40+ } elseif ( is_array( $value ) && // Make sure it's not associative.
 41+ array_keys($value) === range( 0, count($value) - 1 ) ||
 42+ count($value) == 0
 43+ ) {
 44+ $s = '[';
 45+ foreach ( $value as $elt ) {
 46+ if ( $s != '[' ) {
 47+ $s .= ', ';
 48+ }
 49+ $s .= self::encodeJsVar( $elt );
 50+ }
 51+ $s .= ']';
 52+ } elseif ( $value instanceof XmlJsCode ) {
 53+ $s = $value->value;
 54+ } elseif ( is_object( $value ) || is_array( $value ) ) {
 55+ // Objects and associative arrays
 56+ $s = '{';
 57+ foreach ( (array)$value as $name => $elt ) {
 58+ if ( $s != '{' ) {
 59+ $s .= ', ';
 60+ }
 61+ $s .= '"' . self::escapeJsString( $name ) . '": ' .
 62+ self::encodeJsVar( $elt );
 63+ }
 64+ $s .= '}';
 65+ } else {
 66+ $s = '"' . self::escapeJsString( $value ) . '"';
 67+ }
 68+ return $s;
 69+ }
 70+ /**
 71+ * Create a call to a JavaScript function. The supplied arguments will be
 72+ * encoded using Xml::encodeJsVar().
 73+ *
 74+ * @param $name String The name of the function to call, or a JavaScript expression
 75+ * which evaluates to a function object which is called.
 76+ * @param $args Array of arguments to pass to the function.
 77+ * @since 1.17
 78+ */
 79+ public static function encodeJsCall( $name, $args ) {
 80+ $s = "$name(";
 81+ $first = true;
 82+ foreach ( $args as $arg ) {
 83+ if ( $first ) {
 84+ $first = false;
 85+ } else {
 86+ $s .= ', ';
 87+ }
 88+ $s .= Xml::encodeJsVar( $arg );
 89+ }
 90+ $s .= ");\n";
 91+ return $s;
 92+ }
 93+/**
 94+ * Returns an escaped string suitable for inclusion in a string literal
 95+ * for JavaScript source code.
 96+ * Illegal control characters are assumed not to be present.
 97+ *
 98+ * @param $string String to escape
 99+ * @return String
 100+ */
 101+ public static function escapeJsString( $string ) {
 102+ // See ECMA 262 section 7.8.4 for string literal format
 103+ $pairs = array(
 104+ "\\" => "\\\\",
 105+ "\"" => "\\\"",
 106+ '\'' => '\\\'',
 107+ "\n" => "\\n",
 108+ "\r" => "\\r",
 109+
 110+ # To avoid closing the element or CDATA section
 111+ "<" => "\\x3c",
 112+ ">" => "\\x3e",
 113+
 114+ # To avoid any complaints about bad entity refs
 115+ "&" => "\\x26",
 116+
 117+ # Work around https://bugzilla.mozilla.org/show_bug.cgi?id=274152
 118+ # Encode certain Unicode formatting chars so affected
 119+ # versions of Gecko don't misinterpret our strings;
 120+ # this is a common problem with Farsi text.
 121+ "\xe2\x80\x8c" => "\\u200c", // ZERO WIDTH NON-JOINER
 122+ "\xe2\x80\x8d" => "\\u200d", // ZERO WIDTH JOINER
 123+ );
 124+ return strtr( $string, $pairs );
 125+ }
 126+}
 127+/**
 128+ * A wrapper class which causes Xml::encodeJsVar() and Xml::encodeJsCall() to
 129+ * interpret a given string as being a JavaScript expression, instead of string
 130+ * data.
 131+ *
 132+ * Example:
 133+ *
 134+ * Xml::encodeJsVar( new XmlJsCode( 'a + b' ) );
 135+ *
 136+ * Returns "a + b".
 137+ * @since 1.17
 138+ */
 139+class XmlJsCode {
 140+ public $value;
 141+
 142+ function __construct( $value ) {
 143+ $this->value = $value;
 144+ }
 145+}
 146+
 147+// stub html functions
 148+class Html {
 149+ /**
 150+ * Output a <script> tag linking to the given URL, e.g.,
 151+ * <script src=foo.js></script>.
 152+ *
 153+ * @param $url string
 154+ * @return string Raw HTML
 155+ */
 156+ public static function linkedScript( $url ) {
 157+ return '<script src="' . htmlspecialchars( $url) . '" type="text/javascript"></script>';
 158+ }
 159+}
 160+
 161+
 162+// Stub MessageBlobStore ( don't use db, just directly grab messages from php )
 163+class MessageBlobStore {
 164+ /**
 165+ * Get the message blobs for a set of modules
 166+ *
 167+ * @param $resourceLoader ResourceLoader object
 168+ * @param $modules array Array of module objects keyed by module name
 169+ * @param $lang string Language code
 170+ * @return array An array mapping module names to message blobs
 171+ */
 172+ public static function get( ResourceLoader $resourceLoader, $modules, $lang ) {
 173+ $blobs = array();
 174+ foreach( $modules as $name => $module ){
 175+ $messages = array();
 176+ foreach ( $module->getMessages() as $key ) {
 177+ $messages[$key] = wfMsgExt( $key, array( 'language' => $lang ) );
 178+ }
 179+ if( count( $messages ) ){
 180+ $blobs[ $name ] = FormatJson::encode( (object)$messages );
 181+ }
 182+ }
 183+ return $blobs;
 184+ }
 185+}
 186+
 187+// Stub WebRequest
 188+// Just serving static files, don't have a concept of wiki titles etc.)
 189+class WebRequest {
 190+ protected $data, $headers = array();
 191+ public function __construct() {
 192+ // POST overrides GET data
 193+ // We don't use $_REQUEST here to avoid interference from cookies...
 194+ $this->data = $_POST + $_GET;
 195+ }
 196+ /**
 197+ * Fetch a scalar from the input or return $default if it's not set.
 198+ *
 199+ * @param $name String
 200+ * @param $default String: optional default (or NULL)
 201+ * @return String
 202+ */
 203+ public function getVal( $name, $default = null ) {
 204+ return ( isset( $this->data[ $name ] ) )? (string)$this->data[ $name ] : $default;
 205+ }
 206+
 207+ /**
 208+ * Fetch a boolean value from the input or return $default if not set.
 209+ * Unlike getBool, the string "false" will result in boolean false, which is
 210+ * useful when interpreting information sent from JavaScript.
 211+ *
 212+ * @param $name String
 213+ * @param $default Boolean
 214+ * @return Boolean
 215+ */
 216+ public function getFuzzyBool( $name, $default = false ) {
 217+ return ( isset( $this->data[ $name ] ) )? ( $this->data[ $name ] ) : $default;
 218+ }
 219+
 220+ /**
 221+ * Get a request header, or false if it isn't set
 222+ * @param $name String: case-insensitive header name
 223+ */
 224+ public function getHeader( $name ) {
 225+ $name = strtoupper( $name );
 226+ if ( !$this->headers ) {
 227+ foreach ( apache_request_headers() as $tempName => $tempValue ) {
 228+ $this->headers[ strtoupper( $tempName ) ] = $tempValue;
 229+ }
 230+ }
 231+ if ( isset( $this->headers[$name] ) ) {
 232+ return $this->headers[$name];
 233+ } else {
 234+ return false;
 235+ }
 236+ }
 237+}
 238+/**
 239+ * This function takes two arrays as input, and returns a CGI-style string, e.g.
 240+ * "days=7&limit=100". Options in the first array override options in the second.
 241+ * Options set to "" will not be output.
 242+ */
 243+function wfArrayToCGI( $array1, $array2 = null ) {
 244+ if ( !is_null( $array2 ) ) {
 245+ $array1 = $array1 + $array2;
 246+ }
 247+
 248+ $cgi = '';
 249+ foreach ( $array1 as $key => $value ) {
 250+ if ( $value !== '' ) {
 251+ if ( $cgi != '' ) {
 252+ $cgi .= '&';
 253+ }
 254+ if ( is_array( $value ) ) {
 255+ $firstTime = true;
 256+ foreach ( $value as $v ) {
 257+ $cgi .= ( $firstTime ? '' : '&') .
 258+ urlencode( $key . '[]' ) . '=' .
 259+ urlencode( $v );
 260+ $firstTime = false;
 261+ }
 262+ } else {
 263+ if ( is_object( $value ) ) {
 264+ $value = $value->__toString();
 265+ }
 266+ $cgi .= urlencode( $key ) . '=' .
 267+ urlencode( $value );
 268+ }
 269+ }
 270+ }
 271+ return $cgi;
 272+}
 273+
9274 ?>
\ No newline at end of file
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedResourceLoaderFileModule.php
@@ -0,0 +1,65 @@
 2+<?php
 3+
 4+// Replaces the ResourceLoaderFileModule by stubbing out stuff that does not work in stand
 5+// alone mode
 6+
 7+class MwEmbedResourceLoaderFileModule extends ResourceLoaderFileModule {
 8+ /**
 9+ * Get the files this module depends on indirectly for a given skin.
 10+ * Currently these are only image files referenced by the module's CSS.
 11+ *
 12+ * @param $skin String: Skin name
 13+ * @return Array: List of files
 14+ */
 15+ public function getFileDependencies( $skin ) {
 16+ // Try in-object cache first
 17+ if ( isset( $this->fileDeps[$skin] ) ) {
 18+ return $this->fileDeps[$skin];
 19+ }
 20+ // Use file cache instead of db ( for mwEmbed minimal config and minimal framework code )
 21+ $deps = mweGetFromFileCache( implode(
 22+ array( 'module_deps', 'md_deps', 'md_module_' . $this->getName(), 'md_skin_' . $skin )
 23+ ) );
 24+ /*
 25+ $dbr = wfGetDB( DB_SLAVE );
 26+ $deps = $dbr->selectField( 'module_deps', 'md_deps', array(
 27+ 'md_module' => $this->getName(),
 28+ 'md_skin' => $skin,
 29+ ), __METHOD__
 30+ );
 31+ */
 32+ if ( !is_null( $deps ) ) {
 33+ $this->fileDeps[$skin] = (array) FormatJson::decode( $deps, true );
 34+ } else {
 35+ $this->fileDeps[$skin] = array();
 36+ }
 37+ return $this->fileDeps[$skin];
 38+ }
 39+ /**
 40+ * Get the last modification timestamp of the message blob for this
 41+ * module in a given language.
 42+ * @param $lang String: Language code
 43+ * @return Integer: UNIX timestamp, or 0 if no blob found
 44+ */
 45+ public function getMsgBlobMtime( $lang ) {
 46+ if ( !isset( $this->msgBlobMtime[$lang] ) ) {
 47+ if ( !count( $this->getMessages() ) )
 48+ return 0;
 49+ // Use file cache instead of db ( for mwEmbed minimal config and minimal framework code )
 50+ $msgBlobMtime = mweGetFromFileCache( implode(
 51+ array( 'msg_resource', 'mr_timestamp', 'mr_resource_' . $this->getName(), 'mr_lang_' . $lang )
 52+ ) );
 53+ /*$dbr = wfGetDB( DB_SLAVE );
 54+ $msgBlobMtime = $dbr->selectField( 'msg_resource', 'mr_timestamp', array(
 55+ 'mr_resource' => $this->getName(),
 56+ 'mr_lang' => $lang
 57+ ), __METHOD__
 58+ );
 59+ */
 60+ $this->msgBlobMtime[$lang] = $msgBlobMtime ? wfTimestamp( TS_UNIX, $msgBlobMtime ) : 0;
 61+ }
 62+ return $this->msgBlobMtime[$lang];
 63+ }
 64+}
 65+
 66+?>
\ No newline at end of file
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedResourceLoaderStartUpModule.php
@@ -0,0 +1,17 @@
 2+<?php
 3+
 4+// Replaces the ResourceLoaderFileModule by stubbing out stuff that does not work in stand
 5+// alone mode
 6+
 7+class MwEmbedResourceLoaderStartUpModule extends ResourceLoaderStartUpModule {
 8+
 9+ protected function getConfig( $context ) {
 10+ // @@todo set all the configuration variables
 11+ $vars = array();
 12+ wfRunHooks( 'ResourceLoaderGetConfigVars', array( &$vars ) );
 13+
 14+ return $vars;
 15+ }
 16+}
 17+
 18+?>
\ No newline at end of file
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/resourceloader/ResourceLoader.php
@@ -62,7 +62,7 @@
6363 // Get file dependency information
6464 $res = $dbr->select( 'module_deps', array( 'md_module', 'md_deps' ), array(
6565 'md_module' => $modules,
66 - 'md_skin' => $context->getSkin()
 66+ 'md_skin' => $skin,
6767 ), __METHOD__
6868 );
6969
@@ -196,7 +196,6 @@
197197 */
198198 public function register( $name, $info = null ) {
199199 wfProfileIn( __METHOD__ );
200 -
201200 // Allow multiple modules to be registered in one call
202201 if ( is_array( $name ) ) {
203202 foreach ( $name as $key => $value ) {
@@ -213,6 +212,14 @@
214213 'Another module has already been registered as ' . $name
215214 );
216215 }
 216+
 217+ // Check empty names register calls
 218+ if ( trim( $name ) == '' ) {
 219+ // Trying to register module with empty name
 220+ throw new MWException(
 221+ 'ResourceLoader empty module name registration error'
 222+ );
 223+ }
217224
218225 // Attach module
219226 if ( is_object( $info ) ) {
@@ -249,7 +256,7 @@
250257 * @param $name String: Module name
251258 * @return Mixed: ResourceLoaderModule if module has been registered, null otherwise
252259 */
253 - public function getModule( $name ) {
 260+ public function getModule( $name ) {
254261 if ( !isset( $this->modules[$name] ) ) {
255262 if ( !isset( $this->moduleInfos[$name] ) ) {
256263 // No such module
@@ -265,7 +272,7 @@
266273 $class = 'ResourceLoaderFileModule';
267274 } else {
268275 $class = $info['class'];
269 - }
 276+ }
270277 $object = new $class( $info );
271278 }
272279 $object->setName( $name );
@@ -326,7 +333,6 @@
327334 // Add exception to the output as a comment
328335 $exceptions .= "/*\n{$e->__toString()}\n*/\n";
329336 }
330 -
331337 wfProfileIn( __METHOD__.'-getModifiedTime' );
332338
333339 // To send Last-Modified and support If-Modified-Since, we need to detect
@@ -345,7 +351,6 @@
346352 $exceptions .= "/*\n{$e->__toString()}\n*/\n";
347353 }
348354 }
349 -
350355 wfProfileOut( __METHOD__.'-getModifiedTime' );
351356
352357 if ( $context->getOnly() === 'styles' ) {
@@ -391,10 +396,9 @@
392397 return;
393398 }
394399 }
395 -
 400+
396401 // Generate a response
397402 $response = $this->makeModuleResponse( $context, $modules, $missing );
398 -
399403 // Prepend comments indicating exceptions
400404 $response = $exceptions . $response;
401405
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/resourceloader/ResourceLoaderFileModule.php
@@ -318,10 +318,12 @@
319319 * @see ResourceLoaderModule::getFileDependencies
320320 */
321321 public function getModifiedTime( ResourceLoaderContext $context ) {
 322+
322323 if ( isset( $this->modifiedTime[$context->getHash()] ) ) {
323324 return $this->modifiedTime[$context->getHash()];
324325 }
325326 wfProfileIn( __METHOD__ );
 327+
326328
327329 $files = array();
328330
@@ -338,7 +340,6 @@
339341 foreach ( $skinFiles as $styleFiles ) {
340342 $files = array_merge( $files, $styleFiles );
341343 }
342 -
343344 // Final merge, this should result in a master list of dependent files
344345 $files = array_merge(
345346 $files,
@@ -348,10 +349,10 @@
349350 self::tryForKey( $this->skinScripts, $context->getSkin(), 'default' ),
350351 $this->loaderScripts
351352 );
 353+
352354 $files = array_map( array( $this, 'getLocalPath' ), $files );
353355 // File deps need to be treated separately because they're already prefixed
354356 $files = array_merge( $files, $this->getFileDependencies( $context->getSkin() ) );
355 -
356357 // If a module is nothing but a list of dependencies, we need to avoid
357358 // giving max() an empty array
358359 if ( count( $files ) === 0 ) {
@@ -486,7 +487,7 @@
487488 * @return String: CSS data in script file
488489 */
489490 protected function readStyleFile( $path, $flip ) {
490 - $localPath = $this->getLocalPath( $path );
 491+ $localPath = $this->getLocalPath( $path );
491492 $style = file_get_contents( $localPath );
492493 if ( $style === false ) {
493494 throw new MWException( __METHOD__.": style file not found: \"$localPath\"" );
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/resourceloader/ResourceLoaderModule.php
@@ -147,6 +147,7 @@
148148 * @return Array: List of files
149149 */
150150 public function getFileDependencies( $skin ) {
 151+ print_r( debug_backtrace() );
151152 // Try in-object cache first
152153 if ( isset( $this->fileDeps[$skin] ) ) {
153154 return $this->fileDeps[$skin];
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/resourceloader/ResourceLoaderStartUpModule.php
@@ -146,7 +146,6 @@
147147
148148 public function getScript( ResourceLoaderContext $context ) {
149149 global $IP, $wgLoadScript;
150 -
151150 $out = file_get_contents( "$IP/resources/startup.js" );
152151 if ( $context->getOnly() === 'scripts' ) {
153152 // Build load query for jquery and mediawiki modules
@@ -167,19 +166,18 @@
168167 // Startup function
169168 $configuration = $this->getConfig( $context );
170169 $registrations = self::getModuleRegistrations( $context );
171 - $out .= "var startUp = function() {\n" .
 170+ $out .= "var mwStartUp = function() {\n" .
172171 "\t$registrations\n" .
173172 "\t" . Xml::encodeJsCall( 'mediaWiki.config.set', array( $configuration ) ) .
174173 "};\n";
175174
176175 // Conditional script injection
177176 $scriptTag = Html::linkedScript( $wgLoadScript . '?' . wfArrayToCGI( $query ) );
178 - $out .= "if ( isCompatible() ) {\n" .
 177+ $out .= "if ( mwIsCompatible() ) {\n" .
179178 "\t" . Xml::encodeJsCall( 'document.write', array( $scriptTag ) ) .
180179 "}\n" .
181180 "delete isCompatible;";
182 - }
183 -
 181+ }
184182 return $out;
185183 }
186184
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MediaWikiSupport/mwEmbed.i18n.php
@@ -0,0 +1,738 @@
 2+<?php
 3+/**
 4+ * Localization file for mwEmbed.js
 5+ */
 6+
 7+$messages = array();
 8+
 9+$messages['en'] = array(
 10+ 'mwe-loading_txt' => 'Loading ...',
 11+ 'mwe-size-gigabytes' => '$1 GB',
 12+ 'mwe-size-megabytes' => '$1 MB',
 13+ 'mwe-size-kilobytes' => '$1 K',
 14+ 'mwe-size-bytes' => '$1 B',
 15+ 'mwe-error_load_lib' => 'Error: JavaScript $1 was not retrievable or does not define $2',
 16+ 'mwe-apiproxy-setup' => 'Setting up API proxy',
 17+ 'mwe-load-drag-item' => 'Loading dragged item',
 18+ 'mwe-ok' => 'OK',
 19+ 'mwe-cancel' => 'Cancel',
 20+ 'mwe-enable-gadget' => 'Enable multimedia beta (mwEmbed) for all pages',
 21+ 'mwe-enable-gadget-done' => 'Multimedia beta gadget has been enabled',
 22+ 'mwe-must-login-gadget' => 'To enable gadget you must <a target="_new" href="$1">login</a>',
 23+ 'mwe-test-plural' => 'I ran {{PLURAL:$1|$1 test|$1 tests}}',
 24+);
 25+
 26+/** Message documentation (Message documentation)
 27+ * @author EugeneZelenko
 28+ * @author Fryed-peach
 29+ * @author Nike
 30+ */
 31+$messages['qqq'] = array(
 32+ 'mwe-loading_txt' => '{{Identical|Loading}}',
 33+ 'mwe-size-gigabytes' => 'Size (of a file, typically) in gibibytes (1 gibibyte = 1024×1024×1024 bytes).',
 34+ 'mwe-error_load_lib' => 'Parameters:
 35+* $1 Corresponds to the JavaScript file that was not retrievable or does not define its class name.
 36+* $2 Is the class name that was associated with the JavaScript file that was not found or could not be retrieved.',
 37+ 'mwe-ok' => '{{Identical|OK}}',
 38+ 'mwe-cancel' => '{{Identical|Cancel}}',
 39+);
 40+
 41+/** Afrikaans (Afrikaans)
 42+ * @author Naudefj
 43+ */
 44+$messages['af'] = array(
 45+ 'mwe-loading_txt' => 'laai ...',
 46+ 'mwe-error_load_lib' => 'Fout: JavaScript $1 kon nie gevind word of definieer nie $2 nie',
 47+ 'mwe-ok' => 'OK',
 48+ 'mwe-cancel' => 'Kanselleer',
 49+);
 50+
 51+/** Gheg Albanian (Gegë)
 52+ * @author Mdupont
 53+ */
 54+$messages['aln'] = array(
 55+ 'mwe-loading_txt' => 'Loading ...',
 56+ 'mwe-error_load_lib' => 'Gabim: $1 JavaScript nuk ishte shikohen ose nuk define $2',
 57+ 'mwe-apiproxy-setup' => 'Ngritja proxy API',
 58+ 'mwe-load-drag-item' => 'Loading zvarritur artikull',
 59+ 'mwe-ok' => 'Në rregull',
 60+ 'mwe-cancel' => 'Anuloj',
 61+ 'mwe-enable-gadget' => 'Aktivizo multimedial beta (mwEmbed) për të gjitha faqet',
 62+ 'mwe-enable-gadget-done' => 'Multimedia beta vegël ka qenë i aktivizuar',
 63+);
 64+
 65+/** Aragonese (Aragonés)
 66+ * @author Juanpabl
 67+ */
 68+$messages['an'] = array(
 69+ 'mwe-cancel' => 'Cancelar',
 70+);
 71+
 72+/** Arabic (العربية)
 73+ * @author OsamaK
 74+ */
 75+$messages['ar'] = array(
 76+ 'mwe-loading_txt' => 'يحمل...',
 77+ 'mwe-cancel' => 'ألغِ',
 78+);
 79+
 80+/** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца))
 81+ * @author EugeneZelenko
 82+ * @author Jim-by
 83+ */
 84+$messages['be-tarask'] = array(
 85+ 'mwe-loading_txt' => 'загрузка …',
 86+ 'mwe-error_load_lib' => 'Памылка: JavaScript $1 не даступны альбо не вызначае $2',
 87+ 'mwe-apiproxy-setup' => 'Устаноўка API-проксі',
 88+ 'mwe-load-drag-item' => 'Загрузка перанесенага элемэнту',
 89+ 'mwe-ok' => 'Добра',
 90+ 'mwe-cancel' => 'Адмяніць',
 91+ 'mwe-enable-gadget' => 'Уключыць бэта-мультымэдыя (mwEmbed) для ўсіх старонак',
 92+ 'mwe-enable-gadget-done' => 'Дапаўненьне бэта-мультымэтыя ўключанае',
 93+ 'mwe-must-login-gadget' => 'Для ўключэньня дапаўненьня Вам неабходна <a target="_new" href="$1">ўвайсьці ў сыстэму</a>',
 94+ 'mwe-test-plural' => 'Я прайшоў $1 {{PLURAL:$1|тэст|тэсты|тэстаў}}',
 95+);
 96+
 97+/** Breton (Brezhoneg)
 98+ * @author Fohanno
 99+ * @author Fulup
 100+ * @author Y-M D
 101+ */
 102+$messages['br'] = array(
 103+ 'mwe-loading_txt' => 'o kargañ...',
 104+ 'mwe-error_load_lib' => "Fazi : n'eo ket bet kavet JavaScript $1 pe n'eo ket termenet gant $2",
 105+ 'mwe-apiproxy-setup' => 'Kefluniadur ar proksi API',
 106+ 'mwe-load-drag-item' => 'O kargañ an elfenn digargañ',
 107+ 'mwe-ok' => 'Mat eo',
 108+ 'mwe-cancel' => 'Nullañ',
 109+ 'mwe-enable-gadget' => 'Gweredekaat liesvedia beta (mwEmbed) war an holl bajennoù',
 110+ 'mwe-enable-gadget-done' => 'Gweredekaet eo bet ar gadjet liesvedia beta',
 111+ 'mwe-must-login-gadget' => 'Evit gweredekaat ar gadjet e rankit <a target="_new" href="$1">kevreañ</a>',
 112+ 'mwe-test-plural' => 'Sevenet em eus $1 amprouadenn{{PLURAL:$1||}}',
 113+);
 114+
 115+/** Bosnian (Bosanski)
 116+ * @author CERminator
 117+ */
 118+$messages['bs'] = array(
 119+ 'mwe-loading_txt' => 'učitavam ...',
 120+ 'mwe-apiproxy-setup' => 'Postavljanje API proksija',
 121+ 'mwe-ok' => 'U redu',
 122+ 'mwe-cancel' => 'Odustani',
 123+);
 124+
 125+/** Czech (Česky)
 126+ * @author Mormegil
 127+ */
 128+$messages['cs'] = array(
 129+ 'mwe-loading_txt' => 'Načítá se …',
 130+ 'mwe-cancel' => 'Storno',
 131+);
 132+
 133+/** Welsh (Cymraeg) */
 134+$messages['cy'] = array(
 135+ 'mwe-loading_txt' => "wrthi'n llwytho ...",
 136+);
 137+
 138+/** German (Deutsch)
 139+ * @author Kghbln
 140+ * @author Metalhead64
 141+ */
 142+$messages['de'] = array(
 143+ 'mwe-loading_txt' => 'lade …',
 144+ 'mwe-error_load_lib' => 'Fehler: JavaScript $1 war nicht abrufbar oder lässt $2 nicht zu',
 145+ 'mwe-apiproxy-setup' => 'API-Proxy-Konfiguration',
 146+ 'mwe-load-drag-item' => 'Lade eingebettetes Element',
 147+ 'mwe-ok' => 'OK',
 148+ 'mwe-cancel' => 'Abbrechen',
 149+ 'mwe-enable-gadget' => 'Aktiviere die Beta-Version des Multimedia-Helferleins (mwEmbed) für alle Seiten',
 150+ 'mwe-enable-gadget-done' => 'Beta-Version des Multimedia-Helferleins wurde aktiviert',
 151+ 'mwe-must-login-gadget' => 'Um das Helferlein aktivieren zu können, musst du dich <a target="_new" href="$1">anmelden</a>',
 152+ 'mwe-test-plural' => '{{PLURAL:$1|$1 Test|$1 Tests}} durchlaufen',
 153+);
 154+
 155+/** Zazaki (Zazaki)
 156+ * @author Aspar
 157+ */
 158+$messages['diq'] = array(
 159+ 'mwe-loading_txt' => 'bar beno...',
 160+ 'mwe-error_load_lib' => 'xeta: $1 JavaScript re nêresiyeno ya zi pê $2yi şınasnaye niyo.',
 161+ 'mwe-apiproxy-setup' => 'proxyê APIyi eyar beno',
 162+ 'mwe-load-drag-item' => 'unsur bar beno',
 163+ 'mwe-ok' => 'temam',
 164+ 'mwe-cancel' => 'iptal',
 165+);
 166+
 167+/** Lower Sorbian (Dolnoserbski)
 168+ * @author Michawiki
 169+ */
 170+$messages['dsb'] = array(
 171+ 'mwe-loading_txt' => 'zacytujo se ...',
 172+ 'mwe-error_load_lib' => 'Zmólka: JavaScript $1 njejo wótwołujobny był abo njedefiněrujo $2',
 173+ 'mwe-apiproxy-setup' => 'Proksy API zarědowaś',
 174+ 'mwe-load-drag-item' => 'Wlecony zapisk se zacytujo',
 175+ 'mwe-ok' => 'W pórědku',
 176+ 'mwe-cancel' => 'Pśetergnuś',
 177+ 'mwe-enable-gadget' => 'Multimedia beta (mwEmbed) za wšykne boki zmóžniś',
 178+ 'mwe-enable-gadget-done' => 'Pśisłušk Multimedia beta jo se zmóžnił',
 179+ 'mwe-must-login-gadget' => 'Aby pśisłušk zmóžnił, musyš se <a target="_new" href="$1">pśizjawiś</a>',
 180+ 'mwe-test-plural' => 'Som {{PLURAL:$1|$1 test|$1 testa|$1 testy|$1 testow}} pśewjadł',
 181+);
 182+
 183+/** Greek (Ελληνικά)
 184+ * @author Crazymadlover
 185+ */
 186+$messages['el'] = array(
 187+ 'mwe-loading_txt' => 'φόρτωση ...',
 188+ 'mwe-cancel' => 'Ακύρωση',
 189+);
 190+
 191+/** Esperanto (Esperanto)
 192+ * @author Yekrats
 193+ */
 194+$messages['eo'] = array(
 195+ 'mwe-loading_txt' => 'ŝarĝante ...',
 196+ 'mwe-cancel' => 'Nuligi',
 197+);
 198+
 199+/** Spanish (Español)
 200+ * @author Translationista
 201+ */
 202+$messages['es'] = array(
 203+ 'mwe-loading_txt' => 'cargando ...',
 204+ 'mwe-error_load_lib' => 'Error: JavaScript $1 no ha podido ser recuperado o no define $2',
 205+ 'mwe-apiproxy-setup' => 'Configurando proxi de la API',
 206+ 'mwe-load-drag-item' => 'Cargando el objeto arrastrado',
 207+ 'mwe-ok' => 'OK',
 208+ 'mwe-cancel' => 'Cancelar',
 209+ 'mwe-enable-gadget' => 'Habilitar multimedia beta (mwEmbed) en todas las páginas',
 210+ 'mwe-enable-gadget-done' => 'Se ha habilitado el gadget multimedia beta',
 211+ 'mwe-must-login-gadget' => 'Para habilitar el gadget debes <a target="_new" href="$1">ingresar</a>',
 212+ 'mwe-test-plural' => 'Realicé {{PLURAL:$1|$1 prueba|$1 pruebas}}',
 213+);
 214+
 215+/** Basque (Euskara)
 216+ * @author An13sa
 217+ */
 218+$messages['eu'] = array(
 219+ 'mwe-loading_txt' => 'Kargatzen ...',
 220+ 'mwe-ok' => 'Ados',
 221+ 'mwe-cancel' => 'Ezeztatu',
 222+);
 223+
 224+/** Finnish (Suomi)
 225+ * @author Crt
 226+ * @author Str4nd
 227+ */
 228+$messages['fi'] = array(
 229+ 'mwe-loading_txt' => 'Ladataan...',
 230+ 'mwe-error_load_lib' => 'Virhe: JavaScript $1 ei ollut haettavissa tai se ei määrittele luokkaa $2',
 231+ 'mwe-apiproxy-setup' => 'Pystytetään API-välityspalvelinta',
 232+ 'mwe-ok' => 'OK',
 233+ 'mwe-cancel' => 'Peruuta',
 234+ 'mwe-must-login-gadget' => 'Sinun tulee <a target="_new" href="$1">kirjautua sisään</a>, jotta voisit käyttää pienoisohjelmaa',
 235+ 'mwe-test-plural' => 'Ajoin {{PLURAL:$1|$1 testin|$1 testiä}}',
 236+);
 237+
 238+/** French (Français)
 239+ * @author IAlex
 240+ * @author Jean-Frédéric
 241+ * @author PieRRoMaN
 242+ */
 243+$messages['fr'] = array(
 244+ 'mwe-loading_txt' => 'chargement ...',
 245+ 'mwe-error_load_lib' => "Erreur : JavaScript $1 n'a pas pu être trouvé ou ne définit pas $2",
 246+ 'mwe-apiproxy-setup' => 'Configuration du proxy API',
 247+ 'mwe-load-drag-item' => 'Chargement de l’élément dépose',
 248+ 'mwe-ok' => 'OK',
 249+ 'mwe-cancel' => 'Annuler',
 250+ 'mwe-enable-gadget' => 'Activer beta multimédia (mwEmbed) sur toutes les pages',
 251+ 'mwe-enable-gadget-done' => 'Le gadget multimédia beta a été activé',
 252+ 'mwe-must-login-gadget' => 'Afin d\'activer le gadget vous devez vous <a target="_new" href="$1">connecter</a>',
 253+ 'mwe-test-plural' => "J'ai exécuté {{PLURAL:$1|$1 test|$1 tests}}",
 254+);
 255+
 256+/** Galician (Galego)
 257+ * @author Toliño
 258+ */
 259+$messages['gl'] = array(
 260+ 'mwe-loading_txt' => 'cargando...',
 261+ 'mwe-error_load_lib' => 'Erro: o JavaScript $1 non se puido atopar ou non definía $2',
 262+ 'mwe-apiproxy-setup' => 'Configurando o proxy API',
 263+ 'mwe-load-drag-item' => 'Cargando o elemento arrastrado',
 264+ 'mwe-ok' => 'De acordo',
 265+ 'mwe-cancel' => 'Cancelar',
 266+ 'mwe-enable-gadget' => 'Activar a beta multimedia (mwEmbed) en todas as páxinas',
 267+ 'mwe-enable-gadget-done' => 'Activouse o trebello beta multimedia',
 268+ 'mwe-must-login-gadget' => 'Para activar o trebello ten que <a target="_new" href="$1">acceder ao sistema</a>',
 269+ 'mwe-test-plural' => '{{PLURAL:$1|Fíxose unha proba|Fixéronse $1 probas}}',
 270+);
 271+
 272+/** Swiss German (Alemannisch)
 273+ * @author Als-Holder
 274+ */
 275+$messages['gsw'] = array(
 276+ 'mwe-loading_txt' => 'Am Lade ...',
 277+ 'mwe-error_load_lib' => 'Fähler: s JavaScript $1 het nit chenne glade wäre oder s losst $2 nit zue',
 278+ 'mwe-apiproxy-setup' => 'API-Proxy-Konfiguration',
 279+ 'mwe-load-drag-item' => 'Am Lade vu mitgschleipfte Poschte',
 280+ 'mwe-ok' => 'OK',
 281+ 'mwe-cancel' => 'Abbräche',
 282+ 'mwe-enable-gadget' => 'D Beta-Version vum Multimedia-Heälferli (mwEmbed) fir alli Syte aktiviere',
 283+ 'mwe-enable-gadget-done' => 'Beta-Version vum Multimedia-Hälferli isch aktiviert wore',
 284+ 'mwe-must-login-gadget' => 'Go s Hälferli aktiviere chenne, muesch di <a target="_new" href="$1">aamälde</a>',
 285+ 'mwe-test-plural' => '{{PLURAL:$1|$1 Tescht|$1 Tescht}} uusgfiert',
 286+);
 287+
 288+/** Hausa (هَوُسَ) */
 289+$messages['ha'] = array(
 290+ 'mwe-cancel' => 'Soke',
 291+);
 292+
 293+/** Hebrew (עברית)
 294+ * @author Rotemliss
 295+ */
 296+$messages['he'] = array(
 297+ 'mwe-loading_txt' => 'בטעינה ...',
 298+ 'mwe-error_load_lib' => 'שגיאה: לא ניתן היה לטעון את ספריית ה־JavaScript בשם $1 או שהיא אינה מגדירה את $2',
 299+);
 300+
 301+/** Upper Sorbian (Hornjoserbsce)
 302+ * @author Michawiki
 303+ */
 304+$messages['hsb'] = array(
 305+ 'mwe-loading_txt' => 'začituje so ...',
 306+ 'mwe-size-gigabytes' => '$1 GB',
 307+ 'mwe-size-megabytes' => '$1 MB',
 308+ 'mwe-size-kilobytes' => '$1 KB',
 309+ 'mwe-size-bytes' => '$1 B',
 310+ 'mwe-error_load_lib' => 'Zmylk: JavaScript $1 njeda so wotwołać abo njedefinuje $2',
 311+ 'mwe-apiproxy-setup' => 'Proksy API zarjadować',
 312+ 'mwe-load-drag-item' => 'Wlečeny zapisk so začituje',
 313+ 'mwe-ok' => 'W porjadku',
 314+ 'mwe-cancel' => 'Přetorhnyć',
 315+ 'mwe-enable-gadget' => 'Multimedia beta (mwEmbed) za wšě strony zmóžnić',
 316+ 'mwe-enable-gadget-done' => 'Přisłušk za Multimedia beta je so zmóžnił',
 317+ 'mwe-must-login-gadget' => 'Zo by přisłušk zmóžnił, dyrbiš so <a target="_new" href="$1">přizjewić</a>',
 318+ 'mwe-test-plural' => 'Sym {{PLURAL:$1|$1 test|$1 testaj|testy|testow}} přewjedł',
 319+);
 320+
 321+/** Hungarian (Magyar)
 322+ * @author Dani
 323+ * @author Glanthor Reviol
 324+ */
 325+$messages['hu'] = array(
 326+ 'mwe-loading_txt' => 'betöltés…',
 327+ 'mwe-error_load_lib' => 'Hiba: a(z) $1 JavaScript-fájl nem elérhető, vagy nem definiálja a(z) $2 osztályt.',
 328+ 'mwe-apiproxy-setup' => 'API proxy beállítása',
 329+ 'mwe-load-drag-item' => 'Vonszolt elem betöltése',
 330+ 'mwe-ok' => 'OK',
 331+ 'mwe-cancel' => 'Mégse',
 332+ 'mwe-enable-gadget' => 'A multimédia béta (mwEmbed) engedélyezése az összes lapon',
 333+ 'mwe-enable-gadget-done' => 'A multimédia béta segédeszköz engedélyezve',
 334+ 'mwe-must-login-gadget' => 'Hogy engedélyezni tudd a segédeszközt, <a target="_new" href="$1">be kell jelentkezned</a>',
 335+ 'mwe-test-plural' => '$1 tesztet futtattam',
 336+);
 337+
 338+/** Interlingua (Interlingua)
 339+ * @author McDutchie
 340+ */
 341+$messages['ia'] = array(
 342+ 'mwe-loading_txt' => 'cargamento ...',
 343+ 'mwe-error_load_lib' => 'Error: JavaScript $1 non esseva recuperabile o non defini $2',
 344+ 'mwe-apiproxy-setup' => 'Configuration del proxy pro le API',
 345+ 'mwe-load-drag-item' => 'Cargamento del file trahite',
 346+ 'mwe-ok' => 'OK',
 347+ 'mwe-cancel' => 'Cancella',
 348+ 'mwe-enable-gadget' => 'Activar beta multimedia (mwEmbed) pro tote le paginas',
 349+ 'mwe-enable-gadget-done' => 'Le gadget beta multimedia ha essite activate',
 350+ 'mwe-must-login-gadget' => 'Pro activar le gadget tu debe <a target="_new" href="$1">aperir un session</a>',
 351+ 'mwe-test-plural' => 'Io ha executate {{PLURAL:$1|$1 test|$1 tests}}',
 352+);
 353+
 354+/** Indonesian (Bahasa Indonesia)
 355+ * @author Farras
 356+ * @author Irwangatot
 357+ * @author IvanLanin
 358+ */
 359+$messages['id'] = array(
 360+ 'mwe-loading_txt' => 'memuat...',
 361+ 'mwe-error_load_lib' => 'Kesalahan: JavaScript $1 tidak dapat diambil atau tidak mendefinisikan $2',
 362+ 'mwe-apiproxy-setup' => 'Menyiapkan proksi API',
 363+ 'mwe-load-drag-item' => 'Memuat butir terseret',
 364+ 'mwe-ok' => 'Oke',
 365+ 'mwe-cancel' => 'Batalkan',
 366+ 'mwe-enable-gadget' => 'Aktifkan beta multimedia (mwEmbed) untuk semua halaman',
 367+ 'mwe-enable-gadget-done' => 'Gadget beta multimedia telah diaktifkan',
 368+ 'mwe-must-login-gadget' => 'Untuk mengaktifkan gadget Anda harus <a target="_new" href="$1">masuk log</a>',
 369+ 'mwe-test-plural' => 'Saya menjalankan {{PLURAL:$1|$1 tes|$1 tes}}',
 370+);
 371+
 372+/** Igbo (Igbo) */
 373+$messages['ig'] = array(
 374+ 'mwe-ok' => 'Ngwanu',
 375+ 'mwe-cancel' => 'Emekwàlà',
 376+);
 377+
 378+/** Italian (Italiano)
 379+ * @author Gianfranco
 380+ */
 381+$messages['it'] = array(
 382+ 'mwe-cancel' => 'Annulla',
 383+);
 384+
 385+/** Japanese (日本語)
 386+ * @author Fryed-peach
 387+ * @author 青子守歌
 388+ */
 389+$messages['ja'] = array(
 390+ 'mwe-loading_txt' => '読み込み中 …',
 391+ 'mwe-error_load_lib' => 'エラー:JavaScript $1 は参照不能か、$2 を定義していません。',
 392+ 'mwe-apiproxy-setup' => 'API プロキシーをセットアップ中',
 393+ 'mwe-load-drag-item' => 'ドラッグされた項目を読み込み中',
 394+ 'mwe-ok' => 'OK',
 395+ 'mwe-cancel' => '中止',
 396+ 'mwe-enable-gadget' => 'マルチメディアベータ(mwEmbed)を全ページで有効化',
 397+ 'mwe-enable-gadget-done' => 'マルチメディアベータのガジェットが有効です',
 398+ 'mwe-must-login-gadget' => 'ガジェットを有効にするには<a target="_new" href="$1">ログイン</a>が必要です',
 399+ 'mwe-test-plural' => '{{PLURAL:$1|$1のテスト}}を実行する',
 400+);
 401+
 402+/** Korean (한국어)
 403+ * @author Kwj2772
 404+ */
 405+$messages['ko'] = array(
 406+ 'mwe-loading_txt' => '불러오는 중...',
 407+ 'mwe-cancel' => '취소',
 408+);
 409+
 410+/** Colognian (Ripoarisch)
 411+ * @author Purodha
 412+ */
 413+$messages['ksh'] = array(
 414+ 'mwe-loading_txt' => 'aam Laade …',
 415+ 'mwe-size-gigabytes' => '$1&nbsp;GB',
 416+ 'mwe-size-megabytes' => '$1&nbsp;MB',
 417+ 'mwe-size-kilobytes' => '$1&nbsp;KB',
 418+ 'mwe-size-bytes' => '$1&nbsp;Bytes',
 419+ 'mwe-error_load_lib' => 'Fähler: Dat JavaSkrep „<code lang="en">$1</code>“ wohr nit ze laade udder et leiht „<code lang="en">$2</code>“ nit faß.',
 420+ 'mwe-cancel' => 'Affbräsche',
 421+);
 422+
 423+/** Luxembourgish (Lëtzebuergesch)
 424+ * @author Robby
 425+ */
 426+$messages['lb'] = array(
 427+ 'mwe-loading_txt' => 'lueden ...',
 428+ 'mwe-error_load_lib' => 'Feeler: JavaScript $1 konnt net ofgeruf ginn oder definéiert $2 net',
 429+ 'mwe-apiproxy-setup' => 'API-Proxy astellen',
 430+ 'mwe-load-drag-item' => 'Den agebonnen Objet gëtt gelueden',
 431+ 'mwe-ok' => 'OK',
 432+ 'mwe-cancel' => 'Ofbriechen',
 433+ 'mwe-enable-gadget' => 'Multimedia-Beta-Gadget (mwEmbed) fir all Säiten aktivéieren',
 434+ 'mwe-enable-gadget-done' => 'De Multimedia-Beta-Gadget gouf aktivéiert',
 435+ 'mwe-must-login-gadget' => 'Fir de Gadget aktivéieren ze kënne musst Dir Iech <a target="_new" href="$1">aloggen</a>',
 436+ 'mwe-test-plural' => 'Ech hunn {{PLURAL:$1|$1 Test|$1 Tester}} gemaach',
 437+);
 438+
 439+/** Macedonian (Македонски)
 440+ * @author Bjankuloski06
 441+ */
 442+$messages['mk'] = array(
 443+ 'mwe-loading_txt' => 'Вчитувам...',
 444+ 'mwe-error_load_lib' => 'Грешка: JavaScript $1 не е достапен или не определува $2',
 445+ 'mwe-apiproxy-setup' => 'Поставувам API застапник (proxy)',
 446+ 'mwe-load-drag-item' => 'Го вчитувам повлечениот елемент',
 447+ 'mwe-ok' => 'ОК',
 448+ 'mwe-cancel' => 'Откажи',
 449+ 'mwe-enable-gadget' => 'Овозможи бета-мултимедија (mwEmbed) за сите страници',
 450+ 'mwe-enable-gadget-done' => 'Овозможена е алатката за бета-мултимедија',
 451+ 'mwe-must-login-gadget' => 'За да ја овозможите алатката морате да се <a target="_new" href="$1">најавите</a>',
 452+ 'mwe-test-plural' => 'Направив {{PLURAL:$1|$1 проверка|$1 проверки}}',
 453+);
 454+
 455+/** Malayalam (മലയാളം)
 456+ * @author Praveenp
 457+ */
 458+$messages['ml'] = array(
 459+ 'mwe-loading_txt' => 'ശേഖരിക്കുന്നു ...',
 460+ 'mwe-error_load_lib' => 'പിശക്: ജാവാസ്ക്രിപ്റ്റ് $1 ശേഖരിക്കാൻ കഴിഞ്ഞില്ല അല്ലെങ്കിൽ $2 നിർവ്വചിച്ചിട്ടില്ല',
 461+ 'mwe-apiproxy-setup' => 'എ.പി.ഐ. പ്രോക്സി സജ്ജീകരിക്കുക',
 462+ 'mwe-load-drag-item' => 'വലിച്ചിട്ടത് ശേഖരിക്കുന്നു',
 463+ 'mwe-ok' => 'ശരി',
 464+ 'mwe-cancel' => 'റദ്ദാക്കുക',
 465+);
 466+
 467+/** Erzya (Эрзянь)
 468+ * @author Botuzhaleny-sodamo
 469+ */
 470+$messages['myv'] = array(
 471+ 'mwe-loading_txt' => 'Йовкстамозо моли…',
 472+);
 473+
 474+/** Dutch (Nederlands)
 475+ * @author Siebrand
 476+ */
 477+$messages['nl'] = array(
 478+ 'mwe-loading_txt' => 'bezig met laden ...',
 479+ 'mwe-error_load_lib' => 'Fout: JavaScript $1 kon niet opgehaald worden of definieert $2 niet',
 480+ 'mwe-apiproxy-setup' => 'Bezig met het opzetten van een API-proxy',
 481+ 'mwe-load-drag-item' => 'Bezig met het laden van het gesleepte bestand',
 482+ 'mwe-ok' => 'OK',
 483+ 'mwe-cancel' => 'Annuleren',
 484+ 'mwe-enable-gadget' => "Multimedia beta (mwEmbed) voor alle pagina's inschakelen",
 485+ 'mwe-enable-gadget-done' => 'Multimedia beta is ingeschakeld',
 486+ 'mwe-must-login-gadget' => 'Om de uitbreiding in te schakelen, moet u <a target="_new" href="$1">aanmelden</a>',
 487+ 'mwe-test-plural' => '{{PLURAL:$1|$1 test|$1 tests}} uitgevoerd',
 488+);
 489+
 490+/** Norwegian (bokmål)‬ (‪Norsk (bokmål)‬)
 491+ * @author Nghtwlkr
 492+ */
 493+$messages['no'] = array(
 494+ 'mwe-loading_txt' => 'Laster ...',
 495+ 'mwe-error_load_lib' => 'Feil: JavaScript $1 kunne ikke gjenhentes eller definerer ikke $2',
 496+ 'mwe-apiproxy-setup' => 'Setter opp API-mellomtjener',
 497+ 'mwe-load-drag-item' => 'Laster dratt element',
 498+ 'mwe-ok' => 'OK',
 499+ 'mwe-cancel' => 'Avbryt',
 500+ 'mwe-enable-gadget' => 'Aktiver multimedia-beta (mwEmbed) for alle sider',
 501+ 'mwe-enable-gadget-done' => 'Skjermelement for multimedia-beta har blitt aktivert',
 502+ 'mwe-must-login-gadget' => 'For å aktivere skjermelement må du <a target="_new" href="$1">logge inn</a>',
 503+ 'mwe-test-plural' => 'Jeg kjørte {{PLURAL:$1|én test|$1 tester}}',
 504+);
 505+
 506+/** Occitan (Occitan)
 507+ * @author Cedric31
 508+ */
 509+$messages['oc'] = array(
 510+ 'mwe-loading_txt' => 'cargament ...',
 511+ 'mwe-error_load_lib' => 'Error : JavaScript $1 a pas pogut èsser trobat o definís pas $2',
 512+ 'mwe-apiproxy-setup' => 'Configuracion del proxy API',
 513+ 'mwe-load-drag-item' => 'Cargament de l’element depausat',
 514+ 'mwe-ok' => 'OK',
 515+ 'mwe-cancel' => 'Anullar',
 516+);
 517+
 518+/** Deitsch (Deitsch)
 519+ * @author Xqt
 520+ */
 521+$messages['pdc'] = array(
 522+ 'mwe-ok' => 'OK',
 523+);
 524+
 525+/** Polish (Polski)
 526+ * @author Sp5uhe
 527+ */
 528+$messages['pl'] = array(
 529+ 'mwe-loading_txt' => 'ładowanie ...',
 530+ 'mwe-error_load_lib' => 'Błąd – W plik JavaScript $1 brak jest możliwości pobrania oraz definicji $2',
 531+ 'mwe-apiproxy-setup' => 'Konfiguracja proxy dla API',
 532+ 'mwe-load-drag-item' => 'Ładowanie przeciągniętego elementu',
 533+ 'mwe-ok' => 'OK',
 534+ 'mwe-cancel' => 'Anuluj',
 535+ 'mwe-enable-gadget' => 'Włącz wersję testową multimediów (wmEmbed) na wszystkich stronach',
 536+ 'mwe-enable-gadget-done' => 'Testowy gadżet multimediów został włączony',
 537+ 'mwe-must-login-gadget' => 'Gadżet można włączyć dopiero po <a target="_new" href="$1">zalogowaniu się</a>',
 538+ 'mwe-test-plural' => 'Wykonałem $1 {{PLURAL:$1|test|testy|testów}}',
 539+);
 540+
 541+/** Piedmontese (Piemontèis)
 542+ * @author Borichèt
 543+ * @author Dragonòt
 544+ */
 545+$messages['pms'] = array(
 546+ 'mwe-loading_txt' => 'A caria ...',
 547+ 'mwe-error_load_lib' => 'Eror: JavaScript $1 as peul pa trovesse o a definiss pa $2',
 548+ 'mwe-apiproxy-setup' => 'Amposté ël proxy API',
 549+ 'mwe-load-drag-item' => "carié l'element tirà",
 550+ 'mwe-ok' => 'Va bin',
 551+ 'mwe-cancel' => 'Scancela',
 552+ 'mwe-enable-gadget' => 'Abìlita la beta multimedia (mwEmbed) për tute le pàgine',
 553+ 'mwe-enable-gadget-done' => "L'acessòri beta multimedia a l'é stàit abilità",
 554+ 'mwe-must-login-gadget' => 'Për abilité l\'acessòri a dev <a target="_new" href="$1">intré ant ël sistema</a>',
 555+ 'mwe-test-plural' => "I l'heu fàit {{PLURAL:$1|$1 test|$1 test}}",
 556+);
 557+
 558+/** Pashto (پښتو)
 559+ * @author Ahmed-Najib-Biabani-Ibrahimkhel
 560+ */
 561+$messages['ps'] = array(
 562+ 'mwe-ok' => 'ښه',
 563+ 'mwe-cancel' => 'ناګارل',
 564+);
 565+
 566+/** Portuguese (Português)
 567+ * @author Hamilton Abreu
 568+ * @author Malafaya
 569+ */
 570+$messages['pt'] = array(
 571+ 'mwe-loading_txt' => 'A carregar ...',
 572+ 'mwe-error_load_lib' => 'Erro: O JavaScript $1 não pode ser importado ou não define $2',
 573+ 'mwe-apiproxy-setup' => "A preparar o ''proxy'' da API",
 574+ 'mwe-load-drag-item' => 'A carregar o objecto arrastado',
 575+ 'mwe-ok' => 'OK',
 576+ 'mwe-cancel' => 'Cancelar',
 577+ 'mwe-enable-gadget' => 'Activar multimédia beta (mwEmbed) para todas as páginas',
 578+ 'mwe-enable-gadget-done' => 'Gadget de multimédia beta foi activado',
 579+ 'mwe-must-login-gadget' => 'Para activar o gadget tem de estar <a target="_new" href="$1">autenticado</a>',
 580+ 'mwe-test-plural' => 'Fiz $1 {{PLURAL:$1|teste|testes}}',
 581+);
 582+
 583+/** Brazilian Portuguese (Português do Brasil)
 584+ * @author Giro720
 585+ * @author Luckas Blade
 586+ */
 587+$messages['pt-br'] = array(
 588+ 'mwe-loading_txt' => 'Carregando ...',
 589+ 'mwe-error_load_lib' => 'Erro: O JavaScript $1 não pode ser importado ou não define $2',
 590+ 'mwe-apiproxy-setup' => 'Configurando proxy da API',
 591+ 'mwe-load-drag-item' => 'Carregando o objeto arrastado',
 592+ 'mwe-ok' => 'OK',
 593+ 'mwe-cancel' => 'Cancelar',
 594+ 'mwe-enable-gadget' => 'Ativar multimídia beta beta (mwEmbed) para todas as páginas',
 595+ 'mwe-enable-gadget-done' => 'Gadget de multimídia beta foi ativado',
 596+ 'mwe-must-login-gadget' => 'Para ativar o gadget você deve estar <a target="_new" href="$1">autenticado</a>',
 597+ 'mwe-test-plural' => 'Eu fiz $1 {{PLURAL:$1|teste|testes}}',
 598+);
 599+
 600+/** Russian (Русский)
 601+ * @author Александр Сигачёв
 602+ */
 603+$messages['ru'] = array(
 604+ 'mwe-loading_txt' => 'загрузка …',
 605+ 'mwe-error_load_lib' => 'Ошибка. JavaScript $1 не доступен или не определяет $2',
 606+ 'mwe-apiproxy-setup' => 'Настройка API-прокси',
 607+ 'mwe-load-drag-item' => 'Загрузка перетащенного элемента',
 608+ 'mwe-ok' => 'OK',
 609+ 'mwe-cancel' => 'Отмена',
 610+ 'mwe-enable-gadget' => 'Включить бета-мультимедиа (mwEmbed) для всех страниц',
 611+ 'mwe-enable-gadget-done' => 'Включён гаджет бета-мультимедиа',
 612+ 'mwe-must-login-gadget' => 'Для включения гаджета вам следует <a target="_new" href="$1">представиться</a>.',
 613+ 'mwe-test-plural' => 'Я прошёл {{PLURAL:$1|$1 проверку|$1 проверки|$1 проверок}}',
 614+);
 615+
 616+/** Rusyn (Русиньскый)
 617+ * @author Gazeb
 618+ */
 619+$messages['rue'] = array(
 620+ 'mwe-ok' => 'ОК',
 621+ 'mwe-cancel' => 'Сторно',
 622+);
 623+
 624+/** Slovak (Slovenčina)
 625+ * @author Helix84
 626+ */
 627+$messages['sk'] = array(
 628+ 'mwe-loading_txt' => 'načítava sa ...',
 629+ 'mwe-error_load_lib' => 'Error: JavaScript $1 nebolo možné získať alebo neobsahuje definíciu $2',
 630+);
 631+
 632+/** Serbian Cyrillic ekavian (Српски (ћирилица))
 633+ * @author Михајло Анђелковић
 634+ */
 635+$messages['sr-ec'] = array(
 636+ 'mwe-loading_txt' => 'Учитавање ...',
 637+ 'mwe-ok' => 'ОК',
 638+ 'mwe-cancel' => 'Поништи',
 639+ 'mwe-test-plural' => 'Покренуо/ла сам {{PLURAL:$1|$1 тест|$1 тестова}}',
 640+);
 641+
 642+/** Serbian Latin ekavian (Srpski (latinica)) */
 643+$messages['sr-el'] = array(
 644+ 'mwe-loading_txt' => 'Učitavanje ...',
 645+ 'mwe-ok' => 'OK',
 646+ 'mwe-cancel' => 'Poništi',
 647+ 'mwe-test-plural' => 'Pokrenuo/la sam {{PLURAL:$1|$1 test|$1 testova}}',
 648+);
 649+
 650+/** Swedish (Svenska)
 651+ * @author Dafer45
 652+ * @author GameOn
 653+ */
 654+$messages['sv'] = array(
 655+ 'mwe-loading_txt' => 'Laddar…',
 656+ 'mwe-ok' => 'OK',
 657+ 'mwe-cancel' => 'Avbryt',
 658+);
 659+
 660+/** Telugu (తెలుగు)
 661+ * @author Veeven
 662+ */
 663+$messages['te'] = array(
 664+ 'mwe-ok' => 'సరే',
 665+ 'mwe-cancel' => 'రద్దుచేయి',
 666+);
 667+
 668+/** Tagalog (Tagalog)
 669+ * @author AnakngAraw
 670+ */
 671+$messages['tl'] = array(
 672+ 'mwe-loading_txt' => 'Ikinakarga...',
 673+ 'mwe-error_load_lib' => 'Kamalian: hindi makukuha ang JavaScript na $1 o hindi nagbigay kahulugan sa $2',
 674+ 'mwe-apiproxy-setup' => 'Nagtatalaga ng pamalit na API',
 675+ 'mwe-load-drag-item' => 'Ikinakarga ang hinilang bagay',
 676+ 'mwe-ok' => 'Okey',
 677+ 'mwe-cancel' => 'Huwag ituloy',
 678+ 'mwe-enable-gadget' => 'Paganahin ang betang multimidya (mwEmbed) para sa lahat ng mga pahina',
 679+ 'mwe-enable-gadget-done' => 'Pinagana ang gadyet na pangbetang multimidya',
 680+ 'mwe-must-login-gadget' => 'Upang mapagana ang gadyet dapat kang <a target="_new" href="$1">lumagda</a>',
 681+ 'mwe-test-plural' => 'Nagpatakbo ako ng {{PLURAL:$1|$1 pagsusulit|$1 mga pagsusulit}}',
 682+);
 683+
 684+/** Turkish (Türkçe)
 685+ * @author Joseph
 686+ */
 687+$messages['tr'] = array(
 688+ 'mwe-loading_txt' => 'yükleniyor ...',
 689+ 'mwe-error_load_lib' => 'Hata: $1 JavaScripti erişilebilir değil ya da $2 tanımlı değil',
 690+ 'mwe-apiproxy-setup' => 'API vekili ayarlanıyor',
 691+ 'mwe-load-drag-item' => 'Sürüklenen öğe yükleniyor',
 692+ 'mwe-ok' => 'Tamam',
 693+ 'mwe-cancel' => 'İptal',
 694+);
 695+
 696+/** Urdu (اردو) */
 697+$messages['ur'] = array(
 698+ 'mwe-cancel' => 'منسوخ',
 699+);
 700+
 701+/** Vèneto (Vèneto)
 702+ * @author Candalua
 703+ */
 704+$messages['vec'] = array(
 705+ 'mwe-loading_txt' => "so' drio cargar ...",
 706+ 'mwe-ok' => 'Va ben',
 707+ 'mwe-cancel' => 'Anula',
 708+);
 709+
 710+/** Vietnamese (Tiếng Việt)
 711+ * @author Minh Nguyen
 712+ * @author Vinhtantran
 713+ */
 714+$messages['vi'] = array(
 715+ 'mwe-loading_txt' => 'đang tải …',
 716+ 'mwe-size-kilobytes' => '$1 kB',
 717+ 'mwe-error_load_lib' => 'Lỗi: JavaScript $1 không truy xuất được hoặc không định nghĩa $2',
 718+ 'mwe-apiproxy-setup' => 'Đang thiết lập proxy API',
 719+ 'mwe-load-drag-item' => 'Đang tải các mục đã kéo',
 720+ 'mwe-ok' => 'OK',
 721+ 'mwe-cancel' => 'Hủy bỏ',
 722+ 'mwe-enable-gadget' => 'Kích hoạt đa phương tiện bản beta (mwEmbed) cho mọi trang',
 723+ 'mwe-enable-gadget-done' => 'Công cụ đa năng đa phương tiện bản beta đã được kích hoạt',
 724+ 'mwe-must-login-gadget' => 'Để kích hoạt công cụ đa năng bạn phải <a target="_new" href="$1">đăng nhập</a>',
 725+ 'mwe-test-plural' => 'Tôi đã chạy {{PLURAL:$1|$1 mẫu thử|$1 mẫu thử}}',
 726+);
 727+
 728+/** Wu (吴语) */
 729+$messages['wuu'] = array(
 730+ 'mwe-cancel' => '取消',
 731+);
 732+
 733+/** Simplified Chinese (‪中文(简体)‬) */
 734+$messages['zh-hans'] = array(
 735+ 'mwe-loading_txt' => '载入中……',
 736+ 'mwe-ok' => '确定',
 737+ 'mwe-cancel' => '取消',
 738+);
 739+
Property changes on: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MediaWikiSupport/mwEmbed.i18n.php
___________________________________________________________________
Added: svn:mergeinfo
1740 Merged /branches/sqlite/js2/mwEmbed/php/languages/mwEmbed.i18n.php:r58211-58321
2741 Merged /branches/REL1_15/phase3/js2/mwEmbed/php/languages/mwEmbed.i18n.php:r51646
Added: svn:eol-style
3742 + native
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MediaWikiSupport/mwEmbed.js
@@ -0,0 +1,2800 @@
 2+// Add support for html5 / mwEmbed elements to browsers that do not support the elements natively
 3+// For discussion and comments, see: http://ejohn.org/blog/html5-shiv/
 4+'video audio source track'.replace(/\w+/g, function(n){ document.createElement(n); });
 5+
 6+/**
 7+ * @license mwEmbed Dual licensed under the MIT or GPL Version 2 licenses.
 8+ *
 9+ * @copyright (C) 2010 Kaltura
 10+ * @author Michael Dale ( michael.dale at kaltura.com )
 11+ *
 12+ * @url http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library
 13+ *
 14+ * Libraries used include code license in headers
 15+ */
 16+
 17+/**
 18+ * Setup the "mw" global:
 19+ */
 20+if ( typeof window.mw == 'undefined' ) {
 21+ window.mw = { };
 22+}
 23+/**
 24+ * Set the mwEmbedVersion
 25+ */
 26+var MW_EMBED_VERSION = '1.1h';
 27+
 28+// Globals to pre-set ready functions in dynamic loading of mwEmbed
 29+if( typeof preMwEmbedReady == 'undefined'){
 30+ var preMwEmbedReady = [];
 31+}
 32+// Globals to pre-set config values in dynamic loading of mwEmbed
 33+if( typeof preMwEmbedConfig == 'undefined') {
 34+ var preMwEmbedConfig = [];
 35+}
 36+
 37+/**
 38+ * The global mw object:
 39+ */
 40+( function( mw ) {
 41+ // The version of mwEmbed
 42+ mw.version = MW_EMBED_VERSION;
 43+
 44+ // List valid skins here:
 45+ mw.validSkins = [ 'mvpcf', 'kskin' ];
 46+
 47+ // Storage variable for loaded style sheet keys
 48+ if( ! mw.style ){
 49+ mw.style = { };
 50+ }
 51+
 52+ /**
 53+ * Configuration System:
 54+ */
 55+
 56+ // Local scope configuration var:
 57+ if( !mwConfig ){
 58+ var mwConfig = { };
 59+ }
 60+
 61+ if( !mwNonDefaultConfigList ){
 62+ var mwNonDefaultConfigList = [];
 63+ }
 64+
 65+ // mw scope mwUserConfig var. Stores user configuration
 66+ var mwUserConfig = { };
 67+
 68+ /**
 69+ * Setter for configuration values
 70+ *
 71+ * @param [Mixed]
 72+ * name Name of configuration value {Object} Will iderate through
 73+ * each key and call setConfig {String} Will set configuration by
 74+ * string name to value
 75+ * @param {String}
 76+ * value Value of configuration name {Object} value Set of values
 77+ * to be merged
 78+ */
 79+ mw.setConfig = function ( name, value ) {
 80+ if( typeof name == 'object' ) {
 81+ for( var i in name ) {
 82+ mw.setConfig( i, name[ i ] );
 83+ }
 84+ return ;
 85+ }
 86+ mwConfig[ name ] = value;
 87+ mwNonDefaultConfigList.push( name );
 88+ };
 89+
 90+ // Apply any pre-setup config:
 91+ mw.setConfig( preMwEmbedConfig );
 92+
 93+ /**
 94+ * Merge in a configuration value:
 95+ */
 96+ mw.mergeConfig = function( name, value ){
 97+ if( typeof name == 'object' ) {
 98+ $j.each( name, function( inx, val) {
 99+ mw.setConfig( inx, val );
 100+ });
 101+ return ;
 102+ }
 103+ // Check if we should "merge" the config
 104+ if( typeof value == 'object' && typeof mwConfig[ name ] == 'object' ) {
 105+ if ( value.constructor.toString().indexOf("Array") != -1 &&
 106+ mwConfig[ name ].constructor.toString().indexOf("Array") != -1 ){
 107+ // merge in the array
 108+ mwConfig[ name ] = $j.merge( mwConfig[ name ], value );
 109+ } else {
 110+ for( var i in value ){
 111+ mwConfig[ name ][ i ] = value[ i ];
 112+ }
 113+ }
 114+ return ;
 115+ }
 116+ // else do a normal setConfig
 117+ mwConfig[ name ] = value;
 118+ mwNonDefaultConfigList.push( name );
 119+ };
 120+
 121+ /**
 122+ * Set a default config value Will only update configuration if no value is
 123+ * present
 124+ *
 125+ * @param [Mixed]
 126+ * value Set configuration name to value {Object} Will idorate
 127+ * through each key and call setDefaultConfig {String} Will set
 128+ * configuration by string name to value
 129+ */
 130+ mw.setDefaultConfig = function( name, value ) {
 131+ if( typeof name == 'object' ) {
 132+ for( var i in name ) {
 133+ mw.setDefaultConfig( i, name[ i ] );
 134+ }
 135+ return ;
 136+ }
 137+ if( typeof mwConfig[ name ] == 'undefined' ) {
 138+ mwConfig[ name ] = value;
 139+ return ;
 140+ }
 141+ };
 142+
 143+ /**
 144+ * Getter for configuration values
 145+ *
 146+ * @param {String}
 147+ * name of configuration value to get
 148+ * @return {Mixed} value of configuration key returns "false" if key not
 149+ * found
 150+ */
 151+ mw.getConfig = function ( name ) {
 152+ if( mwConfig[ name ] )
 153+ return mwConfig[ name ];
 154+ return false;
 155+ };
 156+ /**
 157+ * Get all the non-default configuration ( useful for passing state to
 158+ * iframes in limited hash url length of a few K )
 159+ */
 160+ mw.getNonDefaultConfigObject = function(){
 161+ var nonDefaultConfig = {};
 162+ for( var i =0 ; i < mwNonDefaultConfigList.length; i ++){
 163+ var configKey = mwNonDefaultConfigList[i];
 164+ nonDefaultConfig[ configKey ] = mw.getConfig( configKey );
 165+ }
 166+ return nonDefaultConfig;
 167+ }
 168+
 169+ /**
 170+ * Loads the mwUserConfig from a cookie.
 171+ *
 172+ * Modules that want to use "User Config" should call this setup function in
 173+ * their moduleLoader code.
 174+ *
 175+ * For performance interfaces using "user config" should load '$j.cookie' &
 176+ * 'JSON' in their module loader
 177+ *
 178+ * By abstracting user preference we could eventually integrate a persistent
 179+ * per-account preference system on the server.
 180+ *
 181+ * @parma {Function} callback Function to be called once userPrefrences are
 182+ * loaded
 183+ */
 184+ var setupUserConfigFlag = false;
 185+ mw.setupUserConfig = function( callback ) {
 186+ if( setupUserConfigFlag ) {
 187+ if( callback ) {
 188+ callback();
 189+ }
 190+ return ;
 191+ }
 192+ // Do Setup user config:
 193+ mw.load( [ '$j.cookie', 'JSON' ], function() {
 194+ if( $j.cookie( 'mwUserConfig' ) ) {
 195+ mwUserConfig = JSON.parse( $j.cookie( 'mwUserConfig' ) );
 196+ }
 197+ setupUserConfigFlag = true;
 198+ if( callback ) {
 199+ callback();
 200+ }
 201+ });
 202+ };
 203+
 204+ /**
 205+ * Save a user configuration var to a cookie & local global variable Loads
 206+ * the cookie plugin if not already loaded
 207+ *
 208+ * @param {String}
 209+ * name Name of user configuration value
 210+ * @param {String}
 211+ * value Value of configuration name
 212+ */
 213+ mw.setUserConfig = function ( name, value, cookieOptions ) {
 214+ if( ! setupUserConfigFlag ) {
 215+ mw.log( "Error: userConfig not setup" );
 216+ return false;
 217+ }
 218+ // Update local value
 219+ mwUserConfig[ name ] = value;
 220+
 221+ // Update the cookie ( '$j.cookie' & 'JSON' should already be loaded )
 222+ $j.cookie( 'mwUserConfig', JSON.stringify( mwUserConfig ) );
 223+ };
 224+
 225+ /**
 226+ * Save a user configuration var to a cookie & local global variable
 227+ *
 228+ * @param {String}
 229+ * name Name of user configuration value
 230+ * @return value of the configuration name false if the configuration name
 231+ * could not be found
 232+ */
 233+ mw.getUserConfig = function ( name ) {
 234+ if( mwUserConfig[ name ] )
 235+ return mwUserConfig[ name ];
 236+ return false;
 237+ };
 238+
 239+ /**
 240+ * Add a hook system for a target object / interface
 241+ *
 242+ * depricated you should instead use jQuery's bind and trigger
 243+ *
 244+ * @param {Object}
 245+ * targetObj Interface Object to add hook system to.
 246+ */
 247+ mw.addHookSystem = function( targetObj ) {
 248+
 249+ // Setup the target object hook holder:
 250+ targetObj[ 'hooks' ] = { };
 251+
 252+ /**
 253+ * Adds a hook to the target object
 254+ *
 255+ * Should be called by clients to setup named hooks
 256+ *
 257+ * @param {String}
 258+ * hookName Name of hook to be added
 259+ * @param {Function}
 260+ * hookFunction Function to be called at hook time
 261+ */
 262+ targetObj.addHook = function( hookName, hookFunction ) {
 263+ if( ! this.hooks[ hookName ] ) {
 264+ this.hooks[ hookName ] = [ ];
 265+ }
 266+ this.hooks[ hookName ].push( hookFunction );
 267+ };
 268+
 269+ /**
 270+ * Runs all the hooks by a given name with reference to the host object
 271+ *
 272+ * Should be called by the host object at named execution points
 273+ *
 274+ * @param {String}
 275+ * hookName Name of hook to be called
 276+ * @return Value of hook result true interface should continue function
 277+ * execution false interface should stop or return from method
 278+ */
 279+ targetObj.runHook = function( hookName, options ) {
 280+ if( this.hooks[ hookName ] ) {
 281+ for( var i =0; i < this.hooks[ hookName ].length; i ++ ) {
 282+ if( typeof( this.hooks[ hookName ][ i ] ) == 'function' ) {
 283+ this.hooks[ hookName ][ i ]( options );
 284+ }
 285+ }
 286+ }
 287+ };
 288+ };
 289+
 290+ // Add hooks system to the core "mw" object
 291+ mw.addHookSystem( mw );
 292+
 293+ // Stores callbacks for resource loader loading
 294+ var mwLoadDoneCB = { };
 295+
 296+
 297+ /**
 298+ * Top level loader prototype:
 299+ */
 300+ mw.loader = {
 301+ /**
 302+ * Javascript Module Loader functions
 303+ *
 304+ * @key Name of Module
 305+ * @value function code to load module
 306+ */
 307+ moduleLoaders : [],
 308+
 309+ /**
 310+ * Module resource list queue.
 311+ *
 312+ * @key Name of Module
 313+ * @value .resourceList list of resources to be loaded .functionQueue
 314+ * list of functions to be run once module is ready
 315+ */
 316+ moduleLoadQueue: { },
 317+
 318+ /**
 319+ * Javascript Class Paths
 320+ *
 321+ * @key Name of resource
 322+ * @value Class file path
 323+ */
 324+ resourcePaths : { },
 325+
 326+ /**
 327+ * Stores resources that have been requested ( to avoid re-requesting
 328+ * the same resources ) in concurrent requests )
 329+ */
 330+ requestedResourceQueue: { },
 331+
 332+ /**
 333+ * javascript Resource Paths
 334+ *
 335+ * @key Name of resource
 336+ * @value Name of depenent style sheet
 337+ */
 338+ resourceStyleDependency: { },
 339+
 340+ /**
 341+ * Core load function:
 342+ *
 343+ * @param {Mixed}
 344+ * loadRequest:
 345+ *
 346+ * {String} Name of a module to be loaded Modules are added via
 347+ * addModuleLoader and can define custom code needed to check config and
 348+ * return a list of resources to be loaded
 349+ *
 350+ * {String} Name of a resource to loaded. Resources are added via
 351+ * addResourcePaths function Using defined resource names avoids loading
 352+ * the same resource twice by first checking if the named resource is
 353+ * defined in the global javascript scope variable
 354+ *
 355+ * {String} Absolute or relative to url path The same file won't be
 356+ * loaded twice
 357+ *
 358+ * {Array} can be an array of any combination of the above strings. Will
 359+ * be loaded in-order or in a single resource loader request if
 360+ * scriptLoader is available.
 361+ *
 362+ * {Array} {Array} Can be a set of Arrays for loading. Some browsers
 363+ * execute included scripts out of order. This lets you chain sets of
 364+ * request for those browsers. If using the server side resource loader
 365+ * order is preserved in output and a single request will be used.
 366+ *
 367+ * @param {Function}
 368+ * callback Function called once loading is complete
 369+ *
 370+ */
 371+ load: function( loadRequest, instanceCallback ) {
 372+ // mw.log("mw.load:: " + loadRequest );
 373+ var _this = this;
 374+
 375+ // Throw out any loadRequests that are not strings
 376+ loadRequest = this.cleanLoadRequest( loadRequest );
 377+
 378+ // Ensure the callback is only called once per load instance
 379+ var callback = function(){
 380+ // mw.log( 'instanceCallback::running callback: ' +
 381+ // instanceCallback );
 382+ if( instanceCallback ){
 383+ // We pass the loadRequest back to the callback for easy
 384+ // debugging of concurrency issues.
 385+ // ( normally its not used )
 386+ instanceCallback( loadRequest );
 387+ instanceCallback = null;
 388+ }
 389+ };
 390+
 391+ // Check for empty loadRequest ( directly return the callback )
 392+ if( mw.isEmpty( loadRequest ) ) {
 393+ mw.log( 'Empty load request: ( ' + loadRequest + ' ) ' );
 394+ callback( loadRequest );
 395+ return ;
 396+ }
 397+
 398+
 399+ // Check if its a multi-part request:
 400+ if( typeof loadRequest == 'object' ) {
 401+ if( loadRequest.length > 1 ) {
 402+ this.loadMany ( loadRequest, callback );
 403+ return ;
 404+ }else{
 405+ // If an array of length 1 set as first element
 406+ loadRequest = loadRequest[0];
 407+ }
 408+ }
 409+
 410+ // Check for the module name loader function
 411+ if( this.moduleLoaders[ loadRequest ] ) {
 412+ var resourceSet = this.getModuleResourceSet( loadRequest );
 413+ if( !resourceSet ){
 414+ mw.log( "mw.load:: Error with module loader: " + loadRequest + ' ( no resource set defined )' );
 415+ return ;
 416+ }
 417+
 418+ // xxx should use refactor "ready" stuff into a "domReady" class
 419+ // So we would not have local scope globals like this:
 420+ // if ( mwReadyFlag ) {
 421+ // Load the module directly if load request is after
 422+ // mw.ready has run
 423+ this.load( resourceSet, callback );
 424+ // } else {
 425+ // this.addToModuleLoaderQueue(
 426+ // loadRequest,
 427+ // resourceSet,
 428+ // callback
 429+ // );
 430+ // }
 431+ return ;
 432+ }
 433+
 434+ // Check for javascript resource
 435+ if( this.getResourcePath( loadRequest ) ) {
 436+ this.loadResource( loadRequest, callback );
 437+ return ;
 438+ }
 439+
 440+ // Try loading as a "file" or via ScriptLoader
 441+ if( loadRequest ) {
 442+ // Check if this resource was already requested
 443+ if( typeof this.requestedResourceQueue[ loadRequest ] == 'object' ){
 444+ this.requestedResourceQueue[ loadRequest ].push( callback );
 445+ return ;
 446+ } else {
 447+ this.requestedResourceQueue[ loadRequest ] = [];
 448+ }
 449+
 450+ if( loadRequest.indexOf( '.js' ) == -1 && !mw.getResourceLoaderPath() ) {
 451+ mw.log( 'Error: are you sure ' + loadRequest + ' is a file ( is it missing a resource path? ) ' );
 452+ }
 453+ mw.getScript( loadRequest, function(){
 454+ // Check if we have requestedResources queue items:
 455+ while( _this.requestedResourceQueue[ loadRequest ].length ){
 456+ _this.requestedResourceQueue[ loadRequest ].shift()( loadRequest );
 457+ }
 458+ callback( loadRequest );
 459+ // empty the load request queue:
 460+ _this.requestedResourceQueue[ loadRequest ] = [];
 461+ });
 462+ return ;
 463+ }
 464+
 465+ // Possible error?
 466+ mw.log( "Error could not handle load request: " + loadRequest );
 467+ },
 468+
 469+ getModuleResourceSet: function( moduleName ){
 470+ // Check if the module loader is a function ~run that function~
 471+ if( typeof ( this.moduleLoaders[ moduleName ] ) == 'function' ) {
 472+ // Add the result of the module loader function
 473+ return this.moduleLoaders[ moduleName ]();
 474+ } else if( typeof ( this.moduleLoaders[ moduleName ] ) == 'object' ){
 475+ // set resourceSet directly
 476+ return this.moduleLoaders[ moduleName ];
 477+ }
 478+ return false;
 479+ },
 480+
 481+ /**
 482+ * Clean the loadRequest ( throw out any non-string items )
 483+ */
 484+ cleanLoadRequest: function( loadRequest ){
 485+ var cleanRequest = [];
 486+ if( ! loadRequest ){
 487+ return [];
 488+ }
 489+ if( typeof loadRequest == 'string' )
 490+ return loadRequest;
 491+ for( var i =0;i < loadRequest.length; i++ ){
 492+ if( typeof loadRequest[i] == 'object' ) {
 493+ cleanRequest[i] = this.cleanLoadRequest( loadRequest[i] );
 494+ } else if( typeof loadRequest[i] == 'string' ){
 495+ cleanRequest[i] = $j.trim( loadRequest[i] );
 496+ } else{
 497+ // bad request type skip
 498+ }
 499+ }
 500+ return cleanRequest;
 501+ },
 502+
 503+ /**
 504+ * Load a set of scripts. Will issue many load requests or package the
 505+ * request for the resource loader
 506+ *
 507+ * @param {Object}
 508+ * loadSet Set of scripts to be loaded
 509+ * @param {Function}
 510+ * callback Function to call once all scripts are loaded.
 511+ */
 512+ loadMany: function( loadSet, callback ) {
 513+ var _this = this;
 514+ // Setup up the local "loadStates"
 515+ var loadStates = { };
 516+
 517+ // Check if we can load via the "resource loader" ( mwEmbed was
 518+ // included via scriptLoader )
 519+ if( mw.getResourceLoaderPath() ) {
 520+ // Get the grouped loadStates variable
 521+ loadStates = this.getGroupLoadState( loadSet );
 522+ if( mw.isEmpty( loadStates ) ) {
 523+ // mw.log( 'loadMany:all resources already loaded');
 524+ callback();
 525+ return ;
 526+ }
 527+ }else{
 528+ // Check if its a dependency set ( nested objects )
 529+ if( typeof loadSet [ 0 ] == 'object' ) {
 530+ _this.dependencyChainCallFlag[ loadSet ] = false;
 531+ // Load sets of resources ( to preserver order for some
 532+ // browsers )
 533+ _this.loadDependencyChain( loadSet, callback );
 534+ return ;
 535+ }
 536+
 537+ // Set the initial load state for every item in the loadSet
 538+ for( var i = 0; i < loadSet.length ; i++ ) {
 539+ var loadName = loadSet[ i ];
 540+ loadStates[ loadName ] = 0;
 541+ }
 542+ }
 543+
 544+ // We are infact loading many:
 545+ // mw.log("mw.load: LoadMany:: " + loadSet );
 546+
 547+ // Issue the load request check check loadStates to see if we are
 548+ // "done"
 549+ for( var loadName in loadStates ) {
 550+ // mw.log("loadMany: load: " + loadName );
 551+ this.load( loadName, function ( loadName ) {
 552+ loadStates[ loadName ] = 1;
 553+
 554+ /*
 555+ * for( var i in loadStates ) { mw.log( loadName + '
 556+ * finished of: ' + i + ' : ' + loadStates[i] ); }
 557+ */
 558+
 559+ // Check if all load request states are set 1
 560+ var loadDone = true;
 561+ for( var j in loadStates ) {
 562+ if( loadStates[ j ] === 0 )
 563+ loadDone = false;
 564+ }
 565+ // Run the parent scope callback for "loadMany"
 566+ if( loadDone ) {
 567+ callback( loadName );
 568+ }
 569+ } );
 570+ }
 571+ },
 572+
 573+ /**
 574+ * Get grouped load state for script loader
 575+ *
 576+ * Groups the scriptRequest where possible: Modules include "loader
 577+ * code" so they are separated into pre-condition code to be run for
 578+ * subsequent requests
 579+ *
 580+ * @param {Object}
 581+ * loadSet Loadset to return grouped
 582+ * @return {Object} grouped loadSet
 583+ */
 584+ getGroupLoadState: function( loadSet ) {
 585+ var groupedLoadSet = [];
 586+ var loadStates = { };
 587+ // Merge load set into new groupedLoadSet
 588+ if( typeof loadSet[0] == 'object' ) {
 589+ for( var i = 0; i < loadSet.length ; i++ ) {
 590+ for( var j = 0; j < loadSet[i].length ; j++ ) {
 591+ // Make sure we have not already included it:
 592+ groupedLoadSet.push( loadSet[i][j] );
 593+ }
 594+ }
 595+ } else {
 596+ // Use the loadSet directly:
 597+ groupedLoadSet = loadSet;
 598+ }
 599+
 600+ // Setup grouped loadStates Set:
 601+ var groupClassKey = '';
 602+ var coma = '';
 603+ var uniqueResourceName = {};
 604+ for( var i=0; i < groupedLoadSet.length; i++ ) {
 605+ var loadName = groupedLoadSet[ i ];
 606+ if( this.getResourcePath( loadName ) ) {
 607+ // Check if not already in request queue and not defined in
 608+ // global namespace
 609+ if( !mw.isset( loadName ) && ! uniqueResourceName[ loadName] ){
 610+ groupClassKey += coma + loadName;
 611+ coma = ',';
 612+
 613+ // Check for style sheet dependencies
 614+ if( this.resourceStyleDependency[ loadName ] ){
 615+ groupClassKey += coma + this.resourceStyleDependency[ loadName ];
 616+ }
 617+ }
 618+ } else if ( this.moduleLoaders[ loadName ] ) {
 619+
 620+ // Module loaders break up grouped script requests ( add the
 621+ // current groupClassKey )
 622+ if( groupClassKey != '' ) {
 623+ loadStates[ groupClassKey ] = 0;
 624+ groupClassKey = coma = '';
 625+ }
 626+ if( ! uniqueResourceName[ loadName] ){
 627+ // Add the module to the loadSate
 628+ loadStates[ loadName ] = 0;
 629+ }
 630+ }
 631+ uniqueResourceName[ loadName] = true;
 632+ }
 633+
 634+ // Add groupClassKey if set:
 635+ if( groupClassKey != '' ) {
 636+ loadStates [ groupClassKey ] = 0;
 637+ }
 638+
 639+ return loadStates;
 640+ },
 641+
 642+ // Array to register that a callback has been called
 643+ dependencyChainCallFlag: { },
 644+
 645+ /**
 646+ * Load a sets of scripts satisfy dependency order for browsers that
 647+ * execute dynamically included scripts out of order
 648+ *
 649+ * @param {Object}
 650+ * loadChain A set of javascript arrays to be loaded. Sets
 651+ * are requested in array order.
 652+ */
 653+ loadDependencyChain: function( loadChain, callback ) {
 654+ var _this = this;
 655+ // Load with dependency checks
 656+ var callSet = loadChain.shift();
 657+ this.load( callSet, function( cbname ) {
 658+ if ( loadChain.length != 0 ) {
 659+ _this.loadDependencyChain( loadChain, callback );
 660+ } else {
 661+ // NOTE: IE gets called twice so we have check the
 662+ // dependencyChainCallFlag before calling the callback
 663+ if( _this.dependencyChainCallFlag[ callSet ] == callback ) {
 664+ mw.log("... already called this callback for " + callSet );
 665+ return ;
 666+ }
 667+ _this.dependencyChainCallFlag[ callSet ] = callback;
 668+ callback( );
 669+ }
 670+ } );
 671+ },
 672+
 673+ /**
 674+ * Add to the module loader queue
 675+ */
 676+ addToModuleLoaderQueue: function( moduleName, resourceSet, callback ) {
 677+ mw.log(" addToModuleLoaderQueue:: " + moduleName + ' resourceSet: ' + resourceSet );
 678+ if( this.moduleLoadQueue[ moduleName ] ){
 679+ // If the module is already in the queue just add its callback:
 680+ this.moduleLoadQueue[ moduleName ].functionQueue.push( callback );
 681+ } else {
 682+ // create the moduleLoadQueue item
 683+ this.moduleLoadQueue[ moduleName ] = {
 684+ 'resourceSet' : resourceSet,
 685+ 'functionQueue' : [ callback ],
 686+ 'loaded' : false
 687+ };
 688+ }
 689+ },
 690+
 691+ /**
 692+ * Loops over all modules in queue, builds request sets based on config
 693+ * request type
 694+ */
 695+ runModuleLoadQueue: function(){
 696+ var _this = this;
 697+ mw.log( "mw.runModuleLoadQueue:: " );
 698+ var runModuleFunctionQueue = function(){
 699+ // Run all the callbacks
 700+ for( var moduleName in _this.moduleLoadQueue ){
 701+ while( _this.moduleLoadQueue[moduleName].functionQueue.length ) {
 702+ _this.moduleLoadQueue[moduleName].functionQueue.shift()();
 703+ }
 704+ }
 705+ };
 706+
 707+ // Check for single request or javascript debug based loading:
 708+ if( !mw.getResourceLoaderPath() || mw.getConfig( 'loader.groupStrategy' ) == 'single' ){
 709+ // if not using the resource load just do a normal array merge
 710+ // ( for browsers like IE that don't follow first append first
 711+ // execute rule )
 712+ var fullResourceList = [];
 713+ for( var moduleName in this.moduleLoadQueue ) {
 714+ var resourceSet = this.moduleLoadQueue[ moduleName ].resourceSet;
 715+ // Lets try a global merge
 716+ fullResourceList = $j.merge( fullResourceList, resourceSet );
 717+ }
 718+ mw.load( fullResourceList, function(){
 719+ runModuleFunctionQueue();
 720+ });
 721+ return ;
 722+ }
 723+
 724+ // Else do per module group loading
 725+ if( mw.getConfig( 'loader.groupStrategy' ) == 'module' ) {
 726+ var fullResourceList = [];
 727+ var sharedResourceList = [];
 728+
 729+ for( var moduleName in this.moduleLoadQueue ) {
 730+ // Build a shared dependencies list and load that separately
 731+ // "first"
 732+ // ( in IE we have to wait until its "ready" since it does
 733+ // not follow dom order )
 734+ var moduleResourceList = this.getFlatModuleResourceList( moduleName );
 735+ // Build the sharedResourceList
 736+ for( var i=0; i < moduleResourceList.length; i++ ){
 737+ var moduleResource = moduleResourceList[i];
 738+ // Check if already in the full resource list if so add
 739+ // to shared.
 740+ if( fullResourceList[ moduleResource ] ){
 741+ if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){
 742+ sharedResourceList.push( moduleResource );
 743+ }
 744+ }
 745+ // Add to the fullResourceList
 746+ fullResourceList[ moduleResource ] = true;
 747+ }
 748+ }
 749+
 750+ // Local module request set ( stores the actual request we will
 751+ // make after grouping shared resources
 752+ var moduleRequestSet = {};
 753+
 754+ // Only add non-shared to respective modules load requests
 755+ for( var moduleName in this.moduleLoadQueue ) {
 756+ moduleRequestSet[ moduleName ] = [];
 757+ var moduleResourceList = this.getFlatModuleResourceList( moduleName );
 758+ for( var i =0; i < moduleResourceList.length; i++ ){
 759+ var moduleResource = moduleResourceList[i];
 760+ if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){
 761+ moduleRequestSet[ moduleName ].push( moduleResource );
 762+ }
 763+ }
 764+ }
 765+ var sharedResourceLoadDone = false;
 766+ // Check if modules are done
 767+ var checkModulesDone = function(){
 768+ if( !sharedResourceLoadDone ){
 769+ return false;
 770+ }
 771+ for( var moduleName in _this.moduleLoadQueue ) {
 772+ if( ! _this.moduleLoadQueue[ moduleName ].loaded ){
 773+ return false;
 774+ }
 775+ }
 776+ runModuleFunctionQueue();
 777+ };
 778+ // Local instance of load requests to retain resourceSet
 779+ // context:
 780+ var localLoadCallInstance = function( moduleName, resourceSet ){
 781+ mw.load( resourceSet, function(){
 782+ _this.moduleLoadQueue[ moduleName ].loaded = true;
 783+ checkModulesDone();
 784+ });
 785+ };
 786+
 787+ // Load the shared resources
 788+ mw.load( sharedResourceList, function(){
 789+ // mw.log("Shared Resources loaded");
 790+ // xxx check if we are in "IE" and dependencies need to be
 791+ // loaded "first"
 792+ sharedResourceLoadDone = true;
 793+ checkModulesDone();
 794+ });
 795+ // Load all module Request Set
 796+ for( var moduleName in moduleRequestSet ){
 797+ localLoadCallInstance( moduleName, moduleRequestSet[ moduleName ] );
 798+ }
 799+ }
 800+ // xxx Here we could also do some "intelligent" grouping
 801+ },
 802+
 803+ getFlatModuleResourceList: function( moduleName ){
 804+ var moduleList = [];
 805+ for( var j in this.moduleLoadQueue[moduleName].resourceSet ){
 806+ // Check if we have a multi-set array:
 807+ if( typeof this.moduleLoadQueue[moduleName].resourceSet[j] == 'object' ){
 808+ moduleList = $j.merge( moduleList, this.moduleLoadQueue[moduleName].resourceSet[j] );
 809+ } else {
 810+ moduleList = $j.merge( moduleList, [ this.moduleLoadQueue[moduleName].resourceSet[j] ] );
 811+ }
 812+ }
 813+ return moduleList;
 814+ },
 815+
 816+ /**
 817+ * Loads javascript or css associated with a resourceName
 818+ *
 819+ * @param {String}
 820+ * resourceName Name of resource to load
 821+ * @param {Function}
 822+ * callback Function to run once resource is loaded
 823+ */
 824+ loadResource: function( resourceName , callback) {
 825+ // mw.log("LoadResource:" + resourceName );
 826+ var _this = this;
 827+
 828+ // Check for css dependency on resource name
 829+ if( this.resourceStyleDependency[ resourceName ] ) {
 830+ if( ! mw.isset( this.resourceStyleDependency[ resourceName ] )){
 831+ mw.log("loadResource:: dependent css resource: " + this.resourceStyleDependency[ resourceName ] );
 832+ _this.loadResource( this.resourceStyleDependency[ resourceName ] , function() {
 833+ // Continue the original loadResource request.
 834+ _this.loadResource( resourceName, callback );
 835+ });
 836+ return ;
 837+ }
 838+ }
 839+
 840+ // Make sure the resource is not already defined:
 841+ if ( mw.isset( resourceName ) ) {
 842+ // mw.log( 'Class ( ' + resourceName + ' ) already defined ' );
 843+ callback( resourceName );
 844+ return ;
 845+ }
 846+
 847+ // Setup the Script Request var:
 848+ var scriptRequest = null;
 849+
 850+
 851+ // If the scriptloader is enabled use the resourceName as the
 852+ // scriptRequest:
 853+ if( mw.getResourceLoaderPath() ) {
 854+ scriptRequest = resourceName;
 855+ }else{
 856+ // Get the resource url:
 857+ var baseClassPath = this.getResourcePath( resourceName );
 858+ // Add the mwEmbed path if not a root path or a full url
 859+ if( baseClassPath.indexOf( '/' ) !== 0 &&
 860+ baseClassPath.indexOf( '://' ) === -1 ) {
 861+ scriptRequest = mw.getMwEmbedPath() + baseClassPath;
 862+ }else{
 863+ scriptRequest = baseClassPath;
 864+ }
 865+ if( ! scriptRequest ) {
 866+ mw.log( "Error Could not get url for resource " + resourceName );
 867+ return false;
 868+ }
 869+ }
 870+ // Include resource defined check for older browsers
 871+ var resourceDone = false;
 872+
 873+ // Set the loadDone callback per the provided resourceName
 874+ mw.setLoadDoneCB( resourceName, callback );
 875+ // Issue the request to load the resource (include resource name in
 876+ // result callback:
 877+ mw.getScript( scriptRequest, function( scriptRequest ) {
 878+ // If its a "style sheet" manually set its resource to true
 879+ var ext = scriptRequest.substr( scriptRequest.split('?')[0].lastIndexOf( '.' ), 4 ).toLowerCase();
 880+ if( ext == '.css' && resourceName.substr(0,8) == 'mw.style' ){
 881+ mw.style[ resourceName.substr( 9 ) ] = true;
 882+ }
 883+
 884+ // Send warning if resourceName is not defined
 885+ if(! mw.isset( resourceName )
 886+ && mwLoadDoneCB[ resourceName ] != 'done' ) {
 887+ // mw.log( 'Possible Error: ' + resourceName +' not set in
 888+ // time, or not defined in:' + "\n"
 889+ // + _this.getResourcePath( resourceName ) );
 890+ }
 891+
 892+ // If ( debug mode ) and the script include is missing resource
 893+ // messages
 894+ // do a separate request to retrieve the msgs
 895+ if( mw.currentClassMissingMessages ) {
 896+ mw.log( " resourceName " + resourceName + " is missing messages" );
 897+ // Reset the currentClassMissingMessages flag
 898+ mw.currentClassMissingMessages = false;
 899+
 900+ // Load msgs for this resource:
 901+ mw.loadResourceMessages( resourceName, function() {
 902+ // Run the onDone callback
 903+ mw.loadDone( resourceName );
 904+ } );
 905+ } else {
 906+ // If not using the resource loader make sure the
 907+ // resourceName is available before firing the loadDone
 908+ if( !mw.getResourceLoaderPath() ) {
 909+ mw.waitForObject( resourceName, function( resourceName ) {
 910+ // Once object is ready run loadDone
 911+ mw.loadDone( resourceName );
 912+ } );
 913+ } else {
 914+ // loadDone should be appended to the bottom of the
 915+ // resource loader response
 916+ // mw.loadDone( resourceName );
 917+ }
 918+ }
 919+ } );
 920+ },
 921+
 922+ /**
 923+ * Adds a module to the mwLoader object
 924+ *
 925+ * @param {String}
 926+ * name Name of module
 927+ * @param {Function}
 928+ * moduleLoader Function that loads dependencies for a module
 929+ */
 930+ addModuleLoader: function( name, moduleLoader ) {
 931+ this.moduleLoaders [ name ] = moduleLoader;
 932+ },
 933+
 934+ /**
 935+ * Adds resource file path key value pairs
 936+ *
 937+ * @param {Object}
 938+ * resourceSet JSON formated list of resource name file path
 939+ * pairs.
 940+ *
 941+ * resourceSet must be strict JSON to allow the php scriptLoader to
 942+ * parse the file paths.
 943+ */
 944+ addResourcePaths: function( resourceSet ) {
 945+ var prefix = ( mw.getConfig( 'loaderContext' ) )?
 946+ mw.getConfig( 'loaderContext' ): '';
 947+
 948+ for( var i in resourceSet ) {
 949+ this.resourcePaths[ i ] = prefix + resourceSet[ i ];
 950+ }
 951+ },
 952+
 953+ /*
 954+ * Adds a named style sheet dependency to a named resource
 955+ *
 956+ * @parma {Object} resourceSet JSON formated list of resource names and
 957+ * associated style sheet names
 958+ */
 959+ addStyleResourceDependency: function( resourceSet ){
 960+ for( var i in resourceSet ){
 961+ this.resourceStyleDependency[ i ] = resourceSet[i];
 962+ }
 963+ },
 964+
 965+ /**
 966+ * Get a resource path from a resourceName if no resource found return
 967+ * false
 968+ */
 969+ getResourcePath: function( resourceName ) {
 970+ if( this.resourcePaths[ resourceName ] )
 971+ return this.resourcePaths[ resourceName ];
 972+ return false;
 973+ }
 974+ };
 975+
 976+ /**
 977+ * Load done callback for script loader
 978+ *
 979+ * @param {String}
 980+ * requestName Name of the load request
 981+ */
 982+ mw.loadDone = function( requestName ) {
 983+ if( !mwLoadDoneCB[ requestName ] ) {
 984+ return true;
 985+ }
 986+ while( mwLoadDoneCB[ requestName ].length ) {
 987+ // check if mwLoadDoneCB is already "done"
 988+ // the function list is not an object
 989+ if( typeof mwLoadDoneCB[ requestName ] != 'object' )
 990+ {
 991+ break;
 992+ }
 993+ var func = mwLoadDoneCB[ requestName ].pop();
 994+ if( typeof func == 'function' ) {
 995+ // mw.log( "LoadDone: " + requestName + ' run callback::' +
 996+ // func);
 997+ func( requestName );
 998+ }else{
 999+ mw.log('mwLoadDoneCB: Error non callback function on stack');
 1000+ }
 1001+ }
 1002+ // Set the load request name to done
 1003+ mwLoadDoneCB[ requestName ] = 'done';
 1004+ };
 1005+
 1006+ /**
 1007+ * Set a load done callback
 1008+ *
 1009+ * @param {String}
 1010+ * requestName Name of resource or request set
 1011+ * @param {Function}
 1012+ * callback Function called once requestName is ready
 1013+ */
 1014+ mw.setLoadDoneCB = function( requestName, callback ) {
 1015+ // If the requestName is already done loading just callback
 1016+ if( mwLoadDoneCB[ requestName ] == 'done' ) {
 1017+ callback( requestName );
 1018+ }
 1019+ // Setup the function queue if unset
 1020+ if( typeof mwLoadDoneCB[ requestName ] != 'object' ) {
 1021+ mwLoadDoneCB[ requestName ] = [];
 1022+ }
 1023+ mwLoadDoneCB[ requestName ].push( callback );
 1024+ };
 1025+
 1026+ /**
 1027+ * Shortcut entry points / convenience functions: Lets you write mw.load()
 1028+ * instead of mw.loader.load() only these entry points should be used.
 1029+ *
 1030+ * future closure optimizations could minify internal function names
 1031+ */
 1032+
 1033+ /**
 1034+ * Load Object entry point: Loads a requested set of javascript
 1035+ */
 1036+ mw.load = function( loadRequest, callback ) {
 1037+ return mw.loader.load( loadRequest, callback );
 1038+ };
 1039+
 1040+ /**
 1041+ * Add module entry point: Adds a module to the mwLoader object
 1042+ */
 1043+ mw.addModuleLoader = function ( name, loaderFunction ) {
 1044+ return mw.loader.addModuleLoader( name, loaderFunction );
 1045+ };
 1046+
 1047+ /**
 1048+ * Add Class File Paths entry point:
 1049+ */
 1050+ mw.addResourcePaths = function ( resourceSet ) {
 1051+ return mw.loader.addResourcePaths( resourceSet );
 1052+ };
 1053+
 1054+ mw.addStyleResourceDependency = function ( resourceSet ) {
 1055+ return mw.loader.addStyleResourceDependency( resourceSet );
 1056+ };
 1057+
 1058+ /**
 1059+ * Get Class File Path entry point:
 1060+ */
 1061+ mw.getResourcePath = function( resourceName ) {
 1062+ return mw.loader.getResourcePath( resourceName );
 1063+ };
 1064+
 1065+
 1066+ /**
 1067+ * Utility Functions
 1068+ */
 1069+
 1070+ /**
 1071+ * addLoaderDialog small helper for displaying a loading dialog
 1072+ *
 1073+ * @param {String}
 1074+ * dialogHtml text Html of the loader msg
 1075+ */
 1076+ mw.addLoaderDialog = function( dialogHtml ) {
 1077+ if( typeof dialogHtml == 'undefined'){
 1078+ dialogHtml ='';
 1079+ }
 1080+ var $dialog = mw.addDialog( {
 1081+ 'title' : dialogHtml,
 1082+ 'content' : dialogHtml + '<br>' +
 1083+ $j('<div />')
 1084+ .loadingSpinner()
 1085+ .html()
 1086+ });
 1087+ return $dialog;
 1088+ };
 1089+
 1090+ /**
 1091+ * Close the loader dialog created with addLoaderDialog
 1092+ */
 1093+ mw.closeLoaderDialog = function() {
 1094+ // Make sure the dialog resource is present
 1095+ if( !mw.isset( '$j.ui.dialog' ) ) {
 1096+ return false;
 1097+ }
 1098+ // Close with timeout since jquery ui binds with timeout:
 1099+ // ui dialog line 530
 1100+ setTimeout( function(){
 1101+ $j( '#mwTempLoaderDialog' )
 1102+ .dialog( 'destroy' );
 1103+ } , 10);
 1104+ };
 1105+
 1106+ /**
 1107+ * Add a (temporary) dialog window:
 1108+ *
 1109+ * @param {Object}
 1110+ * with following keys: title: {String} Title string for the
 1111+ * dialog content: {String} to be inserted in msg box buttons:
 1112+ * {Object} A button object for the dialog Can be a string for
 1113+ * the close button any jquery.ui.dialog option
 1114+ */
 1115+ mw.addDialog = function ( options ) {
 1116+ // Remove any other dialog
 1117+ $j( '#mwTempLoaderDialog' ).remove();
 1118+
 1119+ if( !options){
 1120+ options = {};
 1121+ }
 1122+
 1123+ // Extend the default options with provided options
 1124+ var options = $j.extend({
 1125+ 'bgiframe': true,
 1126+ 'draggable': true,
 1127+ 'resizable': false,
 1128+ 'modal': true,
 1129+ 'position' : ['center', 'center']
 1130+ }, options );
 1131+
 1132+ if( ! options.title || ! options.content ){
 1133+ mw.log("Error: mwEmbed addDialog missing required options ( title, content ) ");
 1134+ return ;
 1135+ }
 1136+
 1137+ // Append the dialog div on top:
 1138+ $j( 'body' ).append(
 1139+ $j('<div />')
 1140+ .attr( {
 1141+ 'id' : "mwTempLoaderDialog",
 1142+ 'title' : options.title
 1143+ })
 1144+ .hide()
 1145+ .append( options.content )
 1146+ );
 1147+
 1148+ // Build the uiRequest
 1149+ var uiRequest = [ '$j.ui.dialog' ];
 1150+ if( options.draggable ){
 1151+ uiRequest.push( '$j.ui.mouse' );
 1152+ uiRequest.push( '$j.ui.draggable' );
 1153+ }
 1154+ if( options.resizable ){
 1155+ uiRequest.push( '$j.ui.resizable' );
 1156+ }
 1157+
 1158+ // Special button string
 1159+ if ( typeof options.buttons == 'string' ) {
 1160+ var buttonMsg = options.buttons;
 1161+ buttons = { };
 1162+ options.buttons[ buttonMsg ] = function() {
 1163+ $j( this ).dialog( 'close' );
 1164+ };
 1165+ }
 1166+
 1167+ // Load the dialog resources
 1168+ mw.load([
 1169+ [
 1170+ '$j.ui',
 1171+ '$j.widget',
 1172+ '$j.ui.mouse',
 1173+ '$j.ui.position'
 1174+ ],
 1175+ uiRequest
 1176+ ], function() {
 1177+ var $dialog = $j( '#mwTempLoaderDialog' ).show().dialog( options );
 1178+ } );
 1179+ return $j( '#mwTempLoaderDialog' );
 1180+ };
 1181+
 1182+ mw.isIphone = function(){
 1183+ return ( navigator.userAgent.indexOf('iPhone') != -1 && ! mw.isIpad() );
 1184+ };
 1185+ // Uses hack described at:
 1186+ // http://www.bdoran.co.uk/2010/07/19/detecting-the-iphone4-and-resolution-with-javascript-or-php/
 1187+ mw.isIphone4 = function(){
 1188+ return ( mw.isIphone() && ( window.devicePixelRatio && window.devicePixelRatio >= 2 ) );
 1189+ };
 1190+ mw.isIpod = function(){
 1191+ return ( navigator.userAgent.indexOf('iPod') != -1 );
 1192+ };
 1193+ mw.isIpad = function(){
 1194+ return ( navigator.userAgent.indexOf('iPad') != -1 );
 1195+ };
 1196+ // Android 2 has some restrictions vs other mobile platforms
 1197+ mw.isAndroid2 = function(){
 1198+ return ( navigator.userAgent.indexOf( 'Android 2.') != -1 );
 1199+ };
 1200+
 1201+ /**
 1202+ * Fallforward system by default prefers flash.
 1203+ *
 1204+ * This is separate from the EmbedPlayer library detection to provide
 1205+ * package loading control NOTE: should be phased out in favor of browser
 1206+ * feature detection where possible
 1207+ *
 1208+ */
 1209+ mw.isHTML5FallForwardNative = function(){
 1210+ if( mw.isMobileHTML5() ){
 1211+ return true;
 1212+ }
 1213+ // Check for url flag to force html5:
 1214+ if( document.URL.indexOf('forceMobileHTML5') != -1 ){
 1215+ return true;
 1216+ }
 1217+ // Fall forward native:
 1218+ // if the browser supports flash ( don't use html5 )
 1219+ if( mw.supportsFlash() ){
 1220+ return false;
 1221+ }
 1222+ // No flash return true if the browser supports html5 video tag with
 1223+ // basic support for canPlayType:
 1224+ if( mw.supportsHTML5() ){
 1225+ return true;
 1226+ }
 1227+
 1228+ return false;
 1229+ }
 1230+
 1231+ mw.isMobileHTML5 = function(){
 1232+ // Check for a mobile html5 user agent:
 1233+ if ( mw.isIphone() ||
 1234+ mw.isIpod() ||
 1235+ mw.isIpad() ||
 1236+ mw.isAndroid2()
 1237+ ){
 1238+ return true;
 1239+ }
 1240+ return false;
 1241+ }
 1242+ mw.supportsHTML5 = function(){
 1243+ // Blackberry is evil in its response to canPlayType calls.
 1244+ if( navigator.userAgent.indexOf('BlackBerry') != -1 ){
 1245+ return false ;
 1246+ }
 1247+ var dummyvid = document.createElement( "video" );
 1248+ if( dummyvid.canPlayType ) {
 1249+ return true;
 1250+ }
 1251+ return false;
 1252+ }
 1253+
 1254+ mw.supportsFlash = function(){
 1255+ // Check if the client does not have flash and has the video tag
 1256+ if ( navigator.mimeTypes && navigator.mimeTypes.length > 0 ) {
 1257+ for ( var i = 0; i < navigator.mimeTypes.length; i++ ) {
 1258+ var type = navigator.mimeTypes[i].type;
 1259+ var semicolonPos = type.indexOf( ';' );
 1260+ if ( semicolonPos > -1 ) {
 1261+ type = type.substr( 0, semicolonPos );
 1262+ }
 1263+ if (type == 'application/x-shockwave-flash' ) {
 1264+ // flash is installed
 1265+ return true;
 1266+ }
 1267+ }
 1268+ }
 1269+
 1270+ // for IE:
 1271+ var hasObj = true;
 1272+ if( typeof ActiveXObject != 'undefined' ){
 1273+ try {
 1274+ var obj = new ActiveXObject( 'ShockwaveFlash.ShockwaveFlash' );
 1275+ } catch ( e ) {
 1276+ hasObj = false;
 1277+ }
 1278+ if( hasObj ){
 1279+ return true;
 1280+ }
 1281+ }
 1282+ return false;
 1283+ };
 1284+ /**
 1285+ * Similar to php isset function checks if the variable exists. Does a safe
 1286+ * check of a descendant method or variable
 1287+ *
 1288+ * @param {String}
 1289+ * objectPath
 1290+ * @return {Boolean} true if objectPath exists false if objectPath is
 1291+ * undefined
 1292+ */
 1293+ mw.isset = function( objectPath ) {
 1294+ if ( !objectPath || typeof objectPath != 'string') {
 1295+ return false;
 1296+ }
 1297+ var pathSet = objectPath.split( '.' );
 1298+ var cur_path = '';
 1299+
 1300+ for ( var p = 0; p < pathSet.length; p++ ) {
 1301+ cur_path = ( cur_path == '' ) ? cur_path + pathSet[p] : cur_path + '.' + pathSet[p];
 1302+ eval( 'var ptest = typeof ( ' + cur_path + ' ); ' );
 1303+ if ( ptest == 'undefined' ) {
 1304+ return false;
 1305+ }
 1306+ }
 1307+ return true;
 1308+ };
 1309+
 1310+ /**
 1311+ * Wait for a object to be defined and the call the callback
 1312+ *
 1313+ * @param {Object}
 1314+ * objectName Name of object to be defined
 1315+ * @param {Function}
 1316+ * callback Function to call once object is defined
 1317+ * @param {Null}
 1318+ * callNumber Used internally to keep track of number of times
 1319+ * waitForObject has been called
 1320+ */
 1321+ var waitTime = 1200; // About 30 seconds
 1322+ mw.waitForObject = function( objectName, callback, _callNumber) {
 1323+ // mw.log( 'waitForObject: ' + objectName + ' cn: ' + _callNumber);
 1324+
 1325+ // Increment callNumber:
 1326+ if( !_callNumber ) {
 1327+ _callNumber = 1;
 1328+ } else {
 1329+ _callNumber++;
 1330+ }
 1331+
 1332+ if( _callNumber > waitTime ) {
 1333+ mw.log( "Error: waiting for object: " + objectName + ' timeout ' );
 1334+ callback( false );
 1335+ return ;
 1336+ }
 1337+
 1338+ // If the object is defined ( or we are done loading from a callback )
 1339+ if ( mw.isset( objectName ) || mwLoadDoneCB[ objectName ] == 'done' ) {
 1340+ callback( objectName );
 1341+ }else{
 1342+ setTimeout( function( ) {
 1343+ mw.waitForObject( objectName, callback, _callNumber);
 1344+ }, 25);
 1345+ }
 1346+ };
 1347+
 1348+ /**
 1349+ * Check if an object is empty or if its an empty string.
 1350+ *
 1351+ * @param {Object}
 1352+ * object Object to be checked
 1353+ */
 1354+ mw.isEmpty = function( object ) {
 1355+ if( typeof object == 'string' ) {
 1356+ if( object == '' ) return true;
 1357+ // Non empty string:
 1358+ return false;
 1359+ }
 1360+
 1361+ // If an array check length:
 1362+ if( Object.prototype.toString.call( object ) === "[object Array]"
 1363+ && object.length == 0 ) {
 1364+ return true;
 1365+ }
 1366+
 1367+ // Else check as an object:
 1368+ for( var i in object ) { return false; }
 1369+
 1370+ // Else object is empty:
 1371+ return true;
 1372+ };
 1373+
 1374+ /**
 1375+ * Log a string msg to the console
 1376+ *
 1377+ * all mw.log statements will be removed on minification so lots of mw.log
 1378+ * calls will not impact performance in non debug mode
 1379+ *
 1380+ * @param {String}
 1381+ * string String to output to console
 1382+ */
 1383+ mw.log = function( string ) {
 1384+ // Add any prepend debug strings if necessary
 1385+ if ( mw.getConfig( 'Mw.LogPrepend' ) ){
 1386+ string = mw.getConfig( 'Mw.LogPrepend' ) + string;
 1387+ }
 1388+ // To debug stack size ( useful for iPad / safari that have a 100 call
 1389+ // stack limit
 1390+ // string = mw.getCallStack().length -1 + ' : ' + string;
 1391+
 1392+ if ( window.console ) {
 1393+ window.console.log( string );
 1394+ } else {
 1395+ /**
 1396+ * Old IE and non-Firebug debug: ( commented out for now )
 1397+ */
 1398+
 1399+ /*
 1400+ * var log_elm = document.getElementById('mv_js_log'); if(!log_elm) {
 1401+ * document.getElementsByTagName("body")[0].innerHTML += '<div ' +
 1402+ * 'style="position:absolute;z-index:500;bottom:0px;left:0px;right:0px;height:200px;">' + '<textarea
 1403+ * id="mv_js_log" cols="120" rows="12"></textarea>' + '</div>'; }
 1404+ * var log_elm = document.getElementById('mv_js_log'); if(log_elm) {
 1405+ * log_elm.value+=string+"\n"; // scroll to bottom:
 1406+ * log_elm.scrollTop = log_elm.scrollHeight; }
 1407+ */
 1408+ }
 1409+ };
 1410+ mw.getCallStack = function(){
 1411+ var stringifyArguments = function(args) {
 1412+ for (var i = 0; i < args.length; ++i) {
 1413+ var arg = args[i];
 1414+ if (arg === undefined) {
 1415+ args[i] = 'undefined';
 1416+ } else if (arg === null) {
 1417+ args[i] = 'null';
 1418+ } else if (arg.constructor) {
 1419+ if (arg.constructor === Array) {
 1420+ if (arg.length < 3) {
 1421+ args[i] = '[' + stringifyArguments(arg) + ']';
 1422+ } else {
 1423+ args[i] = '[' + stringifyArguments(Array.prototype.slice.call(arg, 0, 1)) + '...' + stringifyArguments(Array.prototype.slice.call(arg, -1)) + ']';
 1424+ }
 1425+ } else if (arg.constructor === Object) {
 1426+ args[i] = '#object';
 1427+ } else if (arg.constructor === Function) {
 1428+ args[i] = '#function';
 1429+ } else if (arg.constructor === String) {
 1430+ args[i] = '"' + arg + '"';
 1431+ }
 1432+ }
 1433+ }
 1434+ return args.join(',');
 1435+ };
 1436+ var getStack = function(curr){
 1437+ var ANON = '{anonymous}', fnRE = /function\s*([\w\-$]+)?\s*\(/i,
 1438+ stack = [], fn, args, maxStackSize = 100;
 1439+
 1440+ while (curr && stack.length < maxStackSize) {
 1441+ fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON;
 1442+ args = Array.prototype.slice.call(curr['arguments']);
 1443+ stack[stack.length] = fn + '(' + stringifyArguments(args) + ')';
 1444+ curr = curr.caller;
 1445+ }
 1446+ return stack;
 1447+ }
 1448+ // Add stack size ( iPad has 100 stack size limit )
 1449+ var stack = getStack( arguments.callee );
 1450+ return stack;
 1451+ }
 1452+
 1453+ // Setup the local mwOnLoadFunctions array:
 1454+ var mwOnLoadFunctions = [];
 1455+
 1456+ // mw Ready flag ( set once mwEmbed is ready )
 1457+ var mwReadyFlag = false;
 1458+
 1459+ /**
 1460+ * Enables load hooks to run once mwEmbeed is "ready" Will ensure jQuery is
 1461+ * available, is in the $j namespace and mw interfaces and configuration has
 1462+ * been loaded and applied
 1463+ *
 1464+ * This is different from jQuery(document).ready() ( jQuery ready is not
 1465+ * friendly with dynamic includes and not friendly with core interface
 1466+ * asynchronous build out. )
 1467+ *
 1468+ * @param {Function}
 1469+ * callback Function to run once DOM and jQuery are ready
 1470+ */
 1471+ mw.ready = function( callback ) {
 1472+ if( mwReadyFlag === false ) {
 1473+ // Add the callbcak to the onLoad function stack
 1474+ mwOnLoadFunctions.push ( callback );
 1475+ } else {
 1476+ // If mwReadyFlag is already "true" issue the callback directly:
 1477+ callback();
 1478+ }
 1479+ };
 1480+
 1481+ /**
 1482+ * Runs all the queued functions called by mwEmbedSetup
 1483+ */
 1484+ mw.runReadyFunctions = function ( ) {
 1485+ mw.log('mw.runReadyFunctions: ' + mwOnLoadFunctions.length );
 1486+ // Run any pre-setup ready functions
 1487+ while( preMwEmbedReady.length ){
 1488+ preMwEmbedReady.shift()();
 1489+ }
 1490+ // Run all the queued functions:
 1491+ while( mwOnLoadFunctions.length ) {
 1492+ mwOnLoadFunctions.shift()();
 1493+ }
 1494+ // Sets mwReadyFlag to true so that future mw.ready run the
 1495+ // callback directly
 1496+ mwReadyFlag = true;
 1497+
 1498+ // Once we have run all the queued functions
 1499+ setTimeout(function(){
 1500+ mw.loader.runModuleLoadQueue();
 1501+ },1);
 1502+ };
 1503+
 1504+
 1505+ /**
 1506+ * Wrapper for jQuery getScript, Uses the scriptLoader if enabled
 1507+ *
 1508+ *
 1509+ * @param {String}
 1510+ * scriptRequest The requested path or resourceNames for the
 1511+ * scriptLoader
 1512+ * @param {Function}
 1513+ * callback Function to call once script is loaded
 1514+ */
 1515+ mw.getScript = function( scriptRequest, callback ) {
 1516+ // mw.log( "mw.getScript::" + scriptRequest );
 1517+ // Setup the local scope callback instace
 1518+ var myCallback = function(){
 1519+ if( callback ) {
 1520+ callback( scriptRequest );
 1521+ }
 1522+ };
 1523+ // Set the base url based scriptLoader availability & type of
 1524+ // scriptRequest
 1525+ // ( presently script loader only handles "classes" not relative urls:
 1526+ var scriptLoaderPath = mw.getResourceLoaderPath();
 1527+
 1528+ // Check if its a resource name, ( ie does not start with "/" and does
 1529+ // not include ://
 1530+ var isResourceName = ( scriptRequest.indexOf('://') == -1 && scriptRequest.indexOf('/') !== 0 )? true : false;
 1531+
 1532+ var ext = scriptRequest.substr( scriptRequest.lastIndexOf( '.' ), 4 ).toLowerCase();
 1533+ var isCssFile = ( ext == '.css') ? true : false ;
 1534+
 1535+ if( scriptLoaderPath && isResourceName ) {
 1536+ url = scriptLoaderPath + '?class=' + scriptRequest ;
 1537+ } else {
 1538+ // Add the mwEmbed path if a relative path request
 1539+ url = ( isResourceName ) ? mw.getMwEmbedPath() : '';
 1540+ url+= scriptRequest;
 1541+ }
 1542+
 1543+ // Add on the request parameters to the url:
 1544+ url += ( url.indexOf( '?' ) == -1 )? '?' : '&';
 1545+ url += mw.getUrlParam();
 1546+
 1547+ // Only log sciprts ( Css is logged via "add css" )
 1548+ if( !isCssFile ){
 1549+ mw.log( 'mw.getScript: ' + url );
 1550+ }
 1551+
 1552+ // If jQuery is available and debug is off load the script via jQuery
 1553+ // ( will use XHR if on same domain )
 1554+ if( mw.isset( 'window.jQuery' )
 1555+ && mw.getConfig( 'debug' ) === false
 1556+ && typeof $j != 'undefined'
 1557+ && mw.parseUri( url ).protocal != 'file'
 1558+ && !isCssFile )
 1559+ {
 1560+ $j.getScript( url, myCallback);
 1561+ return ;
 1562+ }
 1563+
 1564+ /**
 1565+ * No jQuery OR In debug mode OR Is css file :: inject the script
 1566+ * instead of doing an XHR eval
 1567+ */
 1568+
 1569+ // load style sheet directly if requested loading css
 1570+ if( isCssFile ){
 1571+ mw.getStyleSheet( url, myCallback);
 1572+ return ;
 1573+ }
 1574+
 1575+ // Load and bind manually: ( copied from jQuery ajax function )
 1576+ var head = document.getElementsByTagName("head")[ 0 ];
 1577+ var script = document.createElement("script");
 1578+ script.setAttribute( 'src', url );
 1579+
 1580+ // Attach handlers ( if using script loader it issues onDone callback as
 1581+ // well )
 1582+ script.onload = script.onreadystatechange = function() {
 1583+ if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") {
 1584+ myCallback();
 1585+ }
 1586+ };
 1587+ // mw.log(" append script: " + script.src );
 1588+ // Append the script to the DOM:
 1589+ head.appendChild( script );
 1590+ };
 1591+
 1592+ /**
 1593+ * Add a style sheet string to the document head
 1594+ *
 1595+ * @param {String}
 1596+ * cssResourceName Name of style sheet that has been defined
 1597+ * @param {String}
 1598+ * cssString Css Payload to be added to head of document
 1599+ */
 1600+ mw.addStyleString = function( cssResourceName, cssString ) {
 1601+ if( mw.style[ cssResourceName ] ) {
 1602+ mw.log(" Style: ( " + cssResourceName + ' ) already set' );
 1603+ return true;
 1604+ }
 1605+ // Set the style to true ( to not request it again )
 1606+ mw.style[ cssResourceName ] = true;
 1607+ // Add the spinner directly ( without jQuery in case we have to
 1608+ // dynamically load jQuery )
 1609+ mw.log( 'Adding style:' + cssResourceName + " to dom " );
 1610+ var styleNode = document.createElement('style');
 1611+ styleNode.type = "text/css";
 1612+ // Use cssText or createTextNode depending on browser:
 1613+ if( ( window.attachEvent && !window.opera ) ) {
 1614+ styleNode.styleSheet.cssText = cssString;
 1615+ } else {
 1616+ var styleText = document.createTextNode( cssString );
 1617+ styleNode.appendChild( styleText );
 1618+ }
 1619+ var head = document.getElementsByTagName("head")[0];
 1620+ head.appendChild( styleNode );
 1621+ };
 1622+
 1623+ /**
 1624+ * Get a style sheet and append the style sheet to the DOM
 1625+ *
 1626+ * @param {Mixed}
 1627+ * {String} url Url of the style sheet to be loaded {Function}
 1628+ * callback Function called once sheet is ready
 1629+ */
 1630+ mw.getStyleSheet = function( url , callback) {
 1631+ // Add URL params ( if not already included )
 1632+ if ( url.indexOf( '?' ) == -1 ) {
 1633+ url += '?' + mw.getUrlParam();
 1634+ }
 1635+
 1636+ // Check if style sheet is already included:
 1637+ var foundSheet = false;
 1638+ $j( 'link' ).each( function() {
 1639+ var currentSheet = $j( this) .attr( 'href' );
 1640+ var sheetParts = currentSheet.split('?');
 1641+ var urlParts = url.split('?');
 1642+ // if the base url's match check the parameters:
 1643+ if( sheetParts[0] == urlParts[0] && sheetParts[1]) {
 1644+ // Check if url params match ( sort to do string compare )
 1645+ if( sheetParts[1].split( '&' ).sort().join('') ==
 1646+ urlParts[1].split('&').sort().join('') ) {
 1647+ foundSheet = true;
 1648+ }
 1649+ }
 1650+ } );
 1651+ if( foundSheet ) {
 1652+ mw.log( 'skiped sheet: ' + url);
 1653+ if( callback) {
 1654+ callback();
 1655+ }
 1656+ return ;
 1657+ }
 1658+
 1659+ mw.log( ' add css: ' + url );
 1660+ $j( 'head' ).append(
 1661+ $j('<link />').attr( {
 1662+ 'rel' : 'stylesheet',
 1663+ 'type' : 'text/css',
 1664+ 'href' : url
 1665+ } )
 1666+ );
 1667+ // No easy way to check css "onLoad" attribute
 1668+ // In production sheets are loaded via resource loader and fire the
 1669+ // onDone function call.
 1670+ if( callback ) {
 1671+ callback();
 1672+ }
 1673+ };
 1674+
 1675+ mw.getRelativeMwEmbedPath = function(){
 1676+ return mw.getMwEmbedPath(true);
 1677+ };
 1678+ /**
 1679+ * Get the path to the mwEmbed folder
 1680+ */
 1681+ mw.getMwEmbedPath = function( relativePath ) {
 1682+ // Get mwEmbed src:
 1683+ var src = mw.getMwEmbedSrc();
 1684+ var mwpath = null;
 1685+
 1686+ // Check for direct include of the mwEmbed.js
 1687+ if ( src.indexOf( 'mwEmbed.js' ) !== -1 ) {
 1688+ alert( 'Direct Refrece to mwEmbed is no longer suported, please update to ResourceLoader.php?class=window.jQuery,mwEmbed& instead');
 1689+ mwpath = src.substr( 0, src.indexOf( 'mwEmbed.js' ) );
 1690+ }
 1691+
 1692+ // Check for scriptLoader include of mwEmbed:
 1693+ if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 ) {
 1694+ // Script loader is in the root of MediaWiki, Include the default
 1695+ // mwEmbed extension path:
 1696+ mwpath = src.substr( 0, src.indexOf( 'mwResourceLoader.php' ) ) + mw.getConfig( 'mediaWikiEmbedPath' );
 1697+ }
 1698+
 1699+ // resource loader has ResourceLoader name when local:
 1700+ if( src.indexOf( 'ResourceLoader.php' ) !== -1 ) {
 1701+ mwpath = src.substr( 0, src.indexOf( 'ResourceLoader.php' ) );
 1702+ }
 1703+
 1704+ // For static packages mwEmbed packages start with: "mwEmbed-"
 1705+ if( src.indexOf( 'mwEmbed-' ) !== -1 && src.indexOf( '-static' ) !== -1 ) {
 1706+ mwpath = src.substr( 0, src.indexOf( 'mwEmbed-' ) );
 1707+ }
 1708+
 1709+ // Error out if we could not get the path:
 1710+ if( mwpath === null ) {
 1711+ mw.log( "Error could not get mwEmbed path " );
 1712+ return ;
 1713+ }
 1714+
 1715+ // Update the cached var with the absolute path:
 1716+ if( !relativePath ){
 1717+ mwpath = mw.absoluteUrl( mwpath ) ;
 1718+ }
 1719+ return mwpath;
 1720+ };
 1721+
 1722+ /**
 1723+ * Get Script loader path
 1724+ *
 1725+ * @returns {String}|{Boolean} Url of the scriptLodaer false if the
 1726+ * scriptLoader is not used
 1727+ */
 1728+ mw.getResourceLoaderPath = function( ) {
 1729+ var src = mw.getMwEmbedSrc();
 1730+ if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 ||
 1731+ src.indexOf( 'ResourceLoader.php' ) !== -1 )
 1732+ {
 1733+ // Return just the script part of the url
 1734+ return src.split('?')[0];
 1735+ }
 1736+ return false;
 1737+ };
 1738+ /**
 1739+ * Given a float number of seconds, returns npt format response. ( ignore
 1740+ * days for now )
 1741+ *
 1742+ * @param {Float}
 1743+ * sec Seconds
 1744+ * @param {Boolean}
 1745+ * verbose If hours and milliseconds should padded be displayed.
 1746+ * @return {Float} String npt format
 1747+ */
 1748+ mw.seconds2npt = function( sec, verbose ) {
 1749+ if ( isNaN( sec ) ) {
 1750+ mw.log("Warning: trying to get npt time on NaN:" + sec);
 1751+ return '0:00:00';
 1752+ }
 1753+
 1754+ var tm = mw.seconds2Measurements( sec );
 1755+
 1756+ // Round the number of seconds to the required number of significant
 1757+ // digits
 1758+ if ( verbose ) {
 1759+ tm.seconds = Math.round( tm.seconds * 1000 ) / 1000;
 1760+ } else {
 1761+ tm.seconds = Math.round( tm.seconds );
 1762+ }
 1763+ if ( tm.seconds < 10 ){
 1764+ tm.seconds = '0' + tm.seconds;
 1765+ }
 1766+ if( tm.hours == 0 && !verbose ){
 1767+ hoursStr = '';
 1768+ } else {
 1769+ if ( tm.minutes < 10 && verbose) {
 1770+ tm.minutes = '0' + tm.minutes;
 1771+ }
 1772+
 1773+ if( tm.hours < 10 && verbose){
 1774+ tm.hours = '0' + tm.hours;
 1775+ }
 1776+
 1777+ hoursStr = tm.hours + ':';
 1778+ }
 1779+ return hoursStr + tm.minutes + ":" + tm.seconds;
 1780+ };
 1781+ /**
 1782+ * Given seconds return array with 'days', 'hours', 'min', 'seconds'
 1783+ *
 1784+ * @param {float}
 1785+ * sec Seconds to be converted into time measurements
 1786+ */
 1787+ mw.seconds2Measurements = function ( sec ){
 1788+ var tm = {};
 1789+ tm.days = Math.floor( sec / ( 3600 * 24 ) );
 1790+ tm.hours = Math.floor( sec / 3600 );
 1791+ tm.minutes = Math.floor( ( sec / 60 ) % 60 );
 1792+ tm.seconds = sec % 60;
 1793+ return tm;
 1794+ };
 1795+
 1796+ /**
 1797+ * Given a float number of seconds, returns npt format response. ( ignore
 1798+ * days for now )
 1799+ *
 1800+ * @param {Float}
 1801+ * sec Seconds
 1802+ * @param {Boolean}
 1803+ * verbose If hours and milliseconds should padded be displayed.
 1804+ * @return {Float} String npt format
 1805+ */
 1806+ mw.npt2seconds = function ( npt_str ) {
 1807+ if ( !npt_str ) {
 1808+ // mw.log('npt2seconds:not valid ntp:'+ntp);
 1809+ return false;
 1810+ }
 1811+ // Strip {npt:}01:02:20 or 32{s} from time if present
 1812+ npt_str = npt_str.replace( /npt:|s/g, '' );
 1813+
 1814+ var hour = 0;
 1815+ var min = 0;
 1816+ var sec = 0;
 1817+
 1818+ times = npt_str.split( ':' );
 1819+ if ( times.length == 3 ) {
 1820+ sec = times[2];
 1821+ min = times[1];
 1822+ hour = times[0];
 1823+ } else if ( times.length == 2 ) {
 1824+ sec = times[1];
 1825+ min = times[0];
 1826+ } else {
 1827+ sec = times[0];
 1828+ }
 1829+ // Sometimes a comma is used instead of period for ms
 1830+ sec = sec.replace( /,\s?/, '.' );
 1831+ // Return seconds float
 1832+ return parseInt( hour * 3600 ) + parseInt( min * 60 ) + parseFloat( sec );
 1833+ };
 1834+
 1835+ // Local mwEmbedSrc variable ( for cache of mw.getMwEmbedSrc )
 1836+ var mwEmbedSrc = null;
 1837+
 1838+ /**
 1839+ * Gets the mwEmbed script src attribute
 1840+ */
 1841+ mw.getMwEmbedSrc = function() {
 1842+ if ( mwEmbedSrc ) {
 1843+ return mwEmbedSrc;
 1844+ }
 1845+
 1846+ // Get all the javascript includes:
 1847+ var js_elements = document.getElementsByTagName( "script" );
 1848+ for ( var i = 0; i < js_elements.length; i++ ) {
 1849+ // Check for mwEmbed.js and/or script loader
 1850+ var src = js_elements[i].getAttribute( "src" );
 1851+ if ( src ) {
 1852+ if ( // Check for mwEmbed.js ( debug mode )
 1853+ ( src.indexOf( 'mwEmbed.js' ) !== -1 && src.indexOf( 'MediaWiki:Gadget') == -1 )
 1854+ || // Check for resource loader
 1855+ (
 1856+ ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || src.indexOf( 'ResourceLoader.php' ) !== -1 )
 1857+ &&
 1858+ src.indexOf( 'mwEmbed' ) !== -1
 1859+ )
 1860+ || // Check for static mwEmbed package
 1861+ ( src.indexOf( 'mwEmbed' ) !== -1 && src.indexOf( 'static' ) !== -1 )
 1862+ ) {
 1863+ mwEmbedSrc = src;
 1864+ return mwEmbedSrc;
 1865+ }
 1866+ }
 1867+ }
 1868+ mw.log( 'Error: getMwEmbedSrc failed to get script path' );
 1869+ return false;
 1870+ };
 1871+
 1872+ // Local mwUrlParam variable ( for cache of mw.getUrlParam )
 1873+ var mwUrlParam = null;
 1874+
 1875+ /**
 1876+ * Get URL Parameters per parameters in the host script include
 1877+ */
 1878+ mw.getUrlParam = function() {
 1879+ if ( mwUrlParam ) {
 1880+ return mwUrlParam;
 1881+ }
 1882+
 1883+ var mwEmbedSrc = mw.getMwEmbedSrc();
 1884+ var req_param = '';
 1885+
 1886+ // If we already have a URI, add it to the param request:
 1887+ var urid = mw.parseUri( mwEmbedSrc ).queryKey['urid'];
 1888+
 1889+ // If we're in debug mode, get a fresh unique request key and pass on
 1890+ // "debug" param
 1891+ if ( mw.parseUri( mwEmbedSrc ).queryKey['debug'] == 'true' ) {
 1892+ mw.setConfig( 'debug', true );
 1893+ var d = new Date();
 1894+ req_param += 'urid=' + d.getTime() + '&debug=true';
 1895+
 1896+ } else if ( urid ) {
 1897+ // Just pass on the existing urid:
 1898+ req_param += 'urid=' + urid;
 1899+ } else {
 1900+ // Otherwise, Use the mwEmbed version
 1901+ req_param += 'urid=' + mw.version;
 1902+ }
 1903+
 1904+ // Add the language param if present:
 1905+ var langKey = mw.parseUri( mwEmbedSrc ).queryKey['uselang'];
 1906+ if ( langKey )
 1907+ req_param += '&uselang=' + langKey;
 1908+
 1909+ // Update the local cache and return the value
 1910+ mwUrlParam = req_param;
 1911+ return mwUrlParam;
 1912+ };
 1913+
 1914+ /**
 1915+ * Replace url parameters via newParams key value pairs
 1916+ *
 1917+ * @param {String}
 1918+ * url Source url to be updated
 1919+ * @param {Object}
 1920+ * newParams key, value paris to swap in
 1921+ * @return {String} the updated url
 1922+ */
 1923+ mw.replaceUrlParams = function( url, newParams ) {
 1924+ var parsedUrl = mw.parseUri( url );
 1925+
 1926+ if ( parsedUrl.protocol != '' ) {
 1927+ var new_url = parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.path + '?';
 1928+ } else {
 1929+ var new_url = parsedUrl.path + '?';
 1930+ }
 1931+
 1932+ // Merge new params:
 1933+ for( var key in newParams ) {
 1934+ parsedUrl.queryKey[ key ] = newParams[ key ];
 1935+ }
 1936+
 1937+ // Output to new_url
 1938+ var amp = '';
 1939+ for ( var key in parsedUrl.queryKey ) {
 1940+ var val = parsedUrl.queryKey[ key ];
 1941+ new_url += amp + key + '=' + val;
 1942+ amp = '&';
 1943+ }
 1944+ return new_url;
 1945+ };
 1946+
 1947+ /**
 1948+ * parseUri 1.2.2 (c) Steven Levithan <stevenlevithan.com> MIT License
 1949+ */
 1950+ mw.parseUri = function (str) {
 1951+ var o = mw.parseUri.options,
 1952+ m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
 1953+ uri = {},
 1954+ i = 14;
 1955+
 1956+ while (i--) uri[o.key[i]] = m[i] || "";
 1957+
 1958+ uri[o.q.name] = {};
 1959+ uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
 1960+ if ($1) uri[o.q.name][$1] = $2;
 1961+ });
 1962+
 1963+ return uri;
 1964+ };
 1965+
 1966+ /**
 1967+ * Parse URI function
 1968+ *
 1969+ * For documentation on its usage see:
 1970+ * http://stevenlevithan.com/demo/parseuri/js/
 1971+ */
 1972+ mw.parseUri.options = {
 1973+ strictMode: false,
 1974+ key: ["source", "protocol", "authority", "userInfo", "user", "password", "host",
 1975+ "port", "relative", "path", "directory", "file", "query", "anchor"],
 1976+ q: {
 1977+ name: "queryKey",
 1978+ parser: /(?:^|&)([^&=]*)=?([^&]*)/g
 1979+ },
 1980+ parser: {
 1981+ strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
 1982+ loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
 1983+ }
 1984+ };
 1985+
 1986+ /**
 1987+ * getAbsoluteUrl takes a src and returns the absolute location given the
 1988+ * document.URL or a contextUrl param
 1989+ *
 1990+ * @param {String}
 1991+ * src path or url
 1992+ * @param {String}
 1993+ * contextUrl The domain / context for creating an absolute url
 1994+ * from a relative path
 1995+ * @return {String} absolute url
 1996+ */
 1997+mw.absoluteUrl = function( src, contextUrl ) {
 1998+
 1999+ var parsedSrc = mw.parseUri( src );
 2000+
 2001+ // Source is already absolute return:
 2002+ if( parsedSrc.protocol != '') {
 2003+ return src;
 2004+ }
 2005+
 2006+ // Get parent Url location the context URL
 2007+ if( !contextUrl ) {
 2008+ contextUrl = document.URL;
 2009+ }
 2010+ var parsedUrl = mw.parseUri( contextUrl );
 2011+
 2012+ // Check for IE local file that does not flip the slashes
 2013+ if( parsedUrl.directory == '' && parsedUrl.protocol == 'file' ){
 2014+ // pop off the file
 2015+ var fileUrl = contextUrl.split( '\\');
 2016+ fileUrl.pop();
 2017+ return fileUrl.join('\\') + '\\' + src;
 2018+ }
 2019+
 2020+ // Check for leading slash:
 2021+ if( src.indexOf( '/' ) === 0 ) {
 2022+ return parsedUrl.protocol + '://' + parsedUrl.authority + src;
 2023+ }else{
 2024+ return parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.directory + src;
 2025+ }
 2026+ };
 2027+ /**
 2028+ * Check if a given source string is likely a url
 2029+ *
 2030+ * @return {boolean} true if a url false if a string
 2031+ */
 2032+ mw.isUrl = function( src ){
 2033+ var parsedSrc = mw.parseUri( src );
 2034+ // if the url is just a string source and host will match
 2035+ return ( parsedSrc.host != parsedSrc.source );
 2036+ };
 2037+
 2038+ /**
 2039+ * Escape quotes in a text string
 2040+ *
 2041+ * @param {String}
 2042+ * text String to be escaped
 2043+ * @return {string} escaped text string
 2044+ */
 2045+ mw.escapeQuotes = function( text ) {
 2046+ var re = new RegExp("'","g");
 2047+ text = text.replace(re,"\\'");
 2048+ re = new RegExp("\\n","g");
 2049+ text = text.replace(re,"\\n");
 2050+ return mw.escapeQuotesHTML(text);
 2051+ };
 2052+
 2053+ /**
 2054+ * Escape an HTML text string
 2055+ *
 2056+ * @param {String}
 2057+ * text String to be escaped
 2058+ * @return {string} escaped text html string
 2059+ */
 2060+ mw.escapeQuotesHTML = function( text ) {
 2061+ var replaceMap = {
 2062+ "&" : "&amp;",
 2063+ '"' : "&quot;",
 2064+ '<' : "&lt;",
 2065+ '>' : "&gt;"
 2066+ };
 2067+ for( var i in replaceMap ){
 2068+ text = text.split(i).join( replaceMap[i]);
 2069+ }
 2070+ return text;
 2071+ };
 2072+
 2073+
 2074+ // Array of setup functions
 2075+ var mwSetupFunctions = [];
 2076+
 2077+ /**
 2078+ * Add a function to be run during setup ( prior to mw.ready) this is useful
 2079+ * for building out interfaces that should be ready before mw.ready is
 2080+ * called.
 2081+ *
 2082+ * @param {callback}
 2083+ * Function Callback function must accept a ready function
 2084+ * callback to be called once setup is done
 2085+ */
 2086+ mw.addSetupHook = function( callback ) {
 2087+ mwSetupFunctions.push ( callback ) ;
 2088+ };
 2089+
 2090+ /**
 2091+ * One time "setup" for mwEmbed run onDomReady ( so calls to setConfg apply
 2092+ * to setup )
 2093+ */
 2094+ // Flag to ensure setup is only run once:
 2095+ var mwSetupFlag = false;
 2096+ mw.setupMwEmbed = function ( ) {
 2097+ // Only run the setup once:
 2098+ if( mwSetupFlag ) {
 2099+ return ;
 2100+ }
 2101+ mwSetupFlag = true;
 2102+
 2103+ mw.log( 'mw:setupMwEmbed SRC:: ' + mw.getMwEmbedSrc() );
 2104+
 2105+ // Check core mwEmbed loader.js file ( to get configuration and paths )
 2106+ mw.checkCoreLoaderFile( function(){
 2107+ // Make sure we have jQuery
 2108+ mw.load( 'window.jQuery', function() {
 2109+
 2110+ // Add jQuery to $j var.
 2111+ if ( ! window[ '$j' ] ) {
 2112+ window[ '$j' ] = jQuery.noConflict();
 2113+ }
 2114+
 2115+ // Set up mvEmbed utility jQuery bindings
 2116+ mw.dojQueryBindings();
 2117+
 2118+ // Setup user config:
 2119+ mw.setupUserConfig( function(){
 2120+ // Get module loader.js, and language files
 2121+ // ( will hit callback directly if set via resource loader )
 2122+ mw.checkModuleLoaderFiles( function() {
 2123+
 2124+ // Set the User language
 2125+ if( typeof wgUserLanguage != 'undefined' && mw.isValidLang( wgUserLanguage) ) {
 2126+ mw.setConfig( 'userLanguage', wgUserLanguage );
 2127+ }else{
 2128+ // Grab it from the included url
 2129+ var langKey = mw.parseUri( mw.getMwEmbedSrc() ).queryKey['uselang'];
 2130+ if ( langKey && mw.isValidLang( langKey ) ) {
 2131+ mw.setConfig( 'userLanguage', langKey);
 2132+ }
 2133+ }
 2134+
 2135+ // Update the image path
 2136+ mw.setConfig( 'imagesPath', mw.getMwEmbedPath() + 'skins/common/images/' );
 2137+
 2138+ // Set up AJAX to not send dynamic URLs for loading
 2139+ // scripts
 2140+ $j.ajaxSetup( {
 2141+ cache: true
 2142+ } );
 2143+
 2144+ // Update the magic keywords
 2145+ mw.Language.magicSetup();
 2146+
 2147+
 2148+ // Special Hack for conditional jquery ui inclusion (
 2149+ // once
 2150+ // Usability extension
 2151+ // registers the jquery.ui skin in mw.style
 2152+ if( mw.hasJQueryUiCss() ){
 2153+ mw.style[ 'ui_' + mw.getConfig( 'jQueryUISkin' ) ] = true;
 2154+ }
 2155+
 2156+
 2157+ // Make sure style sheets are loaded:
 2158+ mw.load( ['mw.style.mwCommon'] , function(){
 2159+ // Run all the setup function hooks
 2160+ // NOTE: setup functions are added via addSetupHook
 2161+ // calls
 2162+ // and must include a callback.
 2163+ //
 2164+ // Once complete we can run .ready() queued
 2165+ // functions
 2166+ function runSetupFunctions() {
 2167+ if( mwSetupFunctions.length ) {
 2168+ mwSetupFunctions.shift()( function() {
 2169+ runSetupFunctions();
 2170+ } );
 2171+ }else{
 2172+ mw.runReadyFunctions();
 2173+ }
 2174+ }
 2175+ runSetupFunctions();
 2176+ } );
 2177+
 2178+ } );
 2179+ });
 2180+ });
 2181+ });
 2182+ };
 2183+
 2184+ /**
 2185+ * Checks for jquery ui css by name jquery-ui-1.7.2.css NOTE: this is a hack
 2186+ * for usability jquery-ui in the future usability should register a
 2187+ * resource in mw.skin
 2188+ *
 2189+ * @return true if found, return false if not found
 2190+ */
 2191+ mw.hasJQueryUiCss = function(){
 2192+ var hasUiCss = false;
 2193+ var cssStyleSheetNames = ['jquery-ui-1.7.2.css', 'jquery-ui.css'];
 2194+ // Load the jQuery ui skin if usability skin not set
 2195+ $j( 'link' ).each( function( na, linkNode ){
 2196+ $j.each( cssStyleSheetNames, function(inx, sheetName ){
 2197+ if( $j( linkNode ).attr( 'href' ).indexOf( sheetName ) != -1 ){
 2198+ hasUiCss = true;
 2199+ return true;
 2200+ }
 2201+ });
 2202+ } );
 2203+ // Check all the "style" nodes for @import for sheet name
 2204+ // xxx Note: we could do this a bit cleaner with regEx
 2205+ $j( 'style' ).each( function( na, styleNode ){
 2206+ $j.each( cssStyleSheetNames, function(inx, sheetName ){
 2207+ if( $j( styleNode ).text().indexOf( '@import' ) != -1
 2208+ &&
 2209+ $j( styleNode ).text().indexOf( sheetName ) != -1 )
 2210+ {
 2211+ hasUiCss=true;
 2212+ return true;
 2213+ }
 2214+ });
 2215+ });
 2216+ return hasUiCss;
 2217+ };
 2218+
 2219+ /**
 2220+ * Loads the core mwEmbed "loader.js" file config
 2221+ *
 2222+ * NOTE: if using the ScriptLoader all the loaders and localization
 2223+ * converters are included automatically
 2224+ *
 2225+ * @param {Function}
 2226+ * callback Function called once core loader file is loaded
 2227+ */
 2228+ mw.checkCoreLoaderFile = function( callback ) {
 2229+ // Check if we are using scriptloader ( handles loader include
 2230+ // automatically )
 2231+ if( mw.getResourceLoaderPath() ) {
 2232+ callback();
 2233+ return ;
 2234+ }
 2235+
 2236+ // Check if we are using a static package ( mwEmbed path includes
 2237+ // -static )
 2238+ if( mw.isStaticPackge() ){
 2239+ callback();
 2240+ return ;
 2241+ }
 2242+
 2243+ // Add the Core loader to the request
 2244+ // The follow code is ONLY RUN in debug / raw file mode
 2245+ mw.load( 'loader.js', callback );
 2246+ };
 2247+
 2248+ /**
 2249+ * Checks if the javascript is a static package ( not using resource loader )
 2250+ *
 2251+ * @return {boolean} true the included script is static false the included
 2252+ * script
 2253+ */
 2254+ mw.isStaticPackge = function(){
 2255+ var src = mw.getMwEmbedSrc();
 2256+ if( src.indexOf('-static') !== -1 ){
 2257+ return true;
 2258+ }
 2259+ return false;
 2260+ };
 2261+
 2262+ /**
 2263+ * Check for resource loader module loaders, and localization files
 2264+ *
 2265+ * NOTE: if using the ScriptLoader all the loaders and localization
 2266+ * converters are included automatically.
 2267+ */
 2268+ mw.checkModuleLoaderFiles = function( callback ) {
 2269+ mw.log( 'doLoaderCheck::' );
 2270+
 2271+ // Check if we are using scriptloader ( handles loader include
 2272+ // automatically )
 2273+ // Or if mwEmbed is a static package ( all resources are already loaded
 2274+ // )
 2275+ if( mw.getResourceLoaderPath() || mw.isStaticPackge() ) {
 2276+ callback();
 2277+ return ;
 2278+ }
 2279+
 2280+ // Load the configured modules / components
 2281+ // The follow code is ONLY RUN in debug / raw file mode
 2282+ var loaderRequest = [];
 2283+
 2284+ // Load enabled components
 2285+ var enabledComponents = mw.getConfig( 'coreComponents' );
 2286+ function loadEnabledComponents( enabledComponents ){
 2287+ if( ! enabledComponents.length ){
 2288+ // If no more components load modules::
 2289+
 2290+ // Add the enabledModules loaders:
 2291+ var enabledModules = mw.getConfig( 'enabledModules' );
 2292+ loadEnabledModules( enabledModules );
 2293+ return ;
 2294+ }
 2295+ var componentName = enabledComponents.shift();
 2296+ componentName = componentName.replace(/"/g,'');
 2297+ mw.load( componentName, function(){
 2298+ loadEnabledComponents( enabledComponents );
 2299+ } );
 2300+ }
 2301+ loadEnabledComponents( enabledComponents );
 2302+
 2303+
 2304+ // Set the loader context and get each loader individually
 2305+ function loadEnabledModules( enabledModules ){
 2306+ if( ! enabledModules.length ){
 2307+ // If no more modules left load the LanguageFile
 2308+ addLanguageFile();
 2309+ return ;
 2310+ }
 2311+ var moduleName = enabledModules.shift();
 2312+ moduleName = moduleName.replace(/"/g,'');
 2313+ mw.setConfig( 'loaderContext', 'modules/' + moduleName + '/' );
 2314+ mw.load( 'modules/' + moduleName + '/loader.js', function(){
 2315+ loadEnabledModules( enabledModules );
 2316+ } );
 2317+ }
 2318+
 2319+ function addLanguageFile(){
 2320+ // Add the language file
 2321+ var langLoaderRequest = [];
 2322+
 2323+ if( mw.getConfig( 'userLanguage' ) ) {
 2324+ var langCode = mw.getConfig( 'userLanguage' );
 2325+
 2326+ // Load the language resource if not default 'en'
 2327+ var transformKey = mw.getLangTransformKey( langCode );
 2328+ if( transformKey != 'en' ){
 2329+ // Upper case the first letter:
 2330+ langCode = langCode.substr(0,1).toUpperCase() + langCode.substr( 1, langCode.length );
 2331+ langLoaderRequest.push( 'languages/classes/Language' +
 2332+ langCode + '.js' );
 2333+ }
 2334+
 2335+ }
 2336+ if ( ! langLoaderRequest.length ) {
 2337+ addLocalSettings();
 2338+ return ;
 2339+ }
 2340+
 2341+ // Load the language if set
 2342+ mw.load( langLoaderRequest, function(){
 2343+ mw.log( 'Done moduleLoaderCheck request' );
 2344+ addLocalSettings();
 2345+ } );
 2346+ }
 2347+ function addLocalSettings(){
 2348+ var continueCallback = function(){
 2349+ // Set the mwModuleLoaderCheckFlag flag to true
 2350+ mwModuleLoaderCheckFlag = true;
 2351+ callback();
 2352+ };
 2353+ if( mw.getConfig( 'LoadLocalSettings') != true ){
 2354+ continueCallback();
 2355+ return;
 2356+ }
 2357+ mw.log("Load loacal settings");
 2358+ mw.load( 'localSettings.js', function(){
 2359+ continueCallback();
 2360+ });
 2361+ }
 2362+
 2363+ };
 2364+
 2365+ /**
 2366+ * Checks if a css style rule exists
 2367+ *
 2368+ * On a page with lots of rules it can take some time so avoid calling this
 2369+ * function where possible and cache its result
 2370+ *
 2371+ * NOTE: this only works for style sheets on the same domain :(
 2372+ *
 2373+ * @param {String}
 2374+ * styleRule Style rule name to check
 2375+ * @return {Boolean} true if the rule exists false if the rule does not
 2376+ * exist
 2377+ */
 2378+ mw.styleRuleExists = function ( styleRule ) {
 2379+ // Set up the skin paths configuration
 2380+ for( var i=0 ; i < document.styleSheets.length ; i++ ) {
 2381+ var rules = null;
 2382+ try{
 2383+ if ( document.styleSheets[i].cssRules )
 2384+ rules = document.styleSheets[i].cssRules;
 2385+ else if (document.styleSheets[0].rules)
 2386+ rules = document.styleSheets[i].rules;
 2387+ for(var j=0 ; j < rules.length ; j++ ) {
 2388+ var rule = rules[j].selectorText;
 2389+ if( rule && rule.indexOf( styleRule ) != -1 ) {
 2390+ return true;
 2391+ }
 2392+ }
 2393+ }catch ( e ) {
 2394+ mw.log( 'Error: cant check rule on cross domain style sheet:' + document.styleSheets[i].href );
 2395+ }
 2396+ }
 2397+ return false;
 2398+ };
 2399+
 2400+ // Flag to register the domReady has been called
 2401+ var mwDomReadyFlag = false;
 2402+
 2403+ // Flag to register if the domreadyHooks have been called
 2404+ var mwModuleLoaderCheckFlag = false;
 2405+
 2406+ /**
 2407+ * This will get called when the DOM is ready Will check configuration and
 2408+ * issue a mw.setupMwEmbed call if needed
 2409+ */
 2410+ mw.domReady = function ( ) {
 2411+ if( mwDomReadyFlag ) {
 2412+ return ;
 2413+ }
 2414+ mw.log( 'run:domReady:: ' + document.getElementsByTagName('video').length );
 2415+ // Set the onDomReady Flag
 2416+ mwDomReadyFlag = true;
 2417+
 2418+ // Give us a chance to get to the bottom of the script.
 2419+ // When loading mwEmbed asynchronously the dom ready gets called
 2420+ // directly and in some browsers beets the $j = jQuery.noConflict();
 2421+ // call
 2422+ // and causes symbol undefined errors.
 2423+ setTimeout(function(){
 2424+ mw.setupMwEmbed();
 2425+ },1);
 2426+ };
 2427+
 2428+ /**
 2429+ * A version comparison utility function Handles version of types
 2430+ * {Major}.{MinorN}.{Patch}
 2431+ *
 2432+ * Note this just handles version numbers not patch letters.
 2433+ *
 2434+ * @param {String}
 2435+ * minVersion Minnium version needed
 2436+ * @param {String}
 2437+ * clientVersion Client version to be checked
 2438+ *
 2439+ * @return true if the version is at least of minVersion false if the
 2440+ * version is less than minVersion
 2441+ */
 2442+ mw.versionIsAtLeast = function( minVersion, clientVersion ) {
 2443+ var minVersionParts = minVersion.split('.');
 2444+ var clientVersionParts = clientVersion.split('.');
 2445+ for( var i =0; i < minVersionParts.length; i++ ) {
 2446+ if( parseInt( clientVersionParts[i] ) > parseInt( minVersionParts[i] ) ) {
 2447+ return true;
 2448+ }
 2449+ if( parseInt( clientVersionParts[i] ) < parseInt( minVersionParts[i] ) ) {
 2450+ return false;
 2451+ }
 2452+ }
 2453+ // Same version:
 2454+ return true;
 2455+ };
 2456+
 2457+ /**
 2458+ * Utility jQuery bindings Setup after jQuery is available ).
 2459+ */
 2460+ mw.dojQueryBindings = function() {
 2461+ mw.log( 'mw.dojQueryBindings' );
 2462+ ( function( $ ) {
 2463+
 2464+ /**
 2465+ * Runs all the triggers on all the named bindings of an object with
 2466+ * a single callback
 2467+ *
 2468+ * NOTE THIS REQUIRES JQUERY 1.4.2 and above
 2469+ *
 2470+ * Normal jQuery tirgger calls will run the callback directly
 2471+ * multiple times for every binded function.
 2472+ *
 2473+ * With triggerQueueCallback() callback is not called until all the
 2474+ * binded events have been run.
 2475+ *
 2476+ * @param {string}
 2477+ * triggerName Name of trigger to be run
 2478+ * @param {object=}
 2479+ * arguments Optional arguments object to be passed to
 2480+ * the callback
 2481+ * @param {function}
 2482+ * callback Function called once all triggers have been
 2483+ * run
 2484+ *
 2485+ */
 2486+ $.fn.triggerQueueCallback = function( triggerName, triggerParam, callback ){
 2487+ var targetObject = this;
 2488+ // Support optional triggerParam data
 2489+ if( !callback && typeof triggerParam == 'function' ){
 2490+ callback = triggerParam;
 2491+ triggerParam = null;
 2492+ }
 2493+ // Support namespaced event segmentation ( jQuery
 2494+ var triggerBaseName = triggerName.split(".")[0];
 2495+ var triggerNamespace = triggerName.split(".")[1];
 2496+ // Get the callback set
 2497+ var callbackSet = [];
 2498+ if( ! triggerNamespace ){
 2499+ callbackSet = $j( targetObject ).data( 'events' )[ triggerBaseName ];
 2500+ } else{
 2501+ $j.each( $j( targetObject ).data( 'events' )[ triggerBaseName ], function( inx, bindObject ){
 2502+ if( bindObject.namespace == triggerNamespace ){
 2503+ callbackSet.push( bindObject );
 2504+ }
 2505+ });
 2506+ }
 2507+
 2508+ if( !callbackSet || callbackSet.length === 0 ){
 2509+ mw.log( '"mwEmbed::jQuery.triggerQueueCallback: No events run the callback directly: ' + triggerName );
 2510+ // No events run the callback directly
 2511+ callback();
 2512+ return ;
 2513+ }
 2514+
 2515+ // Set the callbackCount
 2516+ var callbackCount = ( callbackSet.length )? callbackSet.length : 1;
 2517+ // mw.log("mwEmbed::jQuery.triggerQueueCallback: " + triggerName
 2518+ // + ' number of queued functions:' + callbackCount );
 2519+ var callInx = 0;
 2520+ var doCallbackCheck = function() {
 2521+ // mw.log( 'callback for: ' + mw.getCallStack()[0] +
 2522+ // callInx);
 2523+ callInx++;
 2524+ if( callInx == callbackCount ){
 2525+ callback();
 2526+ }
 2527+ };
 2528+ if( triggerParam ){
 2529+ $( this ).trigger( triggerName, [ triggerParam, doCallbackCheck ]);
 2530+ } else {
 2531+ $( this ).trigger( triggerName, [ doCallbackCheck ] );
 2532+ }
 2533+ };
 2534+
 2535+ /**
 2536+ * Set a given selector html to the loading spinner:
 2537+ */
 2538+ $.fn.loadingSpinner = function( ) {
 2539+ if ( this ) {
 2540+ $( this ).html(
 2541+ $( '<div />' )
 2542+ .addClass( "loadingSpinner" )
 2543+ );
 2544+ }
 2545+ return this;
 2546+ };
 2547+
 2548+ /**
 2549+ * Add an absolute overlay spinner useful for cases where the
 2550+ * element does not display child elements, ( images, video )
 2551+ */
 2552+ $.fn.getAbsoluteOverlaySpinner = function(){
 2553+ var pos = $j( this ).offset();
 2554+ var posLeft = ( $j( this ).width() ) ?
 2555+ parseInt( pos.left + ( .5 * $j( this ).width() ) -16 ) :
 2556+ pos.left + 30;
 2557+
 2558+ var posTop = ( $j( this ).height() ) ?
 2559+ parseInt( pos.top + ( .5 * $j( this ).height() ) -16 ) :
 2560+ pos.top + 30;
 2561+
 2562+ var $spinner = $j('<div />')
 2563+ .loadingSpinner()
 2564+ .css({
 2565+ 'width' : 32,
 2566+ 'height' : 32,
 2567+ 'position': 'absolute',
 2568+ 'top' : posTop + 'px',
 2569+ 'left' : posLeft + 'px'
 2570+ });
 2571+ $j('body').append( $spinner );
 2572+ return $spinner;
 2573+ };
 2574+
 2575+ /**
 2576+ * dragDrop file loader
 2577+ */
 2578+ $.fn.dragFileUpload = function ( conf ) {
 2579+ if ( this.selector ) {
 2580+ var _this = this;
 2581+ // load the dragger and "setup"
 2582+ mw.load( ['$j.fn.dragDropFile'], function() {
 2583+ $j( _this.selector ).dragDropFile();
 2584+ } );
 2585+ }
 2586+ };
 2587+
 2588+ /**
 2589+ * Shortcut to a themed button Should be depreciated for $.button
 2590+ * bellow
 2591+ */
 2592+ $.btnHtml = function( msg, styleClass, iconId, opt ) {
 2593+ if ( !opt )
 2594+ opt = { };
 2595+ var href = ( opt.href ) ? opt.href : '#';
 2596+ var target_attr = ( opt.target ) ? ' target="' + opt.target + '" ' : '';
 2597+ var style_attr = ( opt.style ) ? ' style="' + opt.style + '" ' : '';
 2598+ return '<a href="' + href + '" ' + target_attr + style_attr +
 2599+ ' class="ui-state-default ui-corner-all ui-icon_link ' +
 2600+ styleClass + '"><span class="ui-icon ui-icon-' + iconId + '" ></span>' +
 2601+ '<span class="btnText">' + msg + '</span></a>';
 2602+ };
 2603+
 2604+ // Shortcut to jQuery button ( should replace all btnHtml with
 2605+ // button )
 2606+ var mw_default_button_options = {
 2607+ // The class name for the button link
 2608+ 'class' : '',
 2609+
 2610+ // The style properties for the button link
 2611+ 'style' : { },
 2612+
 2613+ // The text of the button link
 2614+ 'text' : '',
 2615+
 2616+ // The icon id that precedes the button link:
 2617+ 'icon' : 'carat-1-n'
 2618+ };
 2619+
 2620+ $.button = function( options ) {
 2621+ var options = $j.extend( {}, mw_default_button_options, options);
 2622+
 2623+ // Button:
 2624+ var $button = $j('<a />')
 2625+ .attr('href', '#')
 2626+ .addClass( 'ui-state-default ui-corner-all ui-icon_link' );
 2627+ // Add css if set:
 2628+ if( options.css ) {
 2629+ $button.css( options.css );
 2630+ }
 2631+
 2632+ if( options['class'] ) {
 2633+ $button.addClass( options['class'] );
 2634+ }
 2635+
 2636+ // return the button:
 2637+ $button.append(
 2638+ $j('<span />').addClass( 'ui-icon ui-icon-' + options.icon ),
 2639+ $j('<span />').addClass( 'btnText' )
 2640+ )
 2641+ .buttonHover(); // add buttonHover binding;
 2642+
 2643+ if( options.text ){
 2644+ $button.find('.btnText').text( options.text );
 2645+ } else {
 2646+ $button.css('padding', '1em');
 2647+ }
 2648+ return $button;
 2649+ };
 2650+
 2651+ // Shortcut to bind hover state
 2652+ $.fn.buttonHover = function() {
 2653+ $j( this ).hover(
 2654+ function() {
 2655+ $j( this ).addClass( 'ui-state-hover' );
 2656+ },
 2657+ function() {
 2658+ $j( this ).removeClass( 'ui-state-hover' );
 2659+ }
 2660+ );
 2661+ return this;
 2662+ };
 2663+
 2664+ /**
 2665+ * Resize a dialog to fit the window
 2666+ *
 2667+ * @param {Object}
 2668+ * options horizontal and vertical space ( default 50 )
 2669+ */
 2670+ $.fn.dialogFitWindow = function( options ) {
 2671+ var opt_default = { 'hspace':50, 'vspace':50 };
 2672+ if ( !options )
 2673+ var options = { };
 2674+ options = $j.extend( opt_default, options );
 2675+ $j( this.selector ).dialog( 'option', 'width', $j( window ).width() - options.hspace );
 2676+ $j( this.selector ).dialog( 'option', 'height', $j( window ).height() - options.vspace );
 2677+ $j( this.selector ).dialog( 'option', 'position', 'center' );
 2678+ // update the child position: (some of this should be pushed
 2679+ // up-stream via dialog config options
 2680+ $j( this.selector + '~ .ui-dialog-buttonpane' ).css( {
 2681+ 'position':'absolute',
 2682+ 'left':'0px',
 2683+ 'right':'0px',
 2684+ 'bottom':'0px'
 2685+ } );
 2686+ };
 2687+
 2688+ } )( jQuery );
 2689+ };
 2690+
 2691+} )( window.mw );
 2692+
 2693+
 2694+/**
 2695+ * Set DOM-ready call We copy jQuery( document ).ready here since sometimes
 2696+ * mwEmbed.js is included without jQuery and we need our own "ready" system so
 2697+ * that mwEmbed interfaces can support async built out and the include of
 2698+ * jQuery.
 2699+ */
 2700+// Check if already ready:
 2701+if ( document.readyState === "complete" ) {
 2702+ mw.domReady();
 2703+}
 2704+
 2705+// Cleanup functions for the document ready method
 2706+if ( document.addEventListener ) {
 2707+ DOMContentLoaded = function() {
 2708+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
 2709+ mw.domReady();
 2710+ };
 2711+
 2712+} else if ( document.attachEvent ) {
 2713+ DOMContentLoaded = function() {
 2714+ // Make sure body exists, at least, in case IE gets a little overzealous
 2715+ // (ticket #5443).
 2716+ if ( document.readyState === "complete" ) {
 2717+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
 2718+ mw.domReady();
 2719+ }
 2720+ };
 2721+}
 2722+// Mozilla, Opera and webkit nightlies currently support this event
 2723+if ( document.addEventListener ) {
 2724+ // Use the handy event callback
 2725+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
 2726+
 2727+ // A fallback to window.onload, that will always work
 2728+ window.addEventListener( "load", mw.domReady, false );
 2729+
 2730+// If IE event model is used
 2731+} else if ( document.attachEvent ) {
 2732+ // ensure firing before onload,
 2733+ // maybe late but safe also for iframes
 2734+ document.attachEvent("onreadystatechange", DOMContentLoaded);
 2735+
 2736+ // A fallback to window.onload, that will always work
 2737+ window.attachEvent( "onload", mw.domReady );
 2738+
 2739+ // If IE and not a frame
 2740+ // continually check to see if the document is ready
 2741+ var toplevel = false;
 2742+
 2743+ try {
 2744+ toplevel = window.frameElement == null;
 2745+ } catch(e) {}
 2746+
 2747+ if ( document.documentElement.doScroll && toplevel ) {
 2748+ doScrollCheck();
 2749+ }
 2750+}
 2751+// The DOM ready check for Internet Explorer
 2752+function doScrollCheck() {
 2753+ try {
 2754+ // If IE is used, use the trick by Diego Perini
 2755+ // http://javascript.nwbox.com/IEContentLoaded/
 2756+ document.documentElement.doScroll("left");
 2757+ } catch( error ) {
 2758+ setTimeout( doScrollCheck, 1 );
 2759+ return;
 2760+ }
 2761+ mw.domReady();
 2762+}
 2763+
 2764+// If using the resource loader and jQuery has not been set give a warning to
 2765+// the user:
 2766+// (this is needed because packaged loader.js files could refrence jQuery )
 2767+if( mw.getResourceLoaderPath() && !window.jQuery ) {
 2768+ mw.log( 'Error: jQuery is required for mwEmbed, please update your resource loader request' );
 2769+}
 2770+
 2771+if( mw.isStaticPackge() && !window.jQuery ){
 2772+ alert( 'Error: jQuery is required for mwEmbed ');
 2773+}
 2774+
 2775+/**
 2776+ * Hack to keep jQuery in $ when its already there, but also use noConflict to
 2777+ * get $j = jQuery
 2778+ *
 2779+ * This way sites that use $ for jQuery continue to work after including mwEmbed
 2780+ * javascript.
 2781+ *
 2782+ * Also if jQuery is included prior to mwEmbed we ensure $j is set
 2783+ */
 2784+
 2785+if( window.jQuery ){
 2786+ if( ! mw.versionIsAtLeast( '1.4.2', jQuery.fn.jquery ) ){
 2787+ if( window.console && window.console.log ) {
 2788+ console.log( 'Error mwEmbed requires jQuery 1.4 or above' );
 2789+ }
 2790+ }
 2791+ var dollarFlag = false;
 2792+ if( $ && $.fn && $.fn.jquery ) {
 2793+ // NOTE we could check the version of
 2794+ // jQuery and do a removal call if too old
 2795+ dollarFlag = true;
 2796+ }
 2797+ window[ '$j' ] = jQuery.noConflict();
 2798+ if( dollarFlag ) {
 2799+ window[ '$' ] = jQuery.noConflict();
 2800+ }
 2801+}
Property changes on: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MediaWikiSupport/mwEmbed.js
___________________________________________________________________
Added: svn:mergeinfo
12802 Merged /branches/REL1_15/phase3/js2/mwEmbed/mv_embed.js:r51646
22803 Merged /branches/sqlite/js2/mwEmbed/mv_embed.js:r58211-58321
Added: svn:eol-style
32804 + native
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MediaWikiSupport/README
@@ -1 +1,2 @@
2 -The MediaWikiSupport package stores the what is called "MediaWikiSharedJS" in the extensions.
\ No newline at end of file
 2+The MediaWikiSupport module bridges shared mwEmbed gadget support with features that
 3+are not yet in core mediaWiki resources.
\ No newline at end of file
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/loader.js
@@ -440,12 +440,6 @@
441441 dependencyRequest.push( 'mw.style.PlayerSkin' + skinCaseName );
442442 }
443443
444 - // Check if the iFrame api server should be loaded ( iframe api is on ):
445 - if( mw.getConfig('EmbedPlayer.EnableIframeApi') ){
446 - dependencyRequest.push( 'mw.IFramePlayerApiServer' );
447 - }
448 -
449 -
450444 // Allow extension to extend the request.
451445 $j( mw ).trigger( 'LoaderEmbedPlayerUpdateRequest',
452446 [ playerElement, dependencyRequest ] );
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js
@@ -782,53 +782,54 @@
783783 */
784784 detectType: function( uri ) {
785785 // NOTE: if media is on the same server as the javascript
786 - // we can issue a HEAD request and read the mime type of the media ...
787 - // ( this will detect media mime type independently of the url name)
 786+ // we can issue a HEAD request and read the mime type of the media...
 787+ // ( this will detect media mime type independently of the url name )
788788 // http://www.jibbering.com/2002/4/httprequest.html
789 - var end_inx = ( uri.indexOf( '?' ) != -1 ) ? uri.indexOf( '?' ) : uri.length;
790 - var no_param_uri = uri.substr( 0, end_inx );
791 - switch( no_param_uri.substr( no_param_uri.lastIndexOf( '.' )+1 ).toLowerCase() ) {
 789+ var urlParts = mw.parseUri( uri );
 790+ // Get the extension from the url or from the relative name:
 791+ var ext = ( urlParts.file )? urlParts.file.substr( -4 ) : uri.substr( -4 );
 792+ switch( ext.toLowerCase() ) {
792793 case 'smil':
793 - case 'sml':
794 - return 'application/smil'
 794+ case '.sml':
 795+ return 'application/smil';
795796 break;
796 - case 'm4v':
797 - case 'mp4':
798 - case 'mov':
 797+ case '.m4v':
 798+ case '.mp4':
799799 return 'video/h264';
800800 break;
801801 case 'webm':
802802 return 'video/webm';
803803 break;
804 - case 'srt':
 804+ case '.srt':
805805 return 'text/x-srt';
806806 break;
807 - case 'flv':
 807+ case '.flv':
808808 return 'video/x-flv';
809809 break;
810 - case 'ogg':
811 - case 'ogv':
 810+ case '.ogg':
 811+ case '.ogv':
812812 return 'video/ogg';
813813 break;
814 - case 'oga':
 814+ case '.oga':
815815 return 'audio/ogg';
816816 break;
817 - case 'anx':
 817+ case '.anx':
818818 return 'video/ogg';
819819 break;
820 - case 'xml':
 820+ case '.xml':
821821 return 'text/xml';
822822 break;
823 - case 'avi':
 823+ case '.avi':
824824 return 'video/x-msvideo';
825825 break;
826 - case 'mpg':
 826+ case '.mpg':
827827 return 'video/mpeg';
828828 break;
829 - case 'mpeg':
 829+ case '.mpeg':
830830 return 'video/mpeg';
831831 break;
832832 }
 833+ mw.log( "Error: could not detect type of media src: " + uri );
833834 }
834835 };
835836
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/Resources.php
@@ -1,530 +0,0 @@
2 -<?php
3 -
4 -return array(
5 -
6 - /* Special resources who have their own classes */
7 -
8 - 'site' => array( 'class' => 'ResourceLoaderSiteModule' ),
9 - 'startup' => array( 'class' => 'ResourceLoaderStartUpModule' ),
10 - 'user' => array( 'class' => 'ResourceLoaderUserModule' ),
11 - 'user.options' => array( 'class' => 'ResourceLoaderUserOptionsModule' ),
12 -
13 - /* Skins */
14 -
15 - 'skins.vector' => array(
16 - 'styles' => array( 'skins/vector/screen.css' => array( 'media' => 'screen' ) ),
17 - ),
18 - 'skins.monobook' => array(
19 - 'styles' => array(
20 - 'skins/monobook/main.css' => array( 'media' => 'screen' ),
21 - // Honor $wgHandheldStyle. This is kind of evil
22 - //$GLOBALS['wgHandheldStyle'] => array( 'media' => 'handheld' ),
23 - ),
24 - ),
25 -
26 - /* jQuery */
27 -
28 - 'jquery' => array(
29 - 'scripts' => 'resources/jquery/jquery.js',
30 - 'debugRaw' => false
31 - ),
32 -
33 - /* jQuery Plugins */
34 -
35 - 'jquery.async' => array(
36 - 'scripts' => 'resources/jquery/jquery.async.js',
37 - ),
38 - 'jquery.autoEllipsis' => array(
39 - 'scripts' => 'resources/jquery/jquery.autoEllipsis.js',
40 - 'dependencies' => 'jquery.highlightText',
41 - ),
42 - 'jquery.checkboxShiftClick' => array(
43 - 'scripts' => 'resources/jquery/jquery.checkboxShiftClick.js',
44 - ),
45 - 'jquery.client' => array(
46 - 'scripts' => 'resources/jquery/jquery.client.js',
47 - ),
48 - 'jquery.collapsibleTabs' => array(
49 - 'scripts' => 'resources/jquery/jquery.collapsibleTabs.js',
50 - ),
51 - 'jquery.colorUtil' => array(
52 - 'scripts' => 'resources/jquery/jquery.colorUtil.js',
53 - ),
54 - 'jquery.color' => array(
55 - 'scripts' => 'resources/jquery/jquery.color.js',
56 - 'dependencies' => 'jquery.colorUtil',
57 - ),
58 - 'jquery.cookie' => array(
59 - 'scripts' => 'resources/jquery/jquery.cookie.js',
60 - ),
61 - 'jquery.delayedBind' => array(
62 - 'scripts' => 'resources/jquery/jquery.delayedBind.js',
63 - ),
64 - 'jquery.expandableField' => array(
65 - 'scripts' => 'resources/jquery/jquery.expandableField.js',
66 - ),
67 - 'jquery.highlightText' => array(
68 - 'scripts' => 'resources/jquery/jquery.highlightText.js',
69 - ),
70 - 'jquery.hoverIntent' => array(
71 - 'scripts' => 'resources/jquery/jquery.hoverIntent.js',
72 - ),
73 - 'jquery.placeholder' => array(
74 - 'scripts' => 'resources/jquery/jquery.placeholder.js',
75 - ),
76 - 'jquery.localize' => array(
77 - 'scripts' => 'resources/jquery/jquery.localize.js',
78 - ),
79 - 'jquery.makeCollapsible' => array(
80 - 'scripts' => 'resources/jquery/jquery.makeCollapsible.js',
81 - 'styles' => 'resources/jquery/jquery.makeCollapsible.css',
82 - 'messages' => array( 'collapsible-expand', 'collapsible-collapse' ),
83 - ),
84 - 'jquery.suggestions' => array(
85 - 'scripts' => 'resources/jquery/jquery.suggestions.js',
86 - 'styles' => 'resources/jquery/jquery.suggestions.css',
87 - ),
88 - 'jquery.tabIndex' => array(
89 - 'scripts' => 'resources/jquery/jquery.tabIndex.js',
90 - ),
91 - 'jquery.textSelection' => array(
92 - 'scripts' => 'resources/jquery/jquery.textSelection.js',
93 - ),
94 - 'jquery.tipsy' => array(
95 - 'scripts' => 'resources/jquery.tipsy/jquery.tipsy.js',
96 - 'styles' => 'resources/jquery.tipsy/jquery.tipsy.css',
97 - ),
98 -
99 - /* jQuery UI */
100 -
101 - // Core
102 - 'jquery.ui.core' => array(
103 - 'scripts' => 'resources/jquery.ui/jquery.ui.core.js',
104 - 'skinStyles' => array(
105 - 'default' => array(
106 - 'resources/jquery.ui/themes/default/jquery.ui.core.css',
107 - 'resources/jquery.ui/themes/default/jquery.ui.theme.css',
108 - ),
109 - 'vector' => array(
110 - 'resources/jquery.ui/themes/vector/jquery.ui.core.css',
111 - 'resources/jquery.ui/themes/vector/jquery.ui.theme.css',
112 - ),
113 - ),
114 - 'dependencies' => 'jquery',
115 - ),
116 - 'jquery.ui.widget' => array(
117 - 'scripts' => 'resources/jquery.ui/jquery.ui.widget.js',
118 - ),
119 - 'jquery.ui.mouse' => array(
120 - 'scripts' => 'resources/jquery.ui/jquery.ui.mouse.js',
121 - 'dependencies' => 'jquery.ui.widget',
122 - ),
123 - 'jquery.ui.position' => array(
124 - 'scripts' => 'resources/jquery.ui/jquery.ui.position.js',
125 - ),
126 - // Interactions
127 - 'jquery.ui.draggable' => array(
128 - 'scripts' => 'resources/jquery.ui/jquery.ui.draggable.js',
129 - 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.mouse', 'jquery.ui.widget' ),
130 - ),
131 - 'jquery.ui.droppable' => array(
132 - 'scripts' => 'resources/jquery.ui/jquery.ui.droppable.js',
133 - 'dependencies' => array(
134 - 'jquery.ui.core', 'jquery.ui.mouse', 'jquery.ui.widget', 'jquery.ui.draggable',
135 - ),
136 - ),
137 - 'jquery.ui.resizable' => array(
138 - 'scripts' => 'resources/jquery.ui/jquery.ui.resizable.js',
139 - 'skinStyles' => array(
140 - 'default' => 'resources/jquery.ui/themes/default/jquery.ui.resizable.css',
141 - 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.resizable.css',
142 - ),
143 - 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
144 - ),
145 - 'jquery.ui.selectable' => array(
146 - 'scripts' => 'resources/jquery.ui/jquery.ui.selectable.js',
147 - 'skinStyles' => array(
148 - 'default' => 'resources/jquery.ui/themes/default/jquery.ui.selectable.css',
149 - 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.selectable.css',
150 - ),
151 - 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
152 - ),
153 - 'jquery.ui.sortable' => array(
154 - 'scripts' => 'resources/jquery.ui/jquery.ui.sortable.js',
155 - 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
156 - ),
157 - // Widgets
158 - 'jquery.ui.accordion' => array(
159 - 'scripts' => 'resources/jquery.ui/jquery.ui.accordion.js',
160 - 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
161 - 'skinStyles' => array(
162 - 'default' => 'resources/jquery.ui/themes/default/jquery.ui.accordion.css',
163 - 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.accordion.css',
164 - ),
165 - ),
166 - 'jquery.ui.autocomplete' => array(
167 - 'scripts' => 'resources/jquery.ui/jquery.ui.autocomplete.js',
168 - 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.position' ),
169 - 'skinStyles' => array(
170 - 'default' => 'resources/jquery.ui/themes/default/jquery.ui.autocomplete.css',
171 - 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.autocomplete.css',
172 - ),
173 - ),
174 - 'jquery.ui.button' => array(
175 - 'scripts' => 'resources/jquery.ui/jquery.ui.button.js',
176 - 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
177 - 'skinStyles' => array(
178 - 'default' => 'resources/jquery.ui/themes/default/jquery.ui.button.css',
179 - 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.button.css',
180 - ),
181 - ),
182 - 'jquery.ui.datepicker' => array(
183 - 'scripts' => 'resources/jquery.ui/jquery.ui.datepicker.js',
184 - 'dependencies' => 'jquery.ui.core',
185 - 'skinStyles' => array(
186 - 'default' => 'resources/jquery.ui/themes/default/jquery.ui.datepicker.css',
187 - 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.datepicker.css',
188 - ),
189 - 'languageScripts' => array(
190 - 'af' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-af.js',
191 - 'ar' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ar.js',
192 - 'az' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-az.js',
193 - 'bg' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-bg.js',
194 - 'bs' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-bs.js',
195 - 'ca' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ca.js',
196 - 'cs' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-cs.js',
197 - 'da' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-da.js',
198 - 'de' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-de.js',
199 - 'el' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-el.js',
200 - 'en-gb' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js',
201 - 'eo' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-eo.js',
202 - 'es' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-es.js',
203 - 'et' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-et.js',
204 - 'eu' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-eu.js',
205 - 'fa' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fa.js',
206 - 'fi' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fi.js',
207 - 'fo' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fo.js',
208 - 'fr-ch' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fr-CH.js',
209 - 'fr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fr.js',
210 - 'he' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-he.js',
211 - 'hr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-hr.js',
212 - 'hu' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-hu.js',
213 - 'hy' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-hy.js',
214 - 'id' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-id.js',
215 - 'is' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-is.js',
216 - 'it' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-it.js',
217 - 'ja' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ja.js',
218 - 'ko' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ko.js',
219 - 'lt' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-lt.js',
220 - 'lv' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-lv.js',
221 - 'ms' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ms.js',
222 - 'nl' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-nl.js',
223 - 'no' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-no.js',
224 - 'pl' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-pl.js',
225 - 'pt-br' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js',
226 - 'ro' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ro.js',
227 - 'ru' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ru.js',
228 - 'sk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sk.js',
229 - 'sl' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sl.js',
230 - 'sq' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sq.js',
231 - 'sr-sr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js',
232 - 'sr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sr.js',
233 - 'sv' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sv.js',
234 - 'ta' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ta.js',
235 - 'th' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-th.js',
236 - 'tr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-tr.js',
237 - 'uk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-uk.js',
238 - 'vi' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-vi.js',
239 - 'zh-cn' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js',
240 - 'zh-hk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js',
241 - 'zh-tw' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js',
242 - ),
243 - ),
244 - 'jquery.ui.dialog' => array(
245 - 'scripts' => 'resources/jquery.ui/jquery.ui.dialog.js',
246 - 'dependencies' => array(
247 - 'jquery.ui.core',
248 - 'jquery.ui.widget',
249 - 'jquery.ui.button',
250 - 'jquery.ui.draggable',
251 - 'jquery.ui.mouse',
252 - 'jquery.ui.position',
253 - 'jquery.ui.resizable',
254 - ),
255 - 'skinStyles' => array(
256 - 'default' => 'resources/jquery.ui/themes/default/jquery.ui.dialog.css',
257 - 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.dialog.css',
258 - ),
259 - ),
260 - 'jquery.ui.progressbar' => array(
261 - 'scripts' => 'resources/jquery.ui/jquery.ui.progressbar.js',
262 - 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
263 - 'skinStyles' => array(
264 - 'default' => 'resources/jquery.ui/themes/default/jquery.ui.progressbar.css',
265 - 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.progressbar.css',
266 - ),
267 - ),
268 - 'jquery.ui.slider' => array(
269 - 'scripts' => 'resources/jquery.ui/jquery.ui.slider.js',
270 - 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
271 - 'skinStyles' => array(
272 - 'default' => 'resources/jquery.ui/themes/default/jquery.ui.slider.css',
273 - 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.slider.css',
274 - ),
275 - ),
276 - 'jquery.ui.tabs' => array(
277 - 'scripts' => 'resources/jquery.ui/jquery.ui.tabs.js',
278 - 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
279 - 'skinStyles' => array(
280 - 'default' => 'resources/jquery.ui/themes/default/jquery.ui.tabs.css',
281 - 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.tabs.css',
282 - ),
283 - ),
284 - // Effects
285 - 'jquery.effects.core' => array(
286 - 'scripts' => 'resources/jquery.effects/jquery.effects.core.js',
287 - 'dependencies' => 'jquery',
288 - ),
289 - 'jquery.effects.blind' => array(
290 - 'scripts' => 'resources/jquery.effects/jquery.effects.blind.js',
291 - 'dependencies' => 'jquery.effects.core',
292 - ),
293 - 'jquery.effects.bounce' => array(
294 - 'scripts' => 'resources/jquery.effects/jquery.effects.bounce.js',
295 - 'dependencies' => 'jquery.effects.core',
296 - ),
297 - 'jquery.effects.clip' => array(
298 - 'scripts' => 'resources/jquery.effects/jquery.effects.clip.js',
299 - 'dependencies' => 'jquery.effects.core',
300 - ),
301 - 'jquery.effects.drop' => array(
302 - 'scripts' => 'resources/jquery.effects/jquery.effects.drop.js',
303 - 'dependencies' => 'jquery.effects.core',
304 - ),
305 - 'jquery.effects.explode' => array(
306 - 'scripts' => 'resources/jquery.effects/jquery.effects.explode.js',
307 - 'dependencies' => 'jquery.effects.core',
308 - ),
309 - 'jquery.effects.fold' => array(
310 - 'scripts' => 'resources/jquery.effects/jquery.effects.fold.js',
311 - 'dependencies' => 'jquery.effects.core',
312 - ),
313 - 'jquery.effects.highlight' => array(
314 - 'scripts' => 'resources/jquery.effects/jquery.effects.highlight.js',
315 - 'dependencies' => 'jquery.effects.core',
316 - ),
317 - 'jquery.effects.pulsate' => array(
318 - 'scripts' => 'resources/jquery.effects/jquery.effects.pulsate.js',
319 - 'dependencies' => 'jquery.effects.core',
320 - ),
321 - 'jquery.effects.scale' => array(
322 - 'scripts' => 'resources/jquery.effects/jquery.effects.scale.js',
323 - 'dependencies' => 'jquery.effects.core',
324 - ),
325 - 'jquery.effects.shake' => array(
326 - 'scripts' => 'resources/jquery.effects/jquery.effects.shake.js',
327 - 'dependencies' => 'jquery.effects.core',
328 - ),
329 - 'jquery.effects.slide' => array(
330 - 'scripts' => 'resources/jquery.effects/jquery.effects.slide.js',
331 - 'dependencies' => 'jquery.effects.core',
332 - ),
333 - 'jquery.effects.transfer' => array(
334 - 'scripts' => 'resources/jquery.effects/jquery.effects.transfer.js',
335 - 'dependencies' => 'jquery.effects.core',
336 - ),
337 -
338 - /* MediaWiki */
339 -
340 - 'mediawiki' => array(
341 - 'scripts' => 'resources/mediawiki/mediawiki.js',
342 - 'debugScripts' => 'resources/mediawiki/mediawiki.log.js',
343 - 'debugRaw' => false
344 - ),
345 - 'mediawiki.util' => array(
346 - 'scripts' => 'resources/mediawiki.util/mediawiki.util.js',
347 - 'dependencies' => array( 'jquery.checkboxShiftClick', 'jquery.client', 'jquery.cookie', 'jquery.placeholder', 'jquery.makeCollapsible' ),
348 - 'debugScripts' => 'resources/mediawiki.util/mediawiki.util.test.js',
349 - ),
350 - 'mediawiki.action.history' => array(
351 - 'scripts' => 'resources/mediawiki.action/mediawiki.action.history.js',
352 - 'dependencies' => 'mediawiki.legacy.history',
353 - ),
354 - 'mediawiki.action.view.rightClickEdit' => array(
355 - 'scripts' => 'resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js',
356 - ),
357 - 'mediawiki.action.watch.ajax' => array(
358 - 'scripts' => 'resources/mediawiki.action/mediawiki.action.watch.ajax.js',
359 - 'dependencies' => 'mediawiki.util',
360 - ),
361 - 'mediawiki.special.preferences' => array(
362 - 'scripts' => 'resources/mediawiki.special/mediawiki.special.preferences.js',
363 - 'styles' => 'resources/mediawiki.special/mediawiki.special.preferences.css',
364 - 'messages' => array( 'email-address-validity-valid', 'email-address-validity-invalid' ),
365 - ),
366 - 'mediawiki.special.changeslist' => array(
367 - 'styles' => 'resources/mediawiki.special/mediawiki.special.changeslist.css',
368 - 'dependencies' => array( 'jquery.makeCollapsible' ),
369 - ),
370 - 'mediawiki.special.search' => array(
371 - 'scripts' => 'resources/mediawiki.special/mediawiki.special.search.js',
372 - ),
373 - 'mediawiki.special.upload' => array(
374 - // @todo: merge in remainder of mediawiki.legacy.upload
375 - 'scripts' => 'resources/mediawiki.special/mediawiki.special.upload.js',
376 - 'messages' => array( 'widthheight', 'size-bytes', 'size-kilobytes', 'size-megabytes', 'size-gigabytes' ),
377 - ),
378 - 'mediawiki.language' => array(
379 - 'scripts' => 'resources/mediawiki.language/mediawiki.language.js',
380 - 'languageScripts' => array(
381 - 'am' => 'resources/mediawiki.language/languages/am.js',
382 - 'ar' => 'resources/mediawiki.language/languages/ar.js',
383 - 'bat-smg' => 'resources/mediawiki.language/languages/bat-smg.js',
384 - 'be' => 'resources/mediawiki.language/languages/be.js',
385 - 'be-tarask' => 'resources/mediawiki.language/languages/be-tarask.js',
386 - 'bh' => 'resources/mediawiki.language/languages/bh.js',
387 - 'bs' => 'resources/mediawiki.language/languages/bs.js',
388 - 'cs' => 'resources/mediawiki.language/languages/cs.js',
389 - 'cu' => 'resources/mediawiki.language/languages/cu.js',
390 - 'cy' => 'resources/mediawiki.language/languages/cy.js',
391 - 'dsb' => 'resources/mediawiki.language/languages/dsb.js',
392 - 'fr' => 'resources/mediawiki.language/languages/fr.js',
393 - 'ga' => 'resources/mediawiki.language/languages/ga.js',
394 - 'gd' => 'resources/mediawiki.language/languages/gd.js',
395 - 'gv' => 'resources/mediawiki.language/languages/gv.js',
396 - 'he' => 'resources/mediawiki.language/languages/he.js',
397 - 'hi' => 'resources/mediawiki.language/languages/hi.js',
398 - 'hr' => 'resources/mediawiki.language/languages/hr.js',
399 - 'hsb' => 'resources/mediawiki.language/languages/hsb.js',
400 - 'hy' => 'resources/mediawiki.language/languages/hy.js',
401 - 'ksh' => 'resources/mediawiki.language/languages/ksh.js',
402 - 'ln' => 'resources/mediawiki.language/languages/ln.js',
403 - 'lt' => 'resources/mediawiki.language/languages/lt.js',
404 - 'lv' => 'resources/mediawiki.language/languages/lv.js',
405 - 'mg' => 'resources/mediawiki.language/languages/mg.js',
406 - 'mk' => 'resources/mediawiki.language/languages/mk.js',
407 - 'mo' => 'resources/mediawiki.language/languages/mo.js',
408 - 'mt' => 'resources/mediawiki.language/languages/mt.js',
409 - 'nso' => 'resources/mediawiki.language/languages/nso.js',
410 - 'pl' => 'resources/mediawiki.language/languages/pl.js',
411 - 'pt-br' => 'resources/mediawiki.language/languages/pt-br.js',
412 - 'ro' => 'resources/mediawiki.language/languages/ro.js',
413 - 'ru' => 'resources/mediawiki.language/languages/ru.js',
414 - 'se' => 'resources/mediawiki.language/languages/se.js',
415 - 'sh' => 'resources/mediawiki.language/languages/sh.js',
416 - 'sk' => 'resources/mediawiki.language/languages/sk.js',
417 - 'sl' => 'resources/mediawiki.language/languages/sl.js',
418 - 'sma' => 'resources/mediawiki.language/languages/sma.js',
419 - 'sr-ec' => 'resources/mediawiki.language/languages/sr-ec.js',
420 - 'sr-el' => 'resources/mediawiki.language/languages/sr-el.js',
421 - 'sr' => 'resources/mediawiki.language/languages/sr.js',
422 - 'ti' => 'resources/mediawiki.language/languages/ti.js',
423 - 'tl' => 'resources/mediawiki.language/languages/tl.js',
424 - 'uk' => 'resources/mediawiki.language/languages/uk.js',
425 - 'wa' => 'resources/mediawiki.language/languages/wa.js',
426 - ),
427 - ),
428 -
429 - 'mediawiki.language.parser' => new ResourceLoaderFileModule( array(
430 - 'scripts' => 'resources/mediawiki.language/mediawiki.language.parser.js',
431 - 'dependencies' => array( 'mediawiki.language', 'mediawiki.util' ),
432 - 'debugScripts' => 'resources/mediawiki.language/mediawiki.language.parserTest.js',
433 - // @@FIXME note the messages are only needed for debugScirpts
434 - // It appears that debugScripts can only be direct resource paths not 'modules'
435 - 'messages' => array( 'undelete_short', 'category-subcat-count' )
436 - ) ),
437 -
438 -
439 - /* mediawiki Legacy */
440 -
441 - 'mediawiki.legacy.ajax' => array(
442 - 'scripts' => 'skins/common/ajax.js',
443 - 'messages' => array(
444 - 'watch', 'unwatch', 'watching', 'unwatching', 'tooltip-ca-watch', 'tooltip-ca-unwatch',
445 - ),
446 - 'dependencies' => 'mediawiki.legacy.wikibits',
447 - ),
448 - 'mediawiki.legacy.block' => array(
449 - 'scripts' => 'skins/common/block.js',
450 - 'dependencies' => 'mediawiki.legacy.wikibits',
451 - ),
452 - 'mediawiki.legacy.commonPrint' => array(
453 - 'styles' => array( 'skins/common/commonPrint.css' => array( 'media' => 'print' ) ),
454 - ),
455 - 'mediawiki.legacy.config' => array(
456 - 'scripts' => 'skins/common/config.js',
457 - 'styles' => array( 'skins/common/config.css', 'skins/common/config-cc.css' ),
458 - 'dependencies' => 'mediawiki.legacy.wikibits',
459 - ),
460 - 'mediawiki.legacy.diff' => array(
461 - 'scripts' => 'skins/common/diff.js',
462 - 'styles' => 'skins/common/diff.css',
463 - 'dependencies' => 'mediawiki.legacy.wikibits',
464 - ),
465 - 'mediawiki.legacy.edit' => array(
466 - 'scripts' => 'skins/common/edit.js',
467 - 'dependencies' => 'mediawiki.legacy.wikibits',
468 - ),
469 - 'mediawiki.legacy.history' => array(
470 - 'scripts' => 'skins/common/history.js',
471 - 'dependencies' => 'mediawiki.legacy.wikibits',
472 - ),
473 - 'mediawiki.legacy.htmlform' => array(
474 - 'scripts' => 'skins/common/htmlform.js',
475 - 'dependencies' => 'mediawiki.legacy.wikibits',
476 - ),
477 - 'mediawiki.legacy.IEFixes' => array(
478 - 'scripts' => 'skins/common/IEFixes.js',
479 - 'dependencies' => 'mediawiki.legacy.wikibits',
480 - ),
481 - 'mediawiki.legacy.metadata' => array(
482 - 'scripts' => 'skins/common/metadata.js',
483 - 'dependencies' => 'mediawiki.legacy.wikibits',
484 - 'messages' => array( 'metadata-expand', 'metadata-collapse' ),
485 - ),
486 - 'mediawiki.legacy.mwsuggest' => array(
487 - 'scripts' => 'skins/common/mwsuggest.js',
488 - 'dependencies' => array( 'mediawiki.legacy.wikibits', 'jquery.client' ),
489 - 'messages' => array( 'search-mwsuggest-enabled', 'search-mwsuggest-disabled' ),
490 - ),
491 - 'mediawiki.legacy.password' => array(
492 - 'scripts' => 'skins/common/password.js',
493 - 'styles' => 'skins/common/password.css',
494 - 'dependencies' => 'mediawiki.legacy.wikibits',
495 - ),
496 - 'mediawiki.legacy.prefs' => array(
497 - 'scripts' => 'skins/common/prefs.js',
498 - 'dependencies' => array( 'mediawiki.legacy.wikibits', 'mediawiki.legacy.htmlform' ),
499 - ),
500 - 'mediawiki.legacy.preview' => array(
501 - 'scripts' => 'skins/common/preview.js',
502 - 'dependencies' => 'mediawiki.legacy.wikibits',
503 - ),
504 - 'mediawiki.legacy.protect' => array(
505 - 'scripts' => 'skins/common/protect.js',
506 - 'dependencies' => 'mediawiki.legacy.wikibits',
507 - ),
508 - 'mediawiki.legacy.search' => array(
509 - 'scripts' => 'skins/common/search.js',
510 - 'styles' => 'skins/common/search.css',
511 - 'dependencies' => 'mediawiki.legacy.wikibits',
512 - ),
513 - 'mediawiki.legacy.shared' => array(
514 - 'styles' => array( 'skins/common/shared.css' => array( 'media' => 'screen' ) ),
515 - ),
516 - 'mediawiki.legacy.oldshared' => array(
517 - 'styles' => array( 'skins/common/oldshared.css' => array( 'media' => 'screen' ) ),
518 - ),
519 - 'mediawiki.legacy.upload' => array(
520 - 'scripts' => 'skins/common/upload.js',
521 - 'dependencies' => 'mediawiki.legacy.wikibits',
522 - ),
523 - 'mediawiki.legacy.wikibits' => array(
524 - 'scripts' => 'skins/common/wikibits.js',
525 - 'dependencies' => 'mediawiki.language',
526 - 'messages' => array( 'showtoc', 'hidetoc' ),
527 - ),
528 - 'mediawiki.legacy.wikiprintable' => array(
529 - 'styles' => array( 'skins/common/wikiprintable.css' => array( 'media' => 'print' ) ),
530 - ),
531 -);
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki/mediawiki.js
@@ -1272,9 +1272,9 @@
12731273
12741274 /* Auto-register from pre-loaded startup scripts */
12751275
1276 -if ( typeof startUp === 'function' ) {
1277 - startUp();
1278 - delete startUp;
 1276+if ( typeof mwStartUp === 'function' ) {
 1277+ mwStartUp();
 1278+ delete mwStartUp;
12791279 }
12801280
12811281 // Add jQuery Cookie to initial payload (used in mediaWiki.user)
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki.language/mediawiki.language.parser.js
@@ -0,0 +1,240 @@
 2+/**
 3+* Mediawiki language text parser for handling mediawiki style {{PLURAL}} i81n template substitution
 4+* and basic [$1 link text] substitution.
 5+*/
 6+
 7+/**
 8+* MediaWiki wikitext "Parser" constructor
 9+*
 10+* @param {String} wikiText the wikitext to be parsed
 11+* @return {Object} parserObj returns a parser object that has methods:
 12+* getHtml() which returns the html representation of the text
 13+*/
 14+mediaWiki.language.parser = function( wikiText, options) {
 15+ // return the parserObj
 16+ this.init( wikiText, options );
 17+};
 18+
 19+mediaWiki.language.parser.prototype = {
 20+ // The parser output string ( lazy init )
 21+ '_htmlOutput': false,
 22+
 23+ // The wiki text to be parsed ( required parameter of the constructor )
 24+ '_wikiText' : '',
 25+
 26+ // The default parser options
 27+ '_defaultParserOptions' : {
 28+ /**
 29+ * Name template processors ( like PLURAL, GENDER )
 30+ *
 31+ * Magic named templates are passed off to their associated function
 32+ *
 33+ * Dependent functions should be defined BEFORE the parser is included, or
 34+ * passed into the parser as part of the runtime options
 35+ */
 36+ 'templateProcessors' : {
 37+ 'PLURAL' : mw.language.pluralProcessor
 38+ }
 39+ },
 40+
 41+ // Internal parser options ( set via parserOptions argument and default parser options )
 42+ '_options' : {},
 43+
 44+ /**
 45+ * constructor
 46+ */
 47+ 'init' : function( wikiText, parserOptions ) {
 48+ this._wikiText = wikiText;
 49+ this.options = $.extend( this._defaultParserOptions, parserOptions);
 50+ },
 51+
 52+ /**
 53+ * Update the wiki text value and invalidate the cache
 54+ *
 55+ * @param {string} wikiText
 56+ * The wiki text string the parser works on.
 57+ */
 58+ 'updateText' : function( wikiText ) {
 59+ this._wikiText = wikiText;
 60+
 61+ // Invalidate the output ( will force a re-parse )
 62+ this._htmlOutput = false;
 63+ },
 64+
 65+ /**
 66+ * Recursively parse out template:
 67+ *
 68+ * contains a few local scope helper functions:
 69+ */
 70+ 'parse': function() {
 71+ var _this = this;
 72+
 73+ // Setup local swap string constants
 74+ var JQUERY_SWAP_STRING = 'ZjQuerySwapZ';
 75+ var LINK_SWAP_STRING = 'ZreplaceZ';
 76+
 77+ // Local scope functions for parser:
 78+
 79+ /**
 80+ * Recurse through text and tokenize the open and close templates into "node" objects
 81+ */
 82+ function recurseTokenizeNodes ( text ) {
 83+ var node = { };
 84+ mw.log( 'recurseTokenizeNodes:' + text );
 85+ // Inspect each char
 86+ for ( var a = 0; a < text.length; a++ ) {
 87+ if ( text.charAt(a) == '{' && text.charAt(a + 1) == '{' ) {
 88+ a = a + 2;
 89+ node['parent'] = node;
 90+ if ( !node['child'] ) {
 91+ node['child'] = new Array();
 92+ }
 93+
 94+ node['child'].push( recurseTokenizeNodes( text.substr( a ) ) );
 95+ } else if ( text.charAt(a) == '}' && text.charAt(a + 1) == '}' ) {
 96+ a++;
 97+ if ( !node['parent'] ) {
 98+ return node;
 99+ }
 100+ node = node['parent'];
 101+ }
 102+ if ( !node['text'] ) {
 103+ node['text'] = '';
 104+ }
 105+ // Don't put }} closures into output:
 106+ if ( text.charAt(a) && text.charAt(a) != '}' ) {
 107+ node['text'] += text.charAt(a);
 108+ }
 109+ }
 110+ return node;
 111+ }
 112+
 113+ /**
 114+ * Parse template text as template name and named params
 115+ * @param {String} templateString Template String to be parsed
 116+ */
 117+ function parseTemplateText( templateString ) {
 118+ var templateObject = { };
 119+
 120+ mw.log( 'parseTemplateText:' + templateString );
 121+
 122+ // Get template name:
 123+ templateName = templateString.split( '\|' ).shift() ;
 124+ templateName = templateName.split( '\{' ).shift() ;
 125+ templateName = templateName.replace( /^\s+|\s+$/g, "" ); //trim
 126+
 127+ // Check for arguments:
 128+ if ( templateName.split( ':' ).length == 1 ) {
 129+ templateObject["name"] = templateName;
 130+ } else {
 131+ templateObject["name"] = templateName.split( ':' ).shift();
 132+ templateObject["arg"] = templateName.split( ':' ).pop();
 133+ }
 134+
 135+ var paramSet = templateString.split( '\|' );
 136+ paramSet.splice( 0, 1 );
 137+ if ( paramSet.length ) {
 138+ templateObject.parameters = new Array();
 139+ for ( var pInx in paramSet ) {
 140+ var paramString = paramSet[ pInx ];
 141+ // check for empty param
 142+ if ( paramString == '' ) {
 143+ templateObject.parameters[ pInx ] = '';
 144+ continue;
 145+ }
 146+ for ( var b = 0 ; b < paramString.length ; b++ ) {
 147+ if ( paramString[b] == '=' && b > 0 && b < paramString.length && paramString[b - 1] != '\\' ) {
 148+ // named param
 149+ templateObject.parameters[ paramString.split( '=' ).shift() ] = paramString.split( '=' ).pop();
 150+ } else {
 151+ // indexed param
 152+ templateObject.parameters[ pInx ] = paramString;
 153+ }
 154+ }
 155+ }
 156+ }
 157+ return templateObject;
 158+ }
 159+
 160+ /**
 161+ * Get template text using the templateProcesors
 162+ */
 163+ function getTextFromTemplateNode( node ) {
 164+ node.templateObject = parseTemplateText ( node.text );
 165+ // Do magic swap if template key found in this.options.templateProcessors
 166+ if ( node.templateObject.name in _this.options.templateProcessors ) {
 167+ var nodeText = _this.options.templateProcessors[ node.templateObject.name ]( node.templateObject );
 168+ return nodeText;
 169+ } else {
 170+ // don't swap just return text
 171+ return node.text;
 172+ }
 173+ };
 174+
 175+ /**
 176+ * recurse_magic_swap
 177+ *
 178+ * Go the inner most child first then swap upward:
 179+ */
 180+ var parentNode = null;
 181+ function recurse_magic_swap( node ) {
 182+ if ( !parentNode )
 183+ parentNode = node;
 184+
 185+ if ( node['child'] ) {
 186+ // swap all the children:
 187+ for ( var i in node['child'] ) {
 188+ var nodeText = recurse_magic_swap( node['child'][i] );
 189+ // swap it into current
 190+ if ( node.text ) {
 191+ node.text = node.text.replace( node['child'][i].text, nodeText );
 192+ }
 193+ // swap into parent
 194+ parentNode.text = parentNode.text.replace( node['child'][i].text, nodeText );
 195+ }
 196+ // Get the updated node text
 197+ var nodeText = getTextFromTemplateNode( node );
 198+ parentNode.text = parentNode.text.replace( node.text , nodeText );
 199+
 200+ // Return the node text
 201+ return node.text;
 202+ } else {
 203+ return getTextFromTemplateNode( node );
 204+ }
 205+ }
 206+
 207+ // Parse out the template node structure:
 208+ this.parentNode = recurseTokenizeNodes ( this._wikiText );
 209+
 210+ // Strip out the parent from the root
 211+ this.parentNode['parent'] = null;
 212+
 213+ // Do the recursive magic swap on the node structure
 214+ this._htmlOutput = recurse_magic_swap( this.parentNode );
 215+
 216+ // Do link swap
 217+ this._htmlOutput = this._htmlOutput;
 218+ },
 219+
 220+ /**
 221+ * Returns the transformed wikitext
 222+ *
 223+ * Build output from swappable index
 224+ * (all transforms must be expanded in parse stage and linearly rebuilt)
 225+ *
 226+ * @@NOTE
 227+ * Alternatively we could build output using a place-holder & replace system
 228+ * (this lets us be slightly more sloppy with ordering and indexes, but probably slower)
 229+ *
 230+ * Ideal: we build a 'wiki DOM'
 231+ * When editing you update the data structure directly
 232+ * Then in output time you just go DOM->html-ish output without re-parsing the whole thing
 233+ */
 234+ 'getHTML': function() {
 235+ // wikiText updates should invalidate _htmlOutput
 236+ if ( ! this._htmlOutput ) {
 237+ this.parse();
 238+ }
 239+ return this._htmlOutput;
 240+ }
 241+};
\ No newline at end of file
Property changes on: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki.language/mediawiki.language.parser.js
___________________________________________________________________
Added: svn:mime-type
1242 + text/plain
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki.language/mediawiki.language.parserTest.js
@@ -0,0 +1,844 @@
 2+/**
 3+ * mediaWiki.language.parser.test Test Suite
 4+ *
 5+ * This script tests mediaWiki language transform system against the php counterpart.
 6+ *
 7+ * Available on "/Special:BlankPage?action=mw.language.parserTest&debug=true")
 8+ *
 9+ * @author Michael Dale <mdale@wikimedia.org>
 10+ */
 11+
 12+(function ($, mw) {
 13+
 14+mw.language.parserTest = {
 15+ 'init': function(){
 16+ // Make sure we are on the test page ( this will change once we explicitly include test files on test pages )
 17+ if (wgCanonicalSpecialPageName == 'Blankpage' && mw.util.getParamValue('action') === 'mw.language.parserTest') {
 18+ this.setPageContent();
 19+ this.setupParseTests();
 20+ }
 21+ },
 22+ 'setPageContent': function(){
 23+ $('#firstHeading').text('Test Javascript plural msg transformations');
 24+ mw.util.$content.html(
 25+ '<span style="float:left;width:400px;padding:3px;">' +
 26+ 'Run Test transform<br />' +
 27+ '<a id="runAll" href="#">Run all <span id="languageCount">...</span> tests</a> ( takes a while ) <br> '+
 28+
 29+ '<a id="runLang" href="#">Run Language Key</a>:<input size="5" id="testLangKey" name = "testLangKey" value="en"/>'+
 30+ '</span>' +
 31+ '<span style="float:left;width:300px;">'+
 32+ 'Run Custom transform: <br />'+
 33+ 'Value (separate by comma ): <input size="30" id="customValue" name="customValue" value="4,3"/> <br>'+
 34+ 'Msg Swap Text: '+
 35+ '<textarea cols="60" rows="2" id="customMsgText" name="customMsgText" >'+
 36+ '{{PLURAL:$2|This category has only the following subcategory.|'+
 37+ 'This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, '+
 38+ 'out of $2 total.}}'+
 39+ '</textarea>'+
 40+ '<input id="runCustomTransform" type="button" value="Run Custom Transform">'+
 41+
 42+ '</span>'+
 43+ '<div style="clear:both"></div>'+
 44+ '<br />'+
 45+
 46+ '<div id="score_card" style="font-size:large"></div>'+
 47+ '<table style="border:1px solid" id="table_out"></table>'
 48+ );
 49+ },
 50+
 51+
 52+ /**
 53+ * Sets up the parser tests and binds the html actions
 54+ */
 55+ 'setupParseTests' : function(){
 56+ mw.log('setupParseTests::');
 57+ // For just setting one or two to test at a time for debug
 58+
 59+ // Update the language count
 60+ var count=0;
 61+ for( var i in mw.language.names ){
 62+ count++;
 63+ }
 64+ $('#languageCount').text( count );
 65+
 66+ var headerRowHtml = '<tr style="border:1px solid">' +
 67+ '<td style="border:1px solid" >$1[,$2]</td>' +
 68+ '<td style="border:1px solid" width="14%">Msg key</td>' +
 69+ '<td style="border:1px solid" width="34%">Msg text</td>' +
 70+ '<td style="border:1px solid" width="24%">Msg Transform JS</td>' +
 71+ '<td style="border:1px solid" width="24%">Msg Transform Mw</td>' +
 72+ '</tr>';
 73+
 74+ // Setup bindings:
 75+ // Custom transform test
 76+ $('#runCustomTransform').click( function(){
 77+ mw.log('runCustomTransform');
 78+ // Add the custom message:
 79+ mediaWiki.messages.set({ 'mwe-custom-msg': $('#customMsgText').val() });
 80+
 81+ // Empty the table
 82+ $('#table_out,#score_card').empty();
 83+
 84+ // Add table header:
 85+ $('#table_out').html( headerRowHtml +
 86+ '<tr>' +
 87+ '<td>' + $('#customMsgText').val() + '</td>' +
 88+ '<td>mwe-custom-msg</td>' +
 89+ '<td>' + $('#customMsgText').val() + '</td>' +
 90+ '<td id="jsMessageText"></td>' +
 91+ '<td id="mwMessageTransform"></td>' +
 92+ '<tr>'
 93+ );
 94+
 95+ // Set the mw message to loading
 96+ $('#mwMessageTransform').text(
 97+ "note custom messages can not be parsed via the mediaWiki api at this point in time"
 98+ ).css('color', 'red');
 99+
 100+ // Output the js msg:
 101+ var msgArgs = $('#customValue').val().split(',');
 102+
 103+ $('#jsMessageText').append(
 104+ mediaWiki.msg( 'mwe-custom-msg', msgArgs )
 105+ );
 106+
 107+ });
 108+
 109+ $('#runLang').click(function(){
 110+ mw.log('runLang');
 111+ $('#table_out,#score_card').empty();
 112+ if( !mw.language.names[ $('#testLangKey').val() ] ){
 113+ alert( escape( $('#testLangKey').val() ) + ' does not appear to be a valid language key' );
 114+ } else {
 115+ doLanguageTransformTable( new Array( $('#testLangKey').val() ) )
 116+ }
 117+ });
 118+
 119+ $('#runAll').click(function(){
 120+ mw.log('runAll');
 121+ $('#table_out,#score_card').empty();
 122+ // Build the langTestSet from mw.language.names
 123+ var langTestSet = []
 124+ for( var i in mw.language.names ) {
 125+ langTestSet.push( i ) ;
 126+ }
 127+ doLanguageTransformTable( langTestSet );
 128+ });
 129+
 130+ // Set-up base convert plural and gender (to restore for non-transform languages )
 131+ var baseConvertPlural = mw.language.convertPlural;
 132+
 133+ // Do manual script loaders calls to test multiple languages:
 134+ function doLanguageTransformTable( langSet ){
 135+ $('#table_out').html( '<span class="loadingSpinner">loading...</span>' );
 136+ //build table output:
 137+ var messageTestSet = {
 138+ 'undelete_short' : [ 0, 1, 2, 5, 21, 101 ],
 139+ //category-subcat-count' has two params:
 140+ 'category-subcat-count' : [
 141+ [0,10],
 142+ [1,2],
 143+ [3,30]
 144+ ]
 145+ };
 146+
 147+ var passTest=0;
 148+ var failTest=0;
 149+ var testCount=0;
 150+
 151+ /**
 152+ * Process a language key test set
 153+ */
 154+ function doProcLangKey( langKey ){
 155+ mw.log(" doProcLangKey: " + langKey );
 156+ // Clear out the old digitTransformTable
 157+ mw.language.digitTransformTable = null;
 158+ // Load the current language js file if it has a langKey
 159+ var transformLangKey = mw.language.getLangTransformKey ( langKey );
 160+ if( transformLangKey != 'en' ){
 161+ mw.log( langKey + " load msg transform" );
 162+ //var langName = 'Language' + transformLangKey.substr(0,1).toUpperCase() + transformLangKey.substr( 1, transformLangKey.length );
 163+ $.getScript( wgScriptPath + '/resources/mediawiki.language/languages/classes/' + langName.toLowerCase() + '.js' , function(){
 164+ doLangTest();
 165+ });
 166+ } else {
 167+ mw.log( langKey + " no msg transform restore base" );
 168+ //If no transform, restore base plural
 169+ mw.language.convertPlural = baseConvertPlural;
 170+ doLangTest();
 171+ }
 172+
 173+ function doLangTest(){
 174+ mw.log("doLangTest::" + langKey);
 175+ // Load the updated messages for the current language Key
 176+ $.getScript( wgScriptPath + '/load.php?modules=mediawiki.language.parser&debug=true&only=messages&lang='+langKey, function(){
 177+ var o='';
 178+ o+='<tr><td colspan="6" height="20" style="font-size:large"><b>Lang:' + langKey + '</b></td></tr>';
 179+
 180+ // Now for each language msg:
 181+ $.each(messageTestSet, function(mKey, mTestSet){
 182+ //output table names:
 183+ o+= headerRowHtml;
 184+
 185+ //for each number value
 186+ for( var i in mTestSet ){
 187+ var numVal = mTestSet[i];
 188+ var numKey = i;
 189+ var tkey = mKey + '_' + numKey + '_' + langKey;
 190+ o+= '<tr style="border:1px solid">' +
 191+ '<td style="border:1px solid" >' + numVal + '</td>' +
 192+ '<td style="border:1px solid" >' + mKey + '</td>' +
 193+ '<td style="border:1px solid" >' + mw.msgNoTrans( mKey ) + '</td>' +
 194+ '<td style="border:1px solid" id="' + tkey + '_js">' + mw.msg( mKey, numVal ) + '</td>';
 195+ //show mw col:
 196+ if( mKey.substr(0, 5) == 'test_' ){
 197+ o+='<td style="border:1px solid"> (test msg) </td>';
 198+ }else{
 199+ o+='<td style="border:1px solid" id="' + tkey + '">loading...</td>';
 200+
 201+ //get transform from mw (& compare and highlight)
 202+ function doPopWmMsg( mKey, numVal, numKey ){
 203+ // Set the local tkey:
 204+ var tkey = mKey + '_' + numKey + '_' + langKey;
 205+ testCount++;
 206+ $('#score_card').html('Running Tests <span id="perc_done">0</sapn>% done');
 207+ var msgparam = (typeof numVal== 'object')? numVal.join( '|' ) : numVal;
 208+
 209+ var request = {
 210+ 'action' : 'query',
 211+ 'format' : 'json',
 212+ 'meta' : 'allmessages',
 213+ 'ammessages' : mKey,
 214+ 'amlang' : langKey,
 215+ 'amargs' : msgparam,
 216+ 'amenableparser' : true
 217+ };
 218+
 219+ $.getJSON( wgScriptPath + '/api.php', request, function( data ) {
 220+ var t = '#'+ tkey;
 221+ var $target = $( t ) ;
 222+ if( data.query && data.query.allmessages && data.query.allmessages[0]){
 223+ var msgText = data.query.allmessages && data.query.allmessages[0]['*'];
 224+ if( msgText == '' )
 225+ msgText = ' %missing% ';
 226+ $target.html( msgText );
 227+ var js_txt = $.trim( $(t + '_js').text().replace('\n', '') );
 228+ var php_txt = $.trim( msgText );
 229+ // Just get the part in the <p> to compare with js version
 230+ if( js_txt != php_txt ){
 231+ $target.css('color', 'red');
 232+ failTest++;
 233+ }else{
 234+ $target.css('color', 'green');
 235+ passTest++;
 236+ }
 237+ var perc = ( failTest + passTest ) / testCount
 238+ if( perc != 1){
 239+ $('#perc_done').html( Math.round(perc*1000)/1000 + '%');
 240+ }else{
 241+ var failHtlm = (failTest == 0)?failTest: '<span style="color:red">'+ failTest+'</span>';
 242+ $('#score_card').html(
 243+ 'Passed: <span style="color:green">' + passTest + '</span> Failed:' + failHtlm
 244+ );
 245+
 246+ // Done with this lang... call outer function if we have lang keys left to proccess:
 247+ if( langSet.length !=0 ){
 248+ doProcLangKey( langSet.pop() );
 249+ }
 250+ }
 251+ }else{
 252+ $target.html(' error ').css('color', 'red');
 253+ }
 254+ });
 255+ };
 256+ // pop off an anonymous function call
 257+ doPopWmMsg(mKey, numVal, numKey);
 258+ }
 259+ o+='</tr>';
 260+ }
 261+ //output a spacer:
 262+ o+='<tr><td colspan="6" height="20"> </td></tr>';
 263+ });
 264+ // remove the loading text
 265+ $( '.loadingSpinner').remove();
 266+ //Put the output into the page:
 267+ $('#table_out').append( o );
 268+
 269+ });
 270+ }
 271+ } // process lang key:
 272+
 273+ doProcLangKey( langSet.pop() );
 274+ }
 275+ }
 276+
 277+}
 278+// Once the dom is ready init the test page:
 279+$(function () {
 280+ mw.language.parserTest.init();
 281+});
 282+
 283+/**
 284+* Get a language transform key
 285+* returns default "en" fallback if none found
 286+* @param String langKey The language key to be checked
 287+*
 288+
 289+*/
 290+
 291+mw.language.getLangTransformKey = function( langKey ) {
 292+ if( mw.language.fallbackTransformMap[ langKey ] ) {
 293+ langKey = mw.language.fallbackTransformMap[ langKey ];
 294+ }
 295+ // Make sure the langKey has a transformClass:
 296+ for( var i = 0; i < mw.language.transformClass.length ; i++ ) {
 297+ if( langKey == mw.language.transformClass[i] ){
 298+ return langKey
 299+ }
 300+ }
 301+ // By default return the base 'en' class
 302+ return 'en';
 303+};
 304+
 305+/**
 306+ * @@FIXME this should be handled dynamically handled in the resource loader
 307+ * so it keeps up-to-date with php maping.
 308+ * ( not explicitly listed here )
 309+ */
 310+mw.language.fallbackTransformMap = {
 311+ 'mwl' : 'pt',
 312+ 'ace' : 'id',
 313+ 'hsb' : 'de',
 314+ 'frr' : 'de',
 315+ 'pms' : 'it',
 316+ 'dsb' : 'de',
 317+ 'gan' : 'gan-hant',
 318+ 'lzz' : 'tr',
 319+ 'ksh' : 'de',
 320+ 'kl' : 'da',
 321+ 'fur' : 'it',
 322+ 'zh-hk' : 'zh-hant',
 323+ 'kk' : 'kk-cyrl',
 324+ 'zh-my' : 'zh-sg',
 325+ 'nah' : 'es',
 326+ 'sr' : 'sr-ec',
 327+ 'ckb-latn' : 'ckb-arab',
 328+ 'mo' : 'ro',
 329+ 'ay' : 'es',
 330+ 'gl' : 'pt',
 331+ 'gag' : 'tr',
 332+ 'mzn' : 'fa',
 333+ 'ruq-cyrl' : 'mk',
 334+ 'kk-arab' : 'kk-cyrl',
 335+ 'pfl' : 'de',
 336+ 'zh-yue' : 'yue',
 337+ 'ug' : 'ug-latn',
 338+ 'ltg' : 'lv',
 339+ 'nds' : 'de',
 340+ 'sli' : 'de',
 341+ 'mhr' : 'ru',
 342+ 'sah' : 'ru',
 343+ 'ff' : 'fr',
 344+ 'ab' : 'ru',
 345+ 'ko-kp' : 'ko',
 346+ 'sg' : 'fr',
 347+ 'zh-tw' : 'zh-hant',
 348+ 'map-bms' : 'jv',
 349+ 'av' : 'ru',
 350+ 'nds-nl' : 'nl',
 351+ 'pt-br' : 'pt',
 352+ 'ce' : 'ru',
 353+ 'vep' : 'et',
 354+ 'wuu' : 'zh-hans',
 355+ 'pdt' : 'de',
 356+ 'krc' : 'ru',
 357+ 'gan-hant' : 'zh-hant',
 358+ 'bqi' : 'fa',
 359+ 'as' : 'bn',
 360+ 'bm' : 'fr',
 361+ 'gn' : 'es',
 362+ 'tt' : 'ru',
 363+ 'zh-hant' : 'zh-hans',
 364+ 'hif' : 'hif-latn',
 365+ 'zh' : 'zh-hans',
 366+ 'kaa' : 'kk-latn',
 367+ 'lij' : 'it',
 368+ 'vot' : 'fi',
 369+ 'ii' : 'zh-cn',
 370+ 'ku-arab' : 'ckb-arab',
 371+ 'xmf' : 'ka',
 372+ 'vmf' : 'de',
 373+ 'zh-min-nan' : 'nan',
 374+ 'bcc' : 'fa',
 375+ 'an' : 'es',
 376+ 'rgn' : 'it',
 377+ 'qu' : 'es',
 378+ 'nb' : 'no',
 379+ 'bar' : 'de',
 380+ 'lbe' : 'ru',
 381+ 'su' : 'id',
 382+ 'pcd' : 'fr',
 383+ 'glk' : 'fa',
 384+ 'lb' : 'de',
 385+ 'kk-kz' : 'kk-cyrl',
 386+ 'kk-tr' : 'kk-latn',
 387+ 'inh' : 'ru',
 388+ 'mai' : 'hi',
 389+ 'tp' : 'tokipona',
 390+ 'kk-latn' : 'kk-cyrl',
 391+ 'ba' : 'ru',
 392+ 'nap' : 'it',
 393+ 'ruq' : 'ruq-latn',
 394+ 'tt-cyrl' : 'ru',
 395+ 'lad' : 'es',
 396+ 'dk' : 'da',
 397+ 'de-ch' : 'de',
 398+ 'be-x-old' : 'be-tarask',
 399+ 'za' : 'zh-hans',
 400+ 'kk-cn' : 'kk-arab',
 401+ 'shi' : 'ar',
 402+ 'crh' : 'crh-latn',
 403+ 'yi' : 'he',
 404+ 'pdc' : 'de',
 405+ 'eml' : 'it',
 406+ 'uk' : 'ru',
 407+ 'kv' : 'ru',
 408+ 'koi' : 'ru',
 409+ 'cv' : 'ru',
 410+ 'zh-cn' : 'zh-hans',
 411+ 'de-at' : 'de',
 412+ 'jut' : 'da',
 413+ 'vec' : 'it',
 414+ 'zh-mo' : 'zh-hk',
 415+ 'fiu-vro' : 'vro',
 416+ 'frp' : 'fr',
 417+ 'mg' : 'fr',
 418+ 'ruq-latn' : 'ro',
 419+ 'sa' : 'hi',
 420+ 'lmo' : 'it',
 421+ 'kiu' : 'tr',
 422+ 'tcy' : 'kn',
 423+ 'srn' : 'nl',
 424+ 'jv' : 'id',
 425+ 'vls' : 'nl',
 426+ 'zea' : 'nl',
 427+ 'ty' : 'fr',
 428+ 'szl' : 'pl',
 429+ 'rmy' : 'ro',
 430+ 'wo' : 'fr',
 431+ 'vro' : 'et',
 432+ 'udm' : 'ru',
 433+ 'bpy' : 'bn',
 434+ 'mrj' : 'ru',
 435+ 'ckb' : 'ckb-arab',
 436+ 'xal' : 'ru',
 437+ 'de-formal' : 'de',
 438+ 'myv' : 'ru',
 439+ 'ku' : 'ku-latn',
 440+ 'crh-cyrl' : 'ru',
 441+ 'gsw' : 'de',
 442+ 'rue' : 'uk',
 443+ 'iu' : 'ike-cans',
 444+ 'stq' : 'de',
 445+ 'gan-hans' : 'zh-hans',
 446+ 'scn' : 'it',
 447+ 'arn' : 'es',
 448+ 'ht' : 'fr',
 449+ 'zh-sg' : 'zh-hans',
 450+ 'bat-smg' : 'lt',
 451+ 'aln' : 'sq',
 452+ 'tg' : 'tg-cyrl',
 453+ 'li' : 'nl',
 454+ 'simple' : 'en',
 455+ 'os' : 'ru',
 456+ 'ln' : 'fr',
 457+ 'als' : 'gsw',
 458+ 'zh-classical' : 'lzh',
 459+ 'arz' : 'ar',
 460+ 'wa' : 'fr'
 461+ };
 462+
 463+/**
 464+ * Language classes ( which have a file in /languages/classes/Language{code}.js )
 465+ * ( for languages that override default transforms )
 466+ *
 467+ * @@FIXME again not needed if the resource loader manages this mapping and gives
 468+ * us the "right" transform class regardless of what language key we request.
 469+ */
 470+mw.language.transformClass = ['am', 'ar', 'bat_smg', 'be_tarak', 'be', 'bh',
 471+ 'bs', 'cs', 'cu', 'cy', 'dsb', 'fr', 'ga', 'gd', 'gv', 'he', 'hi',
 472+ 'hr', 'hsb', 'hy', 'ksh', 'ln', 'lt', 'lv', 'mg', 'mk', 'mo', 'mt',
 473+ 'nso', 'pl', 'pt_br', 'ro', 'ru', 'se', 'sh', 'sk', 'sl', 'sma',
 474+ 'sr_ec', 'sr_el', 'sr', 'ti', 'tl', 'uk', 'wa' ];
 475+
 476+/**
 477+ * List of all languages mediaWiki supports:
 478+ *
 479+ * Similar to api query:
 480+ * http://commons.wikimedia.org/w/api.php?action=query&meta=siteinfo&siprop=languages&format=jsonfm
 481+ *
 482+ * @@FIXME This should be dynamically generated via the resource loader and identified as a dependency of this test file.
 483+ *
 484+ */
 485+mediaWiki.language.names = {
 486+ "aa" : "Qaf\u00e1r af",
 487+ "ab" : "\u0410\u04a7\u0441\u0443\u0430",
 488+ "ace" : "Ac\u00e8h",
 489+ "af" : "Afrikaans",
 490+ "ak" : "Akan",
 491+ "aln" : "Geg\u00eb",
 492+ "als" : "Alemannisch",
 493+ "am" : "\u12a0\u121b\u122d\u129b",
 494+ "an" : "Aragon\u00e9s",
 495+ "ang" : "Anglo-Saxon",
 496+ "ar" : "\u0627\u0644\u0639\u0631\u0628\u064a\u0629",
 497+ "arc" : "\u0710\u072a\u0721\u071d\u0710",
 498+ "arn" : "Mapudungun",
 499+ "arz" : "\u0645\u0635\u0631\u0649",
 500+ "as" : "\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be",
 501+ "ast" : "Asturianu",
 502+ "av" : "\u0410\u0432\u0430\u0440",
 503+ "avk" : "Kotava",
 504+ "ay" : "Aymar aru",
 505+ "az" : "Az\u0259rbaycan",
 506+ "ba" : "\u0411\u0430\u0448\u04a1\u043e\u0440\u0442",
 507+ "bar" : "Boarisch",
 508+ "bat-smg" : "\u017demait\u0117\u0161ka",
 509+ "bcc" : "\u0628\u0644\u0648\u0686\u06cc \u0645\u06a9\u0631\u0627\u0646\u06cc",
 510+ "bcl" : "Bikol Central",
 511+ "be" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f",
 512+ "be-tarask" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)",
 513+ "be-x-old" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)",
 514+ "bg" : "\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438",
 515+ "bh" : "\u092d\u094b\u091c\u092a\u0941\u0930\u0940",
 516+ "bi" : "Bislama",
 517+ "bm" : "Bamanankan",
 518+ "bn" : "\u09ac\u09be\u0982\u09b2\u09be",
 519+ "bo" : "\u0f56\u0f7c\u0f51\u0f0b\u0f61\u0f72\u0f42",
 520+ "bpy" : "\u0987\u09ae\u09be\u09b0 \u09a0\u09be\u09b0\/\u09ac\u09bf\u09b7\u09cd\u09a3\u09c1\u09aa\u09cd\u09b0\u09bf\u09af\u09bc\u09be \u09ae\u09a3\u09bf\u09aa\u09c1\u09b0\u09c0",
 521+ "bqi" : "\u0628\u062e\u062a\u064a\u0627\u0631\u064a",
 522+ "br" : "Brezhoneg",
 523+ "bs" : "Bosanski",
 524+ "bug" : "\u1a05\u1a14 \u1a15\u1a18\u1a01\u1a17",
 525+ "bxr" : "\u0411\u0443\u0440\u044f\u0430\u0434",
 526+ "ca" : "Catal\u00e0",
 527+ "cbk-zam" : "Chavacano de Zamboanga",
 528+ "cdo" : "M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304",
 529+ "ce" : "\u041d\u043e\u0445\u0447\u0438\u0439\u043d",
 530+ "ceb" : "Cebuano",
 531+ "ch" : "Chamoru",
 532+ "cho" : "Choctaw",
 533+ "chr" : "\u13e3\u13b3\u13a9",
 534+ "chy" : "Tsets\u00eahest\u00e2hese",
 535+ "ckb" : "Soran\u00ee \/ \u06a9\u0648\u0631\u062f\u06cc",
 536+ "ckb-latn" : "\u202aSoran\u00ee (lat\u00een\u00ee)\u202c",
 537+ "ckb-arab" : "\u202b\u06a9\u0648\u0631\u062f\u06cc (\u0639\u06d5\u0631\u06d5\u0628\u06cc)\u202c",
 538+ "co" : "Corsu",
 539+ "cr" : "N\u0113hiyaw\u0113win \/ \u14c0\u1426\u1403\u152d\u140d\u140f\u1423",
 540+ "crh" : "Q\u0131r\u0131mtatarca",
 541+ "crh-latn" : "\u202aQ\u0131r\u0131mtatarca (Latin)\u202c",
 542+ "crh-cyrl" : "\u202a\u041a\u044a\u044b\u0440\u044b\u043c\u0442\u0430\u0442\u0430\u0440\u0434\u0436\u0430 (\u041a\u0438\u0440\u0438\u043b\u043b)\u202c",
 543+ "cs" : "\u010cesky",
 544+ "csb" : "Kasz\u00ebbsczi",
 545+ "cu" : "\u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f",
 546+ "cv" : "\u0427\u04d1\u0432\u0430\u0448\u043b\u0430",
 547+ "cy" : "Cymraeg",
 548+ "da" : "Dansk",
 549+ "de" : "Deutsch",
 550+ "de-at" : "\u00d6sterreichisches Deutsch",
 551+ "de-ch" : "Schweizer Hochdeutsch",
 552+ "de-formal" : "Deutsch (Sie-Form)",
 553+ "diq" : "Zazaki",
 554+ "dk" : "Dansk (deprecated:da)",
 555+ "dsb" : "Dolnoserbski",
 556+ "dv" : "\u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0",
 557+ "dz" : "\u0f47\u0f7c\u0f44\u0f0b\u0f41",
 558+ "ee" : "E\u028begbe",
 559+ "el" : "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac",
 560+ "eml" : "Emili\u00e0n e rumagn\u00f2l",
 561+ "en" : "English",
 562+ "en-gb" : "British English",
 563+ "eo" : "Esperanto",
 564+ "es" : "Espa\u00f1ol",
 565+ "et" : "Eesti",
 566+ "eu" : "Euskara",
 567+ "ext" : "Estreme\u00f1u",
 568+ "fa" : "\u0641\u0627\u0631\u0633\u06cc",
 569+ "ff" : "Fulfulde",
 570+ "fi" : "Suomi",
 571+ "fiu-vro" : "V\u00f5ro",
 572+ "fj" : "Na Vosa Vakaviti",
 573+ "fo" : "F\u00f8royskt",
 574+ "fr" : "Fran\u00e7ais",
 575+ "frc" : "Fran\u00e7ais cadien",
 576+ "frp" : "Arpetan",
 577+ "fur" : "Furlan",
 578+ "fy" : "Frysk",
 579+ "ga" : "Gaeilge",
 580+ "gag" : "Gagauz",
 581+ "gan" : "\u8d1b\u8a9e",
 582+ "gan-hans" : "\u8d63\u8bed(\u7b80\u4f53)",
 583+ "gan-hant" : "\u8d1b\u8a9e(\u7e41\u9ad4)",
 584+ "gd" : "G\u00e0idhlig",
 585+ "gl" : "Galego",
 586+ "glk" : "\u06af\u06cc\u0644\u06a9\u06cc",
 587+ "gn" : "Ava\u00f1e'\u1ebd",
 588+ "got" : "\ud800\udf32\ud800\udf3f\ud800\udf44\ud800\udf39\ud800\udf43\ud800\udf3a",
 589+ "grc" : "\u1f08\u03c1\u03c7\u03b1\u03af\u03b1 \u1f11\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u1f74",
 590+ "gsw" : "Alemannisch",
 591+ "gu" : "\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0",
 592+ "gv" : "Gaelg",
 593+ "ha" : "\u0647\u064e\u0648\u064f\u0633\u064e",
 594+ "hak" : "Hak-k\u00e2-fa",
 595+ "haw" : "Hawai`i",
 596+ "he" : "\u05e2\u05d1\u05e8\u05d9\u05ea",
 597+ "hi" : "\u0939\u093f\u0928\u094d\u0926\u0940",
 598+ "hif" : "Fiji Hindi",
 599+ "hif-deva" : "\u092b\u093c\u0940\u091c\u0940 \u0939\u093f\u0928\u094d\u0926\u0940",
 600+ "hif-latn" : "Fiji Hindi",
 601+ "hil" : "Ilonggo",
 602+ "ho" : "Hiri Motu",
 603+ "hr" : "Hrvatski",
 604+ "hsb" : "Hornjoserbsce",
 605+ "ht" : "Krey\u00f2l ayisyen",
 606+ "hu" : "Magyar",
 607+ "hy" : "\u0540\u0561\u0575\u0565\u0580\u0565\u0576",
 608+ "hz" : "Otsiherero",
 609+ "ia" : "Interlingua",
 610+ "id" : "Bahasa Indonesia",
 611+ "ie" : "Interlingue",
 612+ "ig" : "Igbo",
 613+ "ii" : "\ua187\ua259",
 614+ "ik" : "I\u00f1upiak",
 615+ "ike-cans" : "\u1403\u14c4\u1483\u144e\u1450\u1466",
 616+ "ike-latn" : "inuktitut",
 617+ "ilo" : "Ilokano",
 618+ "inh" : "\u0413\u0406\u0430\u043b\u0433\u0406\u0430\u0439 \u011eal\u011faj",
 619+ "io" : "Ido",
 620+ "is" : "\u00cdslenska",
 621+ "it" : "Italiano",
 622+ "iu" : "\u1403\u14c4\u1483\u144e\u1450\u1466\/inuktitut",
 623+ "ja" : "\u65e5\u672c\u8a9e",
 624+ "jbo" : "Lojban",
 625+ "jut" : "Jysk",
 626+ "jv" : "Basa Jawa",
 627+ "ka" : "\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8",
 628+ "kaa" : "Qaraqalpaqsha",
 629+ "kab" : "Taqbaylit",
 630+ "kg" : "Kongo",
 631+ "ki" : "G\u0129k\u0169y\u0169",
 632+ "kiu" : "Kurmanc\u00ee",
 633+ "kj" : "Kwanyama",
 634+ "kk" : "\u049a\u0430\u0437\u0430\u049b\u0448\u0430",
 635+ "kk-arab" : "\u202b\u0642\u0627\u0632\u0627\u0642\u0634\u0627 (\u062a\u0674\u0648\u062a\u06d5)\u202c",
 636+ "kk-cyrl" : "\u202a\u049a\u0430\u0437\u0430\u049b\u0448\u0430 (\u043a\u0438\u0440\u0438\u043b)\u202c",
 637+ "kk-latn" : "\u202aQazaq\u015fa (lat\u0131n)\u202c",
 638+ "kk-cn" : "\u202b\u0642\u0627\u0632\u0627\u0642\u0634\u0627 (\u062c\u06c7\u0646\u06af\u0648)\u202c",
 639+ "kk-kz" : "\u202a\u049a\u0430\u0437\u0430\u049b\u0448\u0430 (\u049a\u0430\u0437\u0430\u049b\u0441\u0442\u0430\u043d)\u202c",
 640+ "kk-tr" : "\u202aQazaq\u015fa (T\u00fcrk\u00efya)\u202c",
 641+ "kl" : "Kalaallisut",
 642+ "km" : "\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a",
 643+ "kn" : "\u0c95\u0ca8\u0ccd\u0ca8\u0ca1",
 644+ "ko" : "\ud55c\uad6d\uc5b4",
 645+ "ko-kp" : "\ud55c\uad6d\uc5b4 (\uc870\uc120)",
 646+ "kr" : "Kanuri",
 647+ "kri" : "Krio",
 648+ "krj" : "Kinaray-a",
 649+ "ks" : "\u0915\u0936\u094d\u092e\u0940\u0930\u0940 - (\u0643\u0634\u0645\u064a\u0631\u064a)",
 650+ "ksh" : "Ripoarisch",
 651+ "ku" : "Kurd\u00ee \/ \u0643\u0648\u0631\u062f\u06cc",
 652+ "ku-latn" : "\u202aKurd\u00ee (lat\u00een\u00ee)\u202c",
 653+ "ku-arab" : "\u202b\u0643\u0648\u0631\u062f\u064a (\u0639\u06d5\u0631\u06d5\u0628\u06cc)\u202c",
 654+ "kv" : "\u041a\u043e\u043c\u0438",
 655+ "kw" : "Kernowek",
 656+ "ky" : "\u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430",
 657+ "la" : "Latina",
 658+ "lad" : "Ladino",
 659+ "lb" : "L\u00ebtzebuergesch",
 660+ "lbe" : "\u041b\u0430\u043a\u043a\u0443",
 661+ "lez" : "\u041b\u0435\u0437\u0433\u0438",
 662+ "lfn" : "Lingua Franca Nova",
 663+ "lg" : "Luganda",
 664+ "li" : "Limburgs",
 665+ "lij" : "L\u00edguru",
 666+ "lmo" : "Lumbaart",
 667+ "ln" : "Ling\u00e1la",
 668+ "lo" : "\u0ea5\u0eb2\u0ea7",
 669+ "loz" : "Silozi",
 670+ "lt" : "Lietuvi\u0173",
 671+ "lv" : "Latvie\u0161u",
 672+ "lzh" : "\u6587\u8a00",
 673+ "mai" : "\u092e\u0948\u0925\u093f\u0932\u0940",
 674+ "map-bms" : "Basa Banyumasan",
 675+ "mdf" : "\u041c\u043e\u043a\u0448\u0435\u043d\u044c",
 676+ "mg" : "Malagasy",
 677+ "mh" : "Ebon",
 678+ "mhr" : "\u041e\u043b\u044b\u043a \u041c\u0430\u0440\u0438\u0439",
 679+ "mi" : "M\u0101ori",
 680+ "mk" : "\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438",
 681+ "ml" : "\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02",
 682+ "mn" : "\u041c\u043e\u043d\u0433\u043e\u043b",
 683+ "mo" : "\u041c\u043e\u043b\u0434\u043e\u0432\u0435\u043d\u044f\u0441\u043a\u044d",
 684+ "mr" : "\u092e\u0930\u093e\u0920\u0940",
 685+ "ms" : "Bahasa Melayu",
 686+ "mt" : "Malti",
 687+ "mus" : "Mvskoke",
 688+ "mwl" : "Mirand\u00e9s",
 689+ "my" : "\u1019\u103c\u1014\u103a\u1019\u102c\u1018\u102c\u101e\u102c",
 690+ "myv" : "\u042d\u0440\u0437\u044f\u043d\u044c",
 691+ "mzn" : "\u0645\u064e\u0632\u0650\u0631\u0648\u0646\u064a",
 692+ "na" : "Dorerin Naoero",
 693+ "nah" : "N\u0101huatl",
 694+ "nan" : "B\u00e2n-l\u00e2m-g\u00fa",
 695+ "nap" : "Nnapulitano",
 696+ "nb" : "\u202aNorsk (bokm\u00e5l)\u202c",
 697+ "nds" : "Plattd\u00fc\u00fctsch",
 698+ "nds-nl" : "Nedersaksisch",
 699+ "ne" : "\u0928\u0947\u092a\u093e\u0932\u0940",
 700+ "new" : "\u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e",
 701+ "ng" : "Oshiwambo",
 702+ "niu" : "Niu\u0113",
 703+ "nl" : "Nederlands",
 704+ "nn" : "\u202aNorsk (nynorsk)\u202c",
 705+ "no" : "\u202aNorsk (bokm\u00e5l)\u202c",
 706+ "nov" : "Novial",
 707+ "nrm" : "Nouormand",
 708+ "nso" : "Sesotho sa Leboa",
 709+ "nv" : "Din\u00e9 bizaad",
 710+ "ny" : "Chi-Chewa",
 711+ "oc" : "Occitan",
 712+ "om" : "Oromoo",
 713+ "or" : "\u0b13\u0b21\u0b3c\u0b3f\u0b06",
 714+ "os" : "\u0418\u0440\u043e\u043d\u0430\u0443",
 715+ "pa" : "\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40",
 716+ "pag" : "Pangasinan",
 717+ "pam" : "Kapampangan",
 718+ "pap" : "Papiamentu",
 719+ "pcd" : "Picard",
 720+ "pdc" : "Deitsch",
 721+ "pdt" : "Plautdietsch",
 722+ "pfl" : "Pf\u00e4lzisch",
 723+ "pi" : "\u092a\u093e\u093f\u0934",
 724+ "pih" : "Norfuk \/ Pitkern",
 725+ "pl" : "Polski",
 726+ "pms" : "Piemont\u00e8is",
 727+ "pnb" : "\u067e\u0646\u062c\u0627\u0628\u06cc",
 728+ "pnt" : "\u03a0\u03bf\u03bd\u03c4\u03b9\u03b1\u03ba\u03ac",
 729+ "ps" : "\u067e\u069a\u062a\u0648",
 730+ "pt" : "Portugu\u00eas",
 731+ "pt-br" : "Portugu\u00eas do Brasil",
 732+ "qu" : "Runa Simi",
 733+ "rif" : "Tarifit",
 734+ "rm" : "Rumantsch",
 735+ "rmy" : "Romani",
 736+ "rn" : "Kirundi",
 737+ "ro" : "Rom\u00e2n\u0103",
 738+ "roa-rup" : "Arm\u00e3neashce",
 739+ "roa-tara" : "Tarand\u00edne",
 740+ "ru" : "\u0420\u0443\u0441\u0441\u043a\u0438\u0439",
 741+ "ruq" : "Vl\u0103he\u015fte",
 742+ "ruq-cyrl" : "\u0412\u043b\u0430\u0445\u0435\u0441\u0442\u0435",
 743+ "ruq-latn" : "Vl\u0103he\u015fte",
 744+ "rw" : "Kinyarwanda",
 745+ "sa" : "\u0938\u0902\u0938\u094d\u0915\u0943\u0924",
 746+ "sah" : "\u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430",
 747+ "sc" : "Sardu",
 748+ "scn" : "Sicilianu",
 749+ "sco" : "Scots",
 750+ "sd" : "\u0633\u0646\u068c\u064a",
 751+ "sdc" : "Sassaresu",
 752+ "se" : "S\u00e1megiella",
 753+ "sei" : "Cmique Itom",
 754+ "sg" : "S\u00e4ng\u00f6",
 755+ "sh" : "Srpskohrvatski \/ \u0421\u0440\u043f\u0441\u043a\u043e\u0445\u0440\u0432\u0430\u0442\u0441\u043a\u0438",
 756+ "shi" : "Ta\u0161l\u1e25iyt",
 757+ "si" : "\u0dc3\u0dd2\u0d82\u0dc4\u0dbd",
 758+ "simple" : "Simple English",
 759+ "sk" : "Sloven\u010dina",
 760+ "sl" : "Sloven\u0161\u010dina",
 761+ "sli" : "Schl\u00e4sch",
 762+ "sm" : "Gagana Samoa",
 763+ "sma" : "\u00c5arjelsaemien",
 764+ "sn" : "chiShona",
 765+ "so" : "Soomaaliga",
 766+ "sq" : "Shqip",
 767+ "sr" : "\u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski",
 768+ "sr-ec" : "\u0421\u0440\u043f\u0441\u043a\u0438 (\u045b\u0438\u0440\u0438\u043b\u0438\u0446\u0430)",
 769+ "sr-el" : "Srpski (latinica)",
 770+ "srn" : "Sranantongo",
 771+ "ss" : "SiSwati",
 772+ "st" : "Sesotho",
 773+ "stq" : "Seeltersk",
 774+ "su" : "Basa Sunda",
 775+ "sv" : "Svenska",
 776+ "sw" : "Kiswahili",
 777+ "szl" : "\u015al\u016fnski",
 778+ "ta" : "\u0ba4\u0bae\u0bbf\u0bb4\u0bcd",
 779+ "tcy" : "\u0ca4\u0cc1\u0cb3\u0cc1",
 780+ "te" : "\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41",
 781+ "tet" : "Tetun",
 782+ "tg" : "\u0422\u043e\u04b7\u0438\u043a\u04e3",
 783+ "tg-cyrl" : "\u0422\u043e\u04b7\u0438\u043a\u04e3",
 784+ "tg-latn" : "tojik\u012b",
 785+ "th" : "\u0e44\u0e17\u0e22",
 786+ "ti" : "\u1275\u130d\u122d\u129b",
 787+ "tk" : "T\u00fcrkmen\u00e7e",
 788+ "tl" : "Tagalog",
 789+ "tn" : "Setswana",
 790+ "to" : "lea faka-Tonga",
 791+ "tokipona" : "Toki Pona",
 792+ "tp" : "Toki Pona (deprecated:tokipona)",
 793+ "tpi" : "Tok Pisin",
 794+ "tr" : "T\u00fcrk\u00e7e",
 795+ "ts" : "Xitsonga",
 796+ "tt" : "\u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a",
 797+ "tt-cyrl" : "\u0422\u0430\u0442\u0430\u0440\u0447\u0430",
 798+ "tt-latn" : "Tatar\u00e7a",
 799+ "tum" : "chiTumbuka",
 800+ "tw" : "Twi",
 801+ "ty" : "Reo M\u0101`ohi",
 802+ "tyv" : "\u0422\u044b\u0432\u0430 \u0434\u044b\u043b",
 803+ "udm" : "\u0423\u0434\u043c\u0443\u0440\u0442",
 804+ "ug" : "Uyghurche\u200e \/ \u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5",
 805+ "ug-arab" : "\u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5",
 806+ "ug-latn" : "Uyghurche\u200e",
 807+ "uk" : "\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430",
 808+ "ur" : "\u0627\u0631\u062f\u0648",
 809+ "uz" : "O'zbek",
 810+ "ve" : "Tshivenda",
 811+ "vec" : "V\u00e8neto",
 812+ "vep" : "Vepsan kel'",
 813+ "vi" : "Ti\u1ebfng Vi\u1ec7t",
 814+ "vls" : "West-Vlams",
 815+ "vo" : "Volap\u00fck",
 816+ "vro" : "V\u00f5ro",
 817+ "wa" : "Walon",
 818+ "war" : "Winaray",
 819+ "wo" : "Wolof",
 820+ "wuu" : "\u5434\u8bed",
 821+ "xal" : "\u0425\u0430\u043b\u044c\u043c\u0433",
 822+ "xh" : "isiXhosa",
 823+ "xmf" : "\u10db\u10d0\u10e0\u10d2\u10d0\u10da\u10e3\u10e0\u10d8",
 824+ "yi" : "\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9",
 825+ "yo" : "Yor\u00f9b\u00e1",
 826+ "yue" : "\u7cb5\u8a9e",
 827+ "za" : "Vahcuengh",
 828+ "zea" : "Ze\u00eauws",
 829+ "zh" : "\u4e2d\u6587",
 830+ "zh-classical" : "\u6587\u8a00",
 831+ "zh-cn" : "\u202a\u4e2d\u6587(\u4e2d\u56fd\u5927\u9646)\u202c",
 832+ "zh-hans" : "\u202a\u4e2d\u6587(\u7b80\u4f53)\u202c",
 833+ "zh-hant" : "\u202a\u4e2d\u6587(\u7e41\u9ad4)\u202c",
 834+ "zh-hk" : "\u202a\u4e2d\u6587(\u9999\u6e2f)\u202c",
 835+ "zh-min-nan" : "B\u00e2n-l\u00e2m-g\u00fa",
 836+ "zh-mo" : "\u202a\u4e2d\u6587(\u6fb3\u9580)\u202c",
 837+ "zh-my" : "\u202a\u4e2d\u6587(\u9a6c\u6765\u897f\u4e9a)\u202c",
 838+ "zh-sg" : "\u202a\u4e2d\u6587(\u65b0\u52a0\u5761)\u202c",
 839+ "zh-tw" : "\u202a\u4e2d\u6587(\u53f0\u7063)\u202c",
 840+ "zh-yue" : "\u7cb5\u8a9e",
 841+ "zu" : "isiZulu"
 842+};
 843+
 844+
 845+})(jQuery, mediaWiki);
Property changes on: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/mediawiki.language/mediawiki.language.parserTest.js
___________________________________________________________________
Added: svn:mime-type
1846 + text/plain
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/MwEmbedSharedResources.php
@@ -0,0 +1,396 @@
 2+<?php
 3+
 4+return array(
 5+
 6+ /* Special resources who have their own classes */
 7+ 'startup' => array( 'class' => 'MwEmbedResourceLoaderStartUpModule' ),
 8+
 9+ /* jQuery */
 10+
 11+ 'jquery' => array(
 12+ 'scripts' => 'resources/jquery/jquery.js',
 13+ 'debugRaw' => false
 14+ ),
 15+
 16+ /* jQuery Plugins */
 17+
 18+ 'jquery.async' => array(
 19+ 'scripts' => 'resources/jquery/jquery.async.js',
 20+ ),
 21+ 'jquery.autoEllipsis' => array(
 22+ 'scripts' => 'resources/jquery/jquery.autoEllipsis.js',
 23+ 'dependencies' => 'jquery.highlightText',
 24+ ),
 25+ 'jquery.checkboxShiftClick' => array(
 26+ 'scripts' => 'resources/jquery/jquery.checkboxShiftClick.js',
 27+ ),
 28+ 'jquery.client' => array(
 29+ 'scripts' => 'resources/jquery/jquery.client.js',
 30+ ),
 31+ 'jquery.collapsibleTabs' => array(
 32+ 'scripts' => 'resources/jquery/jquery.collapsibleTabs.js',
 33+ ),
 34+ 'jquery.colorUtil' => array(
 35+ 'scripts' => 'resources/jquery/jquery.colorUtil.js',
 36+ ),
 37+ 'jquery.color' => array(
 38+ 'scripts' => 'resources/jquery/jquery.color.js',
 39+ 'dependencies' => 'jquery.colorUtil',
 40+ ),
 41+ 'jquery.cookie' => array(
 42+ 'scripts' => 'resources/jquery/jquery.cookie.js',
 43+ ),
 44+ 'jquery.delayedBind' => array(
 45+ 'scripts' => 'resources/jquery/jquery.delayedBind.js',
 46+ ),
 47+ 'jquery.expandableField' => array(
 48+ 'scripts' => 'resources/jquery/jquery.expandableField.js',
 49+ ),
 50+ 'jquery.highlightText' => array(
 51+ 'scripts' => 'resources/jquery/jquery.highlightText.js',
 52+ ),
 53+ 'jquery.hoverIntent' => array(
 54+ 'scripts' => 'resources/jquery/jquery.hoverIntent.js',
 55+ ),
 56+ 'jquery.placeholder' => array(
 57+ 'scripts' => 'resources/jquery/jquery.placeholder.js',
 58+ ),
 59+ 'jquery.localize' => array(
 60+ 'scripts' => 'resources/jquery/jquery.localize.js',
 61+ ),
 62+ 'jquery.makeCollapsible' => array(
 63+ 'scripts' => 'resources/jquery/jquery.makeCollapsible.js',
 64+ 'styles' => 'resources/jquery/jquery.makeCollapsible.css',
 65+ 'messages' => array( 'collapsible-expand', 'collapsible-collapse' ),
 66+ ),
 67+ 'jquery.suggestions' => array(
 68+ 'scripts' => 'resources/jquery/jquery.suggestions.js',
 69+ 'styles' => 'resources/jquery/jquery.suggestions.css',
 70+ ),
 71+ 'jquery.tabIndex' => array(
 72+ 'scripts' => 'resources/jquery/jquery.tabIndex.js',
 73+ ),
 74+ 'jquery.textSelection' => array(
 75+ 'scripts' => 'resources/jquery/jquery.textSelection.js',
 76+ ),
 77+ 'jquery.tipsy' => array(
 78+ 'scripts' => 'resources/jquery.tipsy/jquery.tipsy.js',
 79+ 'styles' => 'resources/jquery.tipsy/jquery.tipsy.css',
 80+ ),
 81+
 82+ /* jQuery UI */
 83+
 84+ // Core
 85+ 'jquery.ui.core' => array(
 86+ 'scripts' => 'resources/jquery.ui/jquery.ui.core.js',
 87+ 'skinStyles' => array(
 88+ 'default' => array(
 89+ 'resources/jquery.ui/themes/default/jquery.ui.core.css',
 90+ 'resources/jquery.ui/themes/default/jquery.ui.theme.css',
 91+ ),
 92+ 'vector' => array(
 93+ 'resources/jquery.ui/themes/vector/jquery.ui.core.css',
 94+ 'resources/jquery.ui/themes/vector/jquery.ui.theme.css',
 95+ ),
 96+ ),
 97+ 'dependencies' => 'jquery',
 98+ ),
 99+ 'jquery.ui.widget' => array(
 100+ 'scripts' => 'resources/jquery.ui/jquery.ui.widget.js',
 101+ ),
 102+ 'jquery.ui.mouse' => array(
 103+ 'scripts' => 'resources/jquery.ui/jquery.ui.mouse.js',
 104+ 'dependencies' => 'jquery.ui.widget',
 105+ ),
 106+ 'jquery.ui.position' => array(
 107+ 'scripts' => 'resources/jquery.ui/jquery.ui.position.js',
 108+ ),
 109+ // Interactions
 110+ 'jquery.ui.draggable' => array(
 111+ 'scripts' => 'resources/jquery.ui/jquery.ui.draggable.js',
 112+ 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.mouse', 'jquery.ui.widget' ),
 113+ ),
 114+ 'jquery.ui.droppable' => array(
 115+ 'scripts' => 'resources/jquery.ui/jquery.ui.droppable.js',
 116+ 'dependencies' => array(
 117+ 'jquery.ui.core', 'jquery.ui.mouse', 'jquery.ui.widget', 'jquery.ui.draggable',
 118+ ),
 119+ ),
 120+ 'jquery.ui.resizable' => array(
 121+ 'scripts' => 'resources/jquery.ui/jquery.ui.resizable.js',
 122+ 'skinStyles' => array(
 123+ 'default' => 'resources/jquery.ui/themes/default/jquery.ui.resizable.css',
 124+ 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.resizable.css',
 125+ ),
 126+ 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
 127+ ),
 128+ 'jquery.ui.selectable' => array(
 129+ 'scripts' => 'resources/jquery.ui/jquery.ui.selectable.js',
 130+ 'skinStyles' => array(
 131+ 'default' => 'resources/jquery.ui/themes/default/jquery.ui.selectable.css',
 132+ 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.selectable.css',
 133+ ),
 134+ 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
 135+ ),
 136+ 'jquery.ui.sortable' => array(
 137+ 'scripts' => 'resources/jquery.ui/jquery.ui.sortable.js',
 138+ 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
 139+ ),
 140+ // Widgets
 141+ 'jquery.ui.accordion' => array(
 142+ 'scripts' => 'resources/jquery.ui/jquery.ui.accordion.js',
 143+ 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
 144+ 'skinStyles' => array(
 145+ 'default' => 'resources/jquery.ui/themes/default/jquery.ui.accordion.css',
 146+ 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.accordion.css',
 147+ ),
 148+ ),
 149+ 'jquery.ui.autocomplete' => array(
 150+ 'scripts' => 'resources/jquery.ui/jquery.ui.autocomplete.js',
 151+ 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.position' ),
 152+ 'skinStyles' => array(
 153+ 'default' => 'resources/jquery.ui/themes/default/jquery.ui.autocomplete.css',
 154+ 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.autocomplete.css',
 155+ ),
 156+ ),
 157+ 'jquery.ui.button' => array(
 158+ 'scripts' => 'resources/jquery.ui/jquery.ui.button.js',
 159+ 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
 160+ 'skinStyles' => array(
 161+ 'default' => 'resources/jquery.ui/themes/default/jquery.ui.button.css',
 162+ 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.button.css',
 163+ ),
 164+ ),
 165+ 'jquery.ui.datepicker' => array(
 166+ 'scripts' => 'resources/jquery.ui/jquery.ui.datepicker.js',
 167+ 'dependencies' => 'jquery.ui.core',
 168+ 'skinStyles' => array(
 169+ 'default' => 'resources/jquery.ui/themes/default/jquery.ui.datepicker.css',
 170+ 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.datepicker.css',
 171+ ),
 172+ 'languageScripts' => array(
 173+ 'af' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-af.js',
 174+ 'ar' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ar.js',
 175+ 'az' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-az.js',
 176+ 'bg' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-bg.js',
 177+ 'bs' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-bs.js',
 178+ 'ca' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ca.js',
 179+ 'cs' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-cs.js',
 180+ 'da' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-da.js',
 181+ 'de' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-de.js',
 182+ 'el' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-el.js',
 183+ 'en-gb' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js',
 184+ 'eo' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-eo.js',
 185+ 'es' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-es.js',
 186+ 'et' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-et.js',
 187+ 'eu' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-eu.js',
 188+ 'fa' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fa.js',
 189+ 'fi' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fi.js',
 190+ 'fo' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fo.js',
 191+ 'fr-ch' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fr-CH.js',
 192+ 'fr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-fr.js',
 193+ 'he' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-he.js',
 194+ 'hr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-hr.js',
 195+ 'hu' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-hu.js',
 196+ 'hy' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-hy.js',
 197+ 'id' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-id.js',
 198+ 'is' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-is.js',
 199+ 'it' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-it.js',
 200+ 'ja' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ja.js',
 201+ 'ko' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ko.js',
 202+ 'lt' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-lt.js',
 203+ 'lv' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-lv.js',
 204+ 'ms' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ms.js',
 205+ 'nl' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-nl.js',
 206+ 'no' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-no.js',
 207+ 'pl' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-pl.js',
 208+ 'pt-br' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js',
 209+ 'ro' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ro.js',
 210+ 'ru' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ru.js',
 211+ 'sk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sk.js',
 212+ 'sl' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sl.js',
 213+ 'sq' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sq.js',
 214+ 'sr-sr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js',
 215+ 'sr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sr.js',
 216+ 'sv' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-sv.js',
 217+ 'ta' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-ta.js',
 218+ 'th' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-th.js',
 219+ 'tr' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-tr.js',
 220+ 'uk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-uk.js',
 221+ 'vi' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-vi.js',
 222+ 'zh-cn' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js',
 223+ 'zh-hk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js',
 224+ 'zh-tw' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js',
 225+ ),
 226+ ),
 227+ 'jquery.ui.dialog' => array(
 228+ 'scripts' => 'resources/jquery.ui/jquery.ui.dialog.js',
 229+ 'dependencies' => array(
 230+ 'jquery.ui.core',
 231+ 'jquery.ui.widget',
 232+ 'jquery.ui.button',
 233+ 'jquery.ui.draggable',
 234+ 'jquery.ui.mouse',
 235+ 'jquery.ui.position',
 236+ 'jquery.ui.resizable',
 237+ ),
 238+ 'skinStyles' => array(
 239+ 'default' => 'resources/jquery.ui/themes/default/jquery.ui.dialog.css',
 240+ 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.dialog.css',
 241+ ),
 242+ ),
 243+ 'jquery.ui.progressbar' => array(
 244+ 'scripts' => 'resources/jquery.ui/jquery.ui.progressbar.js',
 245+ 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
 246+ 'skinStyles' => array(
 247+ 'default' => 'resources/jquery.ui/themes/default/jquery.ui.progressbar.css',
 248+ 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.progressbar.css',
 249+ ),
 250+ ),
 251+ 'jquery.ui.slider' => array(
 252+ 'scripts' => 'resources/jquery.ui/jquery.ui.slider.js',
 253+ 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
 254+ 'skinStyles' => array(
 255+ 'default' => 'resources/jquery.ui/themes/default/jquery.ui.slider.css',
 256+ 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.slider.css',
 257+ ),
 258+ ),
 259+ 'jquery.ui.tabs' => array(
 260+ 'scripts' => 'resources/jquery.ui/jquery.ui.tabs.js',
 261+ 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
 262+ 'skinStyles' => array(
 263+ 'default' => 'resources/jquery.ui/themes/default/jquery.ui.tabs.css',
 264+ 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.tabs.css',
 265+ ),
 266+ ),
 267+ // Effects
 268+ 'jquery.effects.core' => array(
 269+ 'scripts' => 'resources/jquery.effects/jquery.effects.core.js',
 270+ 'dependencies' => 'jquery',
 271+ ),
 272+ 'jquery.effects.blind' => array(
 273+ 'scripts' => 'resources/jquery.effects/jquery.effects.blind.js',
 274+ 'dependencies' => 'jquery.effects.core',
 275+ ),
 276+ 'jquery.effects.bounce' => array(
 277+ 'scripts' => 'resources/jquery.effects/jquery.effects.bounce.js',
 278+ 'dependencies' => 'jquery.effects.core',
 279+ ),
 280+ 'jquery.effects.clip' => array(
 281+ 'scripts' => 'resources/jquery.effects/jquery.effects.clip.js',
 282+ 'dependencies' => 'jquery.effects.core',
 283+ ),
 284+ 'jquery.effects.drop' => array(
 285+ 'scripts' => 'resources/jquery.effects/jquery.effects.drop.js',
 286+ 'dependencies' => 'jquery.effects.core',
 287+ ),
 288+ 'jquery.effects.explode' => array(
 289+ 'scripts' => 'resources/jquery.effects/jquery.effects.explode.js',
 290+ 'dependencies' => 'jquery.effects.core',
 291+ ),
 292+ 'jquery.effects.fold' => array(
 293+ 'scripts' => 'resources/jquery.effects/jquery.effects.fold.js',
 294+ 'dependencies' => 'jquery.effects.core',
 295+ ),
 296+ 'jquery.effects.highlight' => array(
 297+ 'scripts' => 'resources/jquery.effects/jquery.effects.highlight.js',
 298+ 'dependencies' => 'jquery.effects.core',
 299+ ),
 300+ 'jquery.effects.pulsate' => array(
 301+ 'scripts' => 'resources/jquery.effects/jquery.effects.pulsate.js',
 302+ 'dependencies' => 'jquery.effects.core',
 303+ ),
 304+ 'jquery.effects.scale' => array(
 305+ 'scripts' => 'resources/jquery.effects/jquery.effects.scale.js',
 306+ 'dependencies' => 'jquery.effects.core',
 307+ ),
 308+ 'jquery.effects.shake' => array(
 309+ 'scripts' => 'resources/jquery.effects/jquery.effects.shake.js',
 310+ 'dependencies' => 'jquery.effects.core',
 311+ ),
 312+ 'jquery.effects.slide' => array(
 313+ 'scripts' => 'resources/jquery.effects/jquery.effects.slide.js',
 314+ 'dependencies' => 'jquery.effects.core',
 315+ ),
 316+ 'jquery.effects.transfer' => array(
 317+ 'scripts' => 'resources/jquery.effects/jquery.effects.transfer.js',
 318+ 'dependencies' => 'jquery.effects.core',
 319+ ),
 320+
 321+ /* MediaWiki */
 322+
 323+ 'mediawiki' => array(
 324+ 'scripts' => 'resources/mediawiki/mediawiki.js',
 325+ 'debugScripts' => 'resources/mediawiki/mediawiki.log.js',
 326+ 'debugRaw' => false
 327+ ),
 328+ /*
 329+ 'mediawiki.util' => array(
 330+ 'scripts' => 'resources/mediawiki.util/mediawiki.util.js',
 331+ 'dependencies' => array( 'jquery.checkboxShiftClick', 'jquery.client', 'jquery.cookie', 'jquery.placeholder', 'jquery.makeCollapsible' ),
 332+ 'debugScripts' => 'resources/mediawiki.util/mediawiki.util.test.js',
 333+ ),
 334+ */
 335+
 336+
 337+ 'mediawiki.language' => array(
 338+ 'scripts' => 'resources/mediawiki.language/mediawiki.language.js',
 339+ 'languageScripts' => array(
 340+ 'am' => 'resources/mediawiki.language/languages/am.js',
 341+ 'ar' => 'resources/mediawiki.language/languages/ar.js',
 342+ 'bat-smg' => 'resources/mediawiki.language/languages/bat-smg.js',
 343+ 'be' => 'resources/mediawiki.language/languages/be.js',
 344+ 'be-tarask' => 'resources/mediawiki.language/languages/be-tarask.js',
 345+ 'bh' => 'resources/mediawiki.language/languages/bh.js',
 346+ 'bs' => 'resources/mediawiki.language/languages/bs.js',
 347+ 'cs' => 'resources/mediawiki.language/languages/cs.js',
 348+ 'cu' => 'resources/mediawiki.language/languages/cu.js',
 349+ 'cy' => 'resources/mediawiki.language/languages/cy.js',
 350+ 'dsb' => 'resources/mediawiki.language/languages/dsb.js',
 351+ 'fr' => 'resources/mediawiki.language/languages/fr.js',
 352+ 'ga' => 'resources/mediawiki.language/languages/ga.js',
 353+ 'gd' => 'resources/mediawiki.language/languages/gd.js',
 354+ 'gv' => 'resources/mediawiki.language/languages/gv.js',
 355+ 'he' => 'resources/mediawiki.language/languages/he.js',
 356+ 'hi' => 'resources/mediawiki.language/languages/hi.js',
 357+ 'hr' => 'resources/mediawiki.language/languages/hr.js',
 358+ 'hsb' => 'resources/mediawiki.language/languages/hsb.js',
 359+ 'hy' => 'resources/mediawiki.language/languages/hy.js',
 360+ 'ksh' => 'resources/mediawiki.language/languages/ksh.js',
 361+ 'ln' => 'resources/mediawiki.language/languages/ln.js',
 362+ 'lt' => 'resources/mediawiki.language/languages/lt.js',
 363+ 'lv' => 'resources/mediawiki.language/languages/lv.js',
 364+ 'mg' => 'resources/mediawiki.language/languages/mg.js',
 365+ 'mk' => 'resources/mediawiki.language/languages/mk.js',
 366+ 'mo' => 'resources/mediawiki.language/languages/mo.js',
 367+ 'mt' => 'resources/mediawiki.language/languages/mt.js',
 368+ 'nso' => 'resources/mediawiki.language/languages/nso.js',
 369+ 'pl' => 'resources/mediawiki.language/languages/pl.js',
 370+ 'pt-br' => 'resources/mediawiki.language/languages/pt-br.js',
 371+ 'ro' => 'resources/mediawiki.language/languages/ro.js',
 372+ 'ru' => 'resources/mediawiki.language/languages/ru.js',
 373+ 'se' => 'resources/mediawiki.language/languages/se.js',
 374+ 'sh' => 'resources/mediawiki.language/languages/sh.js',
 375+ 'sk' => 'resources/mediawiki.language/languages/sk.js',
 376+ 'sl' => 'resources/mediawiki.language/languages/sl.js',
 377+ 'sma' => 'resources/mediawiki.language/languages/sma.js',
 378+ 'sr-ec' => 'resources/mediawiki.language/languages/sr-ec.js',
 379+ 'sr-el' => 'resources/mediawiki.language/languages/sr-el.js',
 380+ 'sr' => 'resources/mediawiki.language/languages/sr.js',
 381+ 'ti' => 'resources/mediawiki.language/languages/ti.js',
 382+ 'tl' => 'resources/mediawiki.language/languages/tl.js',
 383+ 'uk' => 'resources/mediawiki.language/languages/uk.js',
 384+ 'wa' => 'resources/mediawiki.language/languages/wa.js',
 385+ ),
 386+ ),
 387+
 388+ 'mediawiki.language.parser' => new MwEmbedResourceLoaderFileModule( array(
 389+ 'scripts' => 'resources/mediawiki.language/mediawiki.language.parser.js',
 390+ 'dependencies' => array( 'mediawiki.language', 'mediawiki.util' ),
 391+ 'debugScripts' => 'resources/mediawiki.language/mediawiki.language.parserTest.js',
 392+ // @@FIXME note the messages are only needed for debugScirpts
 393+ // It appears that debugScripts can only be direct resource paths not 'modules'
 394+ 'messages' => array( 'undelete_short', 'category-subcat-count' )
 395+ ) ),
 396+
 397+);

Status & tagging log