summaryrefslogtreecommitdiff
path: root/www/wiki/vendor/oojs
diff options
context:
space:
mode:
authorYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
committerYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
commitfc7369835258467bf97eb64f184b93691f9a9fd5 (patch)
treedaabd60089d2dd76d9f5fb416b005fbe159c799d /www/wiki/vendor/oojs
first commit
Diffstat (limited to 'www/wiki/vendor/oojs')
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/AUTHORS.txt65
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/History.md3240
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/LICENSE-MIT20
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/README.md152
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/Rakefile14
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/bin/dependencytree.rb42
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/bin/doccomparer.rb158
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/bin/docparser.rb295
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/bin/generate-JSPHP-for-karma.php51
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/bin/testsuitegenerator.rb191
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/BookletDialog.js70
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/BrokenDialog.js61
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.css3
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.js74
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.php82
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/CapsuleNumberPopupMultiselectWidget.js27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/ContinuousOutlinedBookletDialog.js58
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/DelayedReadyProcessDialog.js13
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/DialogWithDropdowns.js218
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/DialogWithPopupAndDropdown.js70
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableGroupWidget.js19
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableHandledItemWidget.js19
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableItemWidget.js19
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/DynamicLabelTextInputWidget.js17
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/FailedReadyProcessDialog.js9
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/FailedSetupProcessDialog.js9
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableTest.css22
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableTest.js125
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableWidget.js10
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/IndexedDialog.js45
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/LongProcessDialog.js32
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/MenuDialog.js90
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/NumberLookupTextInputWidget.js68
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/OutlinedBookletDialog.js46
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/PopupButtonWidgetTest.js123
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/PositionSelectWidget.css34
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/PositionSelectWidget.js35
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/ProcessDialog.js39
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/SamplePage.js20
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/SampleTabPanel.js7
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/SearchWidgetDialog.js30
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleDialog.js26
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleWidget.css23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleWidget.js31
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/classes/UnsupportedSelectFileWidget.js8
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/demo.js794
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/demos.php165
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/index.html97
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/infusion.js44
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/pages/dialogs.js333
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/pages/icons.js302
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/pages/toolbars.js588
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/pages/widgets.js3014
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/pages/widgets.php1180
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/styles/demo.css600
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/demos/widgets.php3
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ace.json10
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/af.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ais.json25
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/am.json7
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ar.json36
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/arc.json7
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/arq.json21
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/as.json25
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ast.json26
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/awa.json8
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/az.json15
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/azb.json11
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ba.json29
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/bcc.json9
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/bcl.json11
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/be-tarask.json29
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/be.json25
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/bg.json29
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/bho.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/bn.json32
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/bqi.json22
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/br.json28
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/bs.json26
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ca.json35
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/cdo.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ce.json19
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ckb.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/co.json9
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/crh-cyrl.json8
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/crh-latn.json8
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/cs.json36
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/cu.json10
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/cy.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/da.json28
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/de.json33
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/diq.json29
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/dsb.json11
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/dty.json18
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/egl.json14
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/el.json33
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/eml.json14
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/en-ca.json22
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/en-gb.json15
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/en.json36
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/eo.json28
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/es.json38
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/et.json25
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/eu.json29
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/fa.json37
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/fi.json37
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/fo.json19
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/fr.json53
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/frr.json12
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/fur.json11
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/fy.json11
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/gd.json13
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/gl.json28
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/glk.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/gom-latn.json14
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/gor.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/gu.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/he.json35
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/hi.json32
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/hif-latn.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/hr.json28
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/hrx.json12
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/hsb.json20
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/hu-formal.json21
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/hu.json31
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/hy.json28
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ia.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/id.json34
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ie.json10
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ilo.json21
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/inh.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/io.json25
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/is.json26
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/it.json39
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ja.json33
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/jv.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ka.json32
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/kab.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/khw.json12
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/kk-cyrl.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/km.json25
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/kn.json26
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ko.json34
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/krc.json22
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/krl.json10
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ksh.json22
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ku-latn.json17
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/kw.json9
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ky.json11
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/la.json15
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/lb.json30
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/li.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/lki.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/lmo.json10
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/lt.json28
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/luz.json21
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/lv.json28
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/lzh.json14
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/mg.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/min.json14
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/mk.json26
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ml.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/mn.json20
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/mr.json32
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ms.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/myv.json17
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/nan.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/nap.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/nb.json31
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/nds-nl.json19
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/nds.json16
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ne.json22
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/nl.json41
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/nn.json20
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/oc.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/olo.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/om.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/or.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/pa.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/pfl.json13
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/pl.json40
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/pms.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/pnb.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ps.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/pt-br.json36
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/pt.json34
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/qqq.json41
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/qu.json12
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ro.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/roa-tara.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ru.json41
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sa.json14
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sah.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/scn.json13
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sco.json22
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sd.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sh.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/shn.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/si.json11
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sk.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/skr-arab.json19
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sl.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sq.json29
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sr-ec.json29
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sr-el.json25
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/su.json25
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sv.json36
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/sw.json16
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ta.json26
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/tay.json20
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/te.json31
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/tg-cyrl.json11
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/th.json10
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/tl.json23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/tr.json34
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/tt-cyrl.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ug-arab.json26
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/uk.json40
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/ur.json26
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/uz.json13
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/vec.json22
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/vep.json8
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/vi.json28
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/vo.json8
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/war.json19
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/wuu.json10
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/xmf.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/yi.json24
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/yo.json10
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/yue.json27
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/zh-hans.json41
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/i18n/zh-hant.json39
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/Element.php304
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/Exception.php6
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/HtmlSnippet.php39
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/Layout.php21
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/Tag.php470
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/Theme.php72
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/Widget.php81
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/layouts/ActionFieldLayout.php55
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/layouts/FieldLayout.php253
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/layouts/FieldsetLayout.php54
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/layouts/FormLayout.php48
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/layouts/HorizontalLayout.php29
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/layouts/PanelLayout.php61
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/mixins/AccessKeyedElement.php96
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/mixins/ButtonElement.php79
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/mixins/FlaggedElement.php133
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/mixins/GroupElement.php129
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/mixins/IconElement.php86
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/mixins/IndicatorElement.php88
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/mixins/LabelElement.php79
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/mixins/TabIndexedElement.php132
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/mixins/TitledElement.php90
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/themes/ApexTheme.php6
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/themes/BlankTheme.php17
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/themes/WikimediaUITheme.php49
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonGroupWidget.php34
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonInputWidget.php123
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonWidget.php220
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/CheckboxInputWidget.php80
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/CheckboxMultiselectInputWidget.php155
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/ComboBoxInputWidget.php80
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/DropdownInputWidget.php113
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/HiddenInputWidget.php43
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/IconWidget.php36
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/IndicatorWidget.php34
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/InputWidget.php170
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/LabelWidget.php52
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/MultilineTextInputWidget.php42
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/ProgressBarWidget.php68
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/RadioInputWidget.php65
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/RadioSelectInputWidget.php126
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/SearchInputWidget.php23
-rw-r--r--www/wiki/vendor/oojs/oojs-ui/php/widgets/TextInputWidget.php249
275 files changed, 21207 insertions, 0 deletions
diff --git a/www/wiki/vendor/oojs/oojs-ui/AUTHORS.txt b/www/wiki/vendor/oojs/oojs-ui/AUTHORS.txt
new file mode 100644
index 00000000..52b48885
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/AUTHORS.txt
@@ -0,0 +1,65 @@
+Principal Authors (major contributors, alphabetically)
+
+Bartosz Dziewoński <matma.rex@gmail.com>
+Ed Sanders <esanders@wikimedia.org>
+James D. Forrester <jforrester@wikimedia.org>
+Kirsten Menger-Anderson <kmenger@wikimedia.org>
+Kunal Mehta <legoktm@gmail.com>
+Moriel Schottlender <moriel@gmail.com>
+Prateek Saxena <prtksxna@gmail.com>
+Roan Kattouw <roan@wikimedia.org>
+Rob Moen <rmoen@wikimedia.org>
+Timo Tijhof <krinklemail@gmail.com>
+Trevor Parscal <trevor@wikimedia.org>
+Volker E. <volker.e@wikimedia.org>
+
+Patch Contributors (minor contributors, alphabetically)
+
+Alangi Derick <alangiderick@gmail.com>
+Alex Monk <krenair@wikimedia.org>
+Amir E. Aharoni <aaharoni@wikimedia.org>
+Amir Sarabadani <Ladsgroup@gmail.com>
+Andrew Garrett <agarrett@wikimedia.org>
+Andrew Green <andrew.green.df@gmail.com>
+Antoine Musso <hashar@free.fr>
+Brad Jorsch <bjorsch@wikimedia.org>
+Brion Vibber <brion@users.mediawiki.org>
+C. Scott Ananian <cscott@cscott.net>
+Chad Horohoe <chadh@wikimedia.org>
+codynguyen1116 <samanthanguyen1116@gmail.com>
+David Lynch <dlynch@wikimedia.org>
+Derk-Jan Hartman <hartman.wiki@gmail.com>
+eranroz <eranroz89@gmail.com>
+Erick Guan <fantasticfears@gmail.com>
+Erik Moeller <erik@wikimedia.org>
+Florian <florian.schmidt.stargatewissen@gmail.com>
+Geoffrey Mon <geofbot@gmail.com>
+Gilles Dubuc <gdubuc@wikimedia.org>
+Huji Lee <huji.huji@gmail.com>
+Inez Korczyński <inez@wikia-inc.com>
+IvanFon <ivanfonseca55@gmail.com>
+Jon Robson <jrobson@wikimedia.org>
+Juliusz Gonera <jgonera@wikimedia.org>
+Kartik Mistry <kartik.mistry@gmail.com>
+Kyle Florence <kflorence@wikia-inc.com>
+Leszek Manicki <leszek.manicki@wikimedia.de>
+Marc A. Pelletier <marc@uberbox.org>
+Mark Holmquist <mtraceur@member.fsf.org>
+Matthew Flaschen <mflaschen@wikimedia.org>
+May Tee-Galloway <mgalloway@wikimedia.org>
+Mr. Stradivarius <misterstrad@gmail.com>
+Niklas Laxström <nlaxstrom@wikimedia.org>
+Nirzar Pangarkar <nirzardp@gmail.com>
+Ori Livneh <ori@wikimedia.org>
+Paladox <thomasmulhall410@yahoo.com>
+Pau Giner <pau.giner@gmail.com>
+Ricordisamoa <ricordisamoa@openmailbox.org>
+rillke <rillke@wikipedia.de>
+Ryan Kaldari <rkaldari@wikimedia.org>
+Sam Reed <reedy@wikimedia.org>
+Stephane Bisson <sbisson@wikimedia.org>
+Sucheta Ghoshal <sghoshal@wikimedia.org>
+Thalia Chan <thalia.e.chan@googlemail.com>
+Victor Barbu <victorbarbu08@gmail.com>
+Wei-Ko Kao <othree@gmail.com>
+Željko Filipin <zeljko.filipin@gmail.com>
diff --git a/www/wiki/vendor/oojs/oojs-ui/History.md b/www/wiki/vendor/oojs/oojs-ui/History.md
new file mode 100644
index 00000000..e626e3d6
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/History.md
@@ -0,0 +1,3240 @@
+# OOUI Release History
+## v0.26.4 / 2018-04-17
+### Code
+* Apex theme: Point pending.gif texture to a directory that exists (Kunal Mehta)
+* Remove white canvases from table move icons (Ed Sanders)
+* WindowManager: Return focus to element after resize (Prateek Saxena)
+* build: Updating mediawiki/mediawiki-codesniffer to 18.0.0 (libraryupgrader)
+
+
+## v0.26.3 / 2018-04-10
+### Styles
+* WikimediaUI theme: Restore background-size transition when checking a checkbox (Bartosz Dziewoński)
+* icons: Add 'tableMoveColumn*' & 'tableMoveRow*' icons (Volker E.)
+
+### Code
+* CheckboxInputWidget: Don't specify icon in CSS (Bartosz Dziewoński)
+* DropdownInput-/RadioSelectInputWidget: Fix support for 'tabIndex' (Bartosz Dziewoński)
+* MenuOptionWidget: Don't specify icon in CSS (Bartosz Dziewoński)
+* MenuToolGroup: Don't specify icon in CSS (Bartosz Dziewoński)
+* PopupTagMultiselectWidget: Use `padding` in popup by default (Ed Sanders)
+* Remove icon overrides for 'en-ca', 'en-gb' when 'en' suffices (Bartosz Dziewoński)
+* Apex icons: Replace entire set with WikimediaUI theme's (Ed Sanders)
+* WikimediaUI theme: Don't override selected MenuToolGroup tools' icon (Bartosz Dziewoński)
+* build: Bump devDependencies to latest (James D. Forrester)
+* demos: Update word processor toolbar styling from VisualEditor (Bartosz Dziewoński)
+
+
+## v0.26.2 / 2018-04-04
+### Deprecations
+* [DEPRECATING CHANGE] icons: Add 'userAnonymous', and deprecate 'userActive'/'userInactive' (Volker E.)
+* [DEPRECATING CHANGE] icons: Deprecate 'find' of 'editing-advanced' pack (Volker E.)
+
+### Styles
+* Blank theme: Use sizes of default theme WikimediaUI (Volker E.)
+* WikimediaUI theme: Fix FieldSetLayout & FieldLayout's help icon position (Volker E.)
+* WikimediaUI theme: Fix FieldLayout with help and align left/right (Bartosz Dziewoński)
+* WikimediaUI theme: Fix miscalculated frameless button's icon position (Volker E.)
+* WikimediaUI theme: Fix tool icons in popup toolgroups (Bartosz Dziewoński)
+* WikimediaUI theme: Replace fixed spacing values with vars (Volker E.)
+* WikimediaUI theme: Simplify SelectFileWidget's CSS (Volker E.)
+
+### Code
+* MultilineTextInputWidget: Allow `resize` except for on autosize (Prateek Saxena)
+* TagMultiselectWidget: Fix arrow movement in inline input (Moriel Schottlender)
+* Update OOjs to v2.2.0 (James D. Forrester)
+* build: Updating mediawiki/mediawiki-codesniffer to 17.0.0 (libraryupgrader)
+* build: colorize-svg.js – reorder functions to avoid forward references (Fomafix)
+* demos: Add theme body classes in PHP demo (Volker E.)
+* demos: Fix icon wrapping (Ed Sanders)
+* icons: Fix size and position of most language variant styling icons (Ed Sanders)
+* icons: Provide RTL 'help' icon for Arabic scripts (Volker E.)
+* icons: Use correct glyphs for bold-a, italic-a, and strikethrough-a (Ed Sanders)
+* icons: Use 'underline-u' in German (Ed Sanders)
+* themes: Remove dash from variable prefix `@ooui` (Volker E.)
+
+
+## v0.26.1 / 2018-03-23
+### Deprecations
+* [DEPRECATING CHANGE] icons: Flag 'comment' as to be removed (James D. Forrester)
+* [DEPRECATING CHANGE] icons: Rename 'clip'/'unClip' to 'bookmark'/'bookmarkOutline' (Volker E.)
+
+### Styles
+* ButtonElement (framed): Remove `padding` on icon + indicator variant (Volker E.)
+* WikimediaUI theme: Reduce distance of Tools in BarToolGroup (Volker E.)
+* WikimediaUI theme: Reduce necessary widths for narrow toolbar elements (Volker E.)
+* WikimediaUI icons: Amend 'help' icon to address feedback (Volker E.)
+* WikimediaUI icons: Fix 'speechBubbles' icons (Volker E.)
+* WikimediaUI icons: Fix 'underline-a' icon to be an 'a', not a 'u' (Ed Sanders)
+* WikimediaUI icons: Slightly adapted size of 'clip'/'unClip' for algnment to other icons (Volker E.)
+* WikimediaUI icons: Swap 'advanced' and 'settings' icons (Volker E.)
+
+### Code
+* WikimediaUI theme: Remove unused RTL variants of alignLeft/Right icons (Ed Sanders)
+* WikimediaUI theme: Fix/remove unused icon files (Bartosz Dziewoński)
+* demos: Add alert popout to toolbars demos (Volker E.)
+* demos: Add specialCharacter terminal tool to toolbars demos (James D. Forrester)
+* docs: Add Demos to JSDuck navigation menu (Timo Tijhof)
+* build: Replace grunt-image with grunt-imagemin (James D. Forrester)
+* icons: Re-crush SVGs (James D. Forrester)
+
+## v0.26.0 / 2018-03-20
+### Breaking changes
+* [BREAKING CHANGE] WikimediaUI: Unify available variants across icon packs (Ed Sanders)
+* [BREAKING CHANGE] icons: Remove 'alignCentre', renamed in v0.24.2 (James D. Forrester)
+* [BREAKING CHANGE] icons: Remove 'arrowLast', deprecated since v0.25.0 (James D. Forrester)
+* [BREAKING CHANGE] icons: Remove 'bellOn', deprecated in v0.25.0 (James D. Forrester)
+* [BREAKING CHANGE] icons: Remove 'quotesAdd', deprecated in v0.24.4 (James D. Forrester)
+* [BREAKING CHANGE] icons: Remove 'redirect', renamed in v0.24.4 (James D. Forrester)
+* [BREAKING CHANGE] indicators: Remove 'next' and 'previous', deprecated in v0.25.0 (James D. Forrester)
+
+### Features
+* FieldLayout: Use better icons for warning/error messages (Bartosz Dziewoński)
+* MenuTagMultiselectWidget: Check for empty inputValue in addTagFromInput (Prateek Saxena)
+* TagMultiselectWidget: Handle disabled items (Moriel Schottlender)
+
+### Styles
+* WikimediaUI theme: Add additional 'interactions' & 'media' pack icons (Volker E.)
+* WikimediaUI theme: Align refined WikimediaUI icons in size and position (Volker E.)
+* WikimediaUI theme: Apply `translateZ` hack to full canvas icons (Volker E.)
+* WikimediaUI theme: Fix regression on accelerator key alignment (Volker E.)
+* WikimediaUI theme: Fix toolbar buttonGroup (Ed Sanders)
+* WikimediaUI theme: Harmonize `padding` on FieldLayout messages (Volker E.)
+* WikimediaUI theme: Unify and refine WikimediaUI icons (Volker E.)
+* WikimediaUI theme: Use `14px` base font size & amend positioning/sizing (Volker E.)
+* Apex theme: Fix toolbar buttonGroup (Ed Sanders)
+* Apex theme: Make Apex also use 20px canvas icons (Bartosz Dziewoński)
+
+### Code
+* Use theme rules to define which tools should get blue icons, not flags (Ed Sanders)
+* build: Make the copy task for the WikimediaUI less vars less confusing (James D. Forrester)
+* build: Stop using 'grunt-image' for optimising PNGs, at least for now (James D. Forrester)
+* build: Switch SVG optimization to 'grunt-svgmin' (Volker E.)
+* build: Temporarily disable running unit tests in Firefox due to timeouts (James D. Forrester)
+* build: Update devDependencies to latest (James D. Forrester)
+* build: Updating jakub-onderka/php-parallel-lint to 1.0.0 (libraryupgrader)
+* build: Acknowledge in package.json that grunt-exec 3.0.0 exists, but we don't want it (Bartosz Dziewoński)
+* demos: Include editor switch menu in toolbars menu (Volker E.)
+* demos: Increase base `font-size` to `14px` (Volker E.)
+* demos: Re-enable bigger base size on mobile breakpoint (Volker E.)
+* demos: Use `0.8em` body font size for Apex (Bartosz Dziewoński)
+* dist: Distribute History.md so people can see what's changed (James D. Forrester)
+
+
+## v0.25.3 / 2018-03-06
+### Features
+* DropdownInputWidget: Extract menu item creation (Gabriel Birke)
+* MenuTagMultiselectWidget: Highlight first item when filtering (Moriel Schottlender)
+* demos: Use individual oojs-ui-* JS files for sourcemap support (Moriel Schottlender)
+
+### Styles
+* WikimediaUI theme: Align action toolbar primary button focus state (Volker E.)
+* WikimediaUI theme: Align toolbar items' focus to widgets elsewhere (Volker E.)
+
+### Code
+* Imply `inline-block` on toolbar item labels (Volker E.)
+* CheckboxMultiselectInputWidget: Fix handling of 'name' config option in JS (Bartosz Dziewoński)
+* TagMultiselectWidget: Only apply `onMouseDown` if not in input (Moriel Schottlender)
+* Gruntfile: Remove reference to long-absent at-ease PHP library (James D. Forrester)
+* build: Add jakub-onderka/php-console-highlighter (Umherirrender)
+* build: Adding MinusX (Kunal Mehta)
+* build: Updating mediawiki/mediawiki-codesniffer to 16.0.1 (libraryupgrader)
+* build: Updating phpunit/phpunit to 4.8.36 || ^6.5 (libraryupgrader)
+* build: pass --ansi --no-progress to composer (Antoine Musso)
+* demos: Add monospace hack for `code` element (Volker E.)
+* demos: Only claim ARIA `main` role on the first toolbar demo (Volker E.)
+* demos: Replace “Save” by “Publish changes” (Volker E.)
+
+
+## v0.25.2 / 2018-02-06
+### Deprecations
+* [DEPRECATING CHANGE] icons: Flag indicator 'alert' as to be removed (Volker E.)
+
+### Features
+* Element: Fix infusion edge case (Bartosz Dziewoński)
+* InputWidget and subclasses: Remember original value when creating the widget (Bartosz Dziewoński)
+* MultilineTextInputWidget: Emit 'enter' for Ctrl+Enter (Ed Sanders)
+* MenuTagMultiselectWidget: Erase the input when a menu option is chosen (Prateek Saxena)
+* OptionWidget: Option is still selectable/highlightable/pressable if its parent is disabled (Bartosz Dziewoński)
+* RadioSelectInputWidget: Prevent exceptions when trying to set unavailable options (Bartosz Dziewoński)
+
+### Styles
+* FieldLayout: Fix help icon negative margin in Apex (Ed Sanders)
+* LabelElement: Switch `box-sizing` to `border-box` (srishakatux)
+* ListToolGroup: Correctly point the collapse/expand icon on bottom toolbars (Volker E.)
+* RadioSelectInputWidget, CheckboxMultiselectInputWidget: Fix spacing between options in PHP (Apex theme) (Bartosz Dziewoński)
+
+### Code
+* Avoid having to call `.setValue()` in some widgets' constructors multiple times (Bartosz Dziewoński)
+* CheckboxMultiselectInputWidget: Turn inline event handler into a method (Bartosz Dziewoński)
+* DraggableElement: Replace 'OOjs-UI' with 'OOUI' for code hygiene (Volker E.)
+* TextInputWidget: Move previously forgotten methods to Multiline (Bartosz Dziewoński)
+* Follow-up b28e99712: Remove `mediawiki/at-ease` dependancy (Sam Reed)
+* Reduce code duplication between `#setValue` and `#setOptions` (Bartosz Dziewoński)
+* Remove duplicate documentation between TextInputWidget and Multiline (Bartosz Dziewoński)
+* TextInputWidget: Document that 'maxLength' counts UTF-16 code units (Bartosz Dziewoński)
+* Toolbars: Replace `$.width` with `clientWidth`/`offsetWidth` (Ed Sanders)
+* Use child selectors for menuLayout (Ed Sanders)
+* build: Don't lint a generated JSON file for validity before it's rebuilt (James D. Forrester)
+* build: Update Rubocop config for deprecations (Bartosz Dziewoński)
+* demos, docs: Replace 'alert' indicator, as it's deprecated (Volker E.)
+* demos: Bring “Word processor toolbar” demos closer to VE (Volker E.)
+* demos: Provide more space at bottom of page (Volker E.)
+* tests: Do not use obviously fake data when testing infusion (Bartosz Dziewoński)
+* testsuitegenerator: Test some 'value' parameters that match 'options' parameters (Bartosz Dziewoński)
+
+
+## v0.25.1 / 2018-01-16
+### Code
+* Allow other stuff to handle the event when we call `simulateLabelClick()` (Bartosz Dziewoński)
+* Follow-Up I0f1d9c1f: Update usages of `getSelectedItem` -> `findSelectedItem` (Ed Sanders)
+* PanelLayout: Remove buggy `translateZ` performance hack (Volker E.)
+* PopupToolGroup: Revert "Fix popup direction changing…" (Bartosz Dziewoński)
+* Rename prefixes of unique IDs to not mention "OOjs" (Bartosz Dziewoński)
+* build, demos, docs: Use “OOUI” as unified name (Volker E.)
+* demos: Use MultilineTextInputWidget in PHP demos (Ed Sanders)
+* docs: Clarify `required` true handling with `indicator: 'required'` (Volker E.)
+* docs: Use “OOUI” as unified name in code comments (Volker E.)
+
+
+## v0.25.0 / 2018-01-09
+### Breaking changes
+* [BREAKING CHANGE] Drop the `constructive` flag entirely (James D. Forrester)
+* [BREAKING CHANGE] Remove `BookletLayout#getClosestPage` (James D. Forrester)
+* [BREAKING CHANGE] SelectWidget: Remove `getFirstSelectableItem` (Prateek Saxena)
+* [BREAKING CHANGE] SelectWidget: Remove `getHighlightedItem` (Prateek Saxena)
+* [BREAKING CHANGE] SelectWidget: Remove `getRelativeSelectableItem` (Prateek Saxena)
+* [BREAKING CHANGE] icons: Drop 'watchlist', deprecated in v0.23.1 (James D. Forrester)
+
+### Deprecations
+* [DEPRECATING CHANGE] GroupElement: Rename getItem(s)FromData to findItem(s)FromData (Prateek Saxena)
+* [DEPRECATING CHANGE] MultiSelectWidget: Rename getters (Prateek Saxena)
+* [DEPRECATING CHANGE] SelectWidget: Rename `getSelectedItem` to `findSelectedItem` (Prateek Saxena)
+* [DEPRECATING CHANGE] icons: Flag indicators 'previous' & 'next' as to be removed (Volker E.)
+* [DEPRECATING CHANGE] icons: Rename 'arrowLast' to 'arrowPrevious' (James D. Forrester)
+
+### Features
+* MenuTagMultiselectWidget: Erase the input when tag is selected if filtering (Moriel Schottlender)
+
+### Styles
+* Add `margin-bottom` for widgets which are part of OOUI HorizontalLayout (Phantom42)
+* FieldLayout: Improve alignment of multiline labels with 'help' button (Bartosz Dziewoński)
+* WikimediaUI theme: Align 'transparency' icon to WikimedaUI color palette (Volker E.)
+* WikimediaUI theme: Remove obsolete global flag for 'layout' icon pack (Volker E.)
+* WikimediaUI theme: Remove obsolete icon flags (Volker E.)
+* Apex theme: Align readonly TextInputWidget across themes (Volker E.)
+* Apex theme: Apply `opacity` button transition and ensure Chrome support (Volker E.)
+* Apex theme: Remove unused, obsolete 'logo-wikimediaDiscovery' icon (Volker E.)
+* icons: Remove obsolete 'bookmark' icon remainders (Volker E.)
+* icons: Remove obsolete 'watchlist' icon remainders (Volker E.)
+* icons: Shorten 'accessibility' pack invert hex color (Volker E.)
+
+### Code
+* Clarify `.oo-ui-force-gpu-composite-layer()` mixin comment (Volker E.)
+* Fix blurry text on PanelLayout promoted to GPU in Safari (Volker E.)
+* Fix popup direction changing when the "anchor" is partially offscreen (Bartosz Dziewoński)
+* MenuTagMultiselectWidget: Don't use overlay for `$autoCloseIgnore` (Moriel Schottlender)
+* MultilineTextInputWidget: Correct documentation for `config.maxRows` (Roan Kattouw)
+* PHP TextInputWidget: Remove remaining type 'search' specific code (Volker E.)
+* Use findItem(s)FromData instead of getItem(s)FromData (Prateek Saxena)
+* demos: Override OO.ui.getViewportSpacing in infused PHP demo too (Bartosz Dziewoński)
+* demos: Promote icons page IndicatorWidget to GPU layer (Volker E.)
+* docs: Bump copyright year (James D. Forrester)
+* docs: TagMultiselectWidget: Remove wrong link to MediaWiki documentation (Prateek Saxena)
+* build: Update .gitattributes for .phpcs.xml file move (Kunal Mehta)
+* build: Add rake to Gemfile (Antoine Musso)
+* build: Don't include Gemfile* in composer zipballs (Kunal Mehta)
+* build: Update RuboCop Ruby gem (Željko Filipin)
+* build: Updating mediawiki/mediawiki-codesniffer to 15.0.0 (libraryupgrader)
+* build: Use SVGO option of 'grunt-image' for distribution (Volker E.)
+
+
+## v0.24.4 / 2017-12-20 special release
+### Deprecations
+* [DEPRECATING CHANGE] icons: Flag unused 'bellOn' icon as to be removed (Volker E.)
+* [DEPRECATING CHANGE] icons: Flag unused 'quotesAdd' & 'redirect' as to be removed (Volker E.)
+
+### Features
+* Introduce `OO.ui.getDefaultOverlay` (Bartosz Dziewoński)
+* Put menus/popups of infused PHP widgets into the default overlay (Bartosz Dziewoński)
+
+### Styles
+* icons: Add 'lightbulb' icon (Prateek Saxena)
+* icons: Add 'stop' icon to Apex theme (Volker E.)
+
+### Code
+* ClippableElement: Fix JS error when Floatable is mixed in but disabled (Roan Kattouw)
+* DropdownWidget: Remove stray use of `this.$()` (Bartosz Dziewoński)
+
+
+## v0.24.3 / 2017-11-28
+### Features
+* Allow adding virtual viewport spacing (Bartosz Dziewoński)
+* ClippableElement: Allow clipping with top or left edge (Bartosz Dziewoński)
+* DropdownInputWidget: Generate a hidden `<select>` in JS (Bartosz Dziewoński)
+* FieldsetLayout: Hide header when there is no icon or label (Bartosz Dziewoński)
+* MenuSelectWidget, PopupWidget: Automatically change popup direction if there is no space (Bartosz Dziewoński)
+* PopupToolGroup: Set clipping edges to fix clipping edge (heh) cases (Bartosz Dziewoński)
+* TextInputWidget: support spellcheck attribute (David Lynch)
+
+### Styles
+* themes: Fix PHP ComboboxInputWidget indicator position (Volker E.)
+* WikimediaUI theme: Restore `:hover:focus` border color on TextInputWidgets (Volker E.)
+* oo-ui-background-image: Drop `-o-linear-gradient` fallback (James D. Forrester)
+* oo-ui-background-image: Drop `-webkit-linear-gradient` fallback (James D. Forrester)
+
+### Code
+* PHP DropdownInputWidget: Workaround for Firefox 57 ignoring attr selector with whitespace (Volker E.)
+* DraggableGroupElement: Don't try to access non-existent property (Bartosz Dziewoński)
+* DropdownInputWidget: Remove duplicate TitledElement mixin (Bartosz Dziewoński)
+* README: Add "Community" section (Prateek Saxena)
+* README: Re-arrange intro section (Prateek Saxena)
+* build: Bump wikimedia-ui-base (Volker E.)
+* git.wikimedia.org -> phab (Zach)
+
+
+## v0.24.2 / 2017-11-07
+### Deprecations
+* [DEPRECATING CHANGE] Use en-US spelling for icon names for consistency (Ed Sanders)
+
+### Code
+* README: Consistently refer to OOUI as library (Volker E.)
+* README: Fix Doxygen rendering (Volker E.)
+* README: Simplify “Quick start” and “Contributing” section (Volker E.)
+* demos: Correct and simplify SimpleWidget styles (Bartosz Dziewoński)
+* docs: onMenuToggle: `isVisible` is the state of the menu (Prateek Saxena)
+
+
+## v0.24.1 / 2017-10-31
+### Features
+* DropdownWidget: Allow pressing Space to close the widget, as well as open (Bartosz Dziewoński)
+
+### Styles
+* WikimediaUI theme: Visually improve MenuSectionOptionWidget MenuOptions (Volker E.)
+
+### Code
+* ComboBoxInputWidget: Add `.oo-ui-comboBoxInputWidget-open` class to widget (Volker E.)
+* Generate clover.xml with code coverage results (Kunal Mehta)
+* WikimediaUI theme: Use child selectors for styling toolbar action buttons (Bartosz Dziewoński)
+* README: Simplify and move “Versioning” section (Volker E.)
+* README: Simplify “Contributing” section slightly and add LESS lint hint (Volker E.)
+* build: Bump stylelint devDependencies (James D. Forrester)
+* build: Bump various devDependencies to latest (James D. Forrester)
+* build: Downgrade 'grunt-exec' to 1.0.1 (again) (Bartosz Dziewoński)
+* build: Update grunt-image to version 4.0.0 (Ed Sanders)
+* build: Update mediawiki/mediawiki-codesniffer to 14.1.0 (libraryupgrader)
+* icons: Unify SVG markup (Volker E.)
+
+
+## v0.24.0 / 2017-10-17
+### Breaking changes
+* [BREAKING CHANGE] Drop 'MediaWiki' backwards-compatibility theme (James D. Forrester)
+* [BREAKING CHANGE] icons: Drop 'stripeSideMenu', renamed in v0.22.2 (James D. Forrester)
+* [BREAKING CHANGE] icons: Remove 'eye'/'eyeClosed' icons, deprecated in v0.23.0 (Volker E.)
+* [BREAKING CHANGE] icons: Remove 'signature' icon, deprecated in v0.23.0 (Volker E.)
+* [BREAKING CHANGE] icons: Remove 'sun', deprecated in v0.23.0 (James D. Forrester)
+
+### Styles
+* themes: Unify icon/indicator visibility (Volker E.)
+* WikimediaUI theme: Ensure hover feedback on TextInputWidget & descendants (Volker E.)
+
+### Code
+* Fix `.oo-ui-selectable()` mixin to actually undo `.oo-ui-unselectable()` (Bartosz Dziewoński)
+* WikimediaUI theme: Fix selector in PopupWidget styles (Bartosz Dziewoński)
+
+
+## v0.23.5 / 2017-10-12
+### Code
+* PHP MultilineTextInputWidget, SearchInputWidget: Remove duplicate `use` statements (Bartosz Dziewoński)
+* PHP Theme: Fix check for IconElement/IndicatorElement for inherited traits (Bartosz Dziewoński)
+
+
+## v0.23.4 / 2017-10-11
+### Styles
+* IndexLayout: Handle long lists of tabs (Bartosz Dziewoński)
+* icons: Provide a 'reload' icon in the 'interactions' pack (Ed Sanders)
+* Apex theme: Fix PopupToolGroup active box size (Volker E.)
+* Apex theme: Fix SelectFileWidget (no browser support)‎ `padding` (Volker E.)
+* Generalize icon and indicator positioning & visibility (Volker E.)
+* WikimediaUI theme: Reduce Checkbox*- & RadioSelectInputWidget vertical space (Volker E.)
+* WikimediaUI theme: Reduce FieldLayout `margin-top` slightly (Volker E.)
+* WikimediaUI theme: Streamlining icon/indicator visibility (Volker E.)
+
+### Code
+* Only store initialConfig in demo mode (Ed Sanders)
+* SearchInputWidget: Prevent extra `oo-ui-textInputWidget-type-text` class (Bartosz Dziewoński)
+* TextInputWidget: Use child selector for icons/indicators/labels (Ed Sanders)
+* Do not call `.offset()` on `$( 'html' )` (Bartosz Dziewoński)
+* PHP: Implement MultilineTextInputWidget, deprecate multiline option (Prateek Saxena)
+* PHP: Implement SearchInputWidget, deprecate search option (Bartosz Dziewoński)
+* build: Downgrade 'grunt-exec' to 1.0.1 (Bartosz Dziewoński)
+* demos: Adding missing `:hover` (Volker E.)
+
+
+## v0.23.3 / 2017-10-03
+### Styles
+* PopupToolGroup: Move accelerator keys `padding` to themes (Volker E.)
+* WikimediaUI theme: Align PopupToolGroup header styles (Volker E.)
+* WikimediaUI theme: Fix border on narrow bottom toolbars (Volker E.)
+* WikimediaUI theme: Fix flagged elements' icon `opacity` (Volker E.)
+* WikimediaUI theme: Improve PopupToolGroup's indicator vertical alignment (Volker E.)
+* WikimediaUI theme: Make toolbar active element highlights visually equal (Volker E.)
+* WikimediaUI theme: Remove `box-shadow` not in design (Volker E.)
+* WikimediaUI theme: Replace BookletLayout menu `border-color` (Volker E.)
+* WikimediaUI theme: Unify positioning and sizing of tools, toolgroups and menus (Volker E.)
+* WindowManager: Remove `overflow: hidden` to enhance styling flexibility (Volker E.)
+
+### Code
+* Follow-up I576f3175: highlightQuery: Handle case when query is not found (Ed Sanders)
+* IndexLayout, BookletLayout: Don't scroll panels if not scrollable (Bartosz Dziewoński)
+* LabelElement: Add tests for setHighlightedQuery (Ed Sanders)
+* SelectWidget: Allow focussing things inside OptionWidget labels (Bartosz Dziewoński)
+* WikimediaUI theme: Simplify action toolbar buttons selectors (Volker E.)
+* demos: Remove unnecessary button demo widgets (Volker E.)
+
+
+## v0.23.2 / 2017-09-26
+### Deprecations
+* [DEPRECATING CHANGE]: Apex theme: Begin killing `constructive` flag (James D. Forrester)
+
+### Features
+* LabelElement#highlightQuery: Support locale comparison (Ed Sanders)
+* MenuLayout, BookletLayout, IndexLayout: Support `expanded: false` (Bartosz Dziewoński)
+* WindowManager: Set `aria-hidden` by default and change toggleAriaIsolation behavior (Prateek Saxena)
+
+### Code
+* MenuLayout: Rewrite support for `expanded: false` (Bartosz Dziewoński)
+* TextInputWidget: Reduce CSS output by enhancing unselectable behaviour (Volker E.)
+* themes: Align DropdownWidget `&-handle` selectors for code hygiene (Volker E.)
+* Apex theme: Simplify Radio- & Checkbox*optionWidget label rules (Volker E.)
+* Remove duplicated `outline` property (Volker E.)
+* Remove LESS vars covered by WikimediaUI Base (Volker E.)
+* demos: Expand long dialog title to actually test things (James D. Forrester)
+* demos: Restrict `opacity` to non-flagged icons only (Volker E.)
+
+
+## v0.23.1 / 2017-09-19
+### Deprecations
+* [DEPRECATING CHANGE] SelectWidget: Rename `getFirstSelectableItem` to `findFirstSelectableItem` (Prateek Saxena)
+* [DEPRECATING CHANGE] SelectWidget: Rename `getHighlightedItem` to `findHighlightedItem` (Prateek Saxena)
+* [DEPRECATING CHANGE] SelectWidget: Rename `getRelativeSelectableItem` to `findRelativeSelectableItem` (Prateek Saxena)
+* [DEPRECATING CHANGE] icons: Flag unused 'watchlist' icon as to be removed (Volker E.)
+
+### Styles
+* RadioOptionWidget, CheckboxMultioptionWidget: Support very long labels (Bartosz Dziewoński)
+* WikimediaUI theme: Harmonize toolbar icon/indicator opacity (Volker E.)
+* WikimediaUI theme: Improve ListToolGroup's color and opacity handling (Volker E.)
+* WikimediaUI theme: Simplify disabled tool opacity rules (Volker E.)
+
+### Code
+* BookletLayout#getClosestPage: Fix version number of deprecation (Prateek Saxena)
+* HtmlSnippet: Throw exception if given non-string content (Bartosz Dziewoński)
+* Use `findFirstSelectableItem` instead of `getFirstSelectableItem` (Prateek Saxena)
+* Use `findHighlightedItem` instead of `getHighlightedItem` (Prateek Saxena)
+* Use `findRelativeSelectableItem` instead of `getRelativeSelectableItem` (Prateek Saxena)
+* WikimediaUI theme: Concatenate constructive & progressive selectors (Volker E.)
+* WikimediaUI theme: Remove unnecessary properties (Volker E.)
+* demos: Add examples of FieldLayout with very long labels (Bartosz Dziewoński)
+* demos: Avoid menu's `box-shadow` from lurkin into toolbar (Volker E.)
+
+
+## v0.23.0 / 2017-09-05
+### Breaking changes
+* [BREAKING CHANGE] Remove CardLayout and references in IndexLayout (Volker E.)
+* [BREAKING CHANGE] Remove FloatingMenuSelectWidget (Volker E.)
+* [BREAKING CHANGE] Remove back-compat `OO.ui` prefix assumption in infusion code (Prateek Saxena)
+* [BREAKING CHANGE] icons: Remove 'caret' icons, deprecated in v0.21.3 (James D. Forrester)
+* [BREAKING CHANGE] icons: Remove 'wikitrail' icon, renamed in v0.20.1 (James D. Forrester)
+
+### Deprecations
+* [DEPRECATING CHANGE] BookletLayout: Rename `getClosestPage()` to `findClosestPage()` (Prateek Saxena)
+* [DEPRECATING CHANGE] icons: Flag unused 'sun' icon as to be removed (James D. Forrester)
+* [DEPRECATING CHANGE] icons: Move 'eye'/'eyeClosed' to 'accessibility' (Volker E.)
+* [DEPRECATING CHANGE] icons: Move 'signature' to 'editing-advanced' (Volker E.)
+
+### Features
+* Element: Improve error message when the widget being infused is missing (Bartosz Dziewoński)
+
+### Styles
+* Apex theme: Only apply `margin` to label if visible (Ed Sanders)
+* WikimediaUI theme: Fix frameless indicator combination buttons' appearance (Volker E.)
+* ButtonInputWidget: Fix Safari-specific intrinsic `margin` (Volker E.)
+
+### Code
+* Ensure only options belonging to the SelectWidget can be clicked (Ed Sanders)
+* SelectFileWidget: Rename `getTargetItem()` to `findTargetItem()` (Prateek Saxena)
+* Toolgroup: Rename `getTargetTool()` to `findTargetTool()` (Prateek Saxena)
+* WikimediaUI theme: Simplify `transition` code and remove obsolete (Volker E.)
+* build: Add 'accessibility' icon pack in Apex to build module definition (Volker E.)
+* build: Update eslint-config-wikimedia 0.4->0.5 (Ed Sanders)
+* build: Updating mediawiki/mediawiki-codesniffer to 0.12.0 (libraryupgrader)
+* tests: Make MockWidget filename match class name (Kunal Mehta)
+
+
+## v0.22.5 / 2017-08-22
+### Features
+* Add `title` attribute to the 'remove' button in TagItemWidget (Moriel Schottlender)
+
+### Styles
+* WikimediaUI theme: Fix regression on disabled border (Volker E.)
+
+### Code
+* Align vars to WikimediaUI Base and remove them as OOjs UI vars (Volker E.)
+* DraggableElement: Make toggling draggability consistent (Bartosz Dziewoński)
+* Follow-up 022f532: Don't crash if TitledElement initializes before AccessKeyedElement (Roan Kattouw)
+* WikimediaUI theme: Make checkbox/radio code leaner (Volker E.)
+* WikimediaUI theme: Remove unnecessary selector in CheckboxInputWidget (Volker E.)
+* docs: Align code comment references to Phabricator tasks (Volker E.)
+* build: Upgrade devDependencies to latest and make pass (James D. Forrester)
+* build: Update mediawiki-codesniffer to v0.10.1 and fix issues (WMDE-Fisch)
+* build: Update mediawiki-codesniffer to v0.11.0 and fix issues (WMDE-Fisch)
+* tests: Prepare for qunit 2.x (James D. Forrester)
+
+
+## v0.22.4 / 2017-08-01
+### Features
+* CheckboxMultiselectInputWidget: setValue when CheckboxMultiselect changes (Prateek Saxena)
+* FieldLayout: Show widget's accesskey in our title (Bartosz Dziewoński)
+* TextInputWidget: When positioning label, don't clear padding if we will set it again (Bartosz Dziewoński)
+* TitledElement: When an AccessKeyedElement, show access key in the title (Bartosz Dziewoński)
+
+### Styles
+* icons: Vertically align 'play' & 'stop' icons (Volker E.)
+* Apex theme: Add focus styles to Tag-/CapsuleMultiselectWidget (Volker E.)
+* Apex theme: Add focus styles to frameless buttons (Volker E.)
+* Apex theme: Add play icon (copied from WikimediaUI theme) (Roan Kattouw)
+* Apex theme: Align ButtonGroup-/ButtonSelectWidget focus logic to WikimediaUI (Volker E.)
+* Apex theme: Align Dropdown*Widget's focus state with other widgets (Volker E.)
+* Apex theme: Align TextInputWidget focus to variablized way (Volker E.)
+* Apex theme: Align ToggleSwitchWidget focus style to other widgets (Volker E.)
+* Apex theme: Improve alignment of TextInputWidget and its elements (Volker E.)
+* Apex theme: Introduce framed button focus indication (Volker E.)
+* Apex theme: Replace and unify `border-radius` with variables (Volker E.)
+* WikimediaUI theme: Set ButtonElement's height per default (Volker E.)
+* WikimediaUI theme: Work around a Firefox rendering bug for checkboxes and radios (Bartosz Dziewoński)
+
+### Code
+* DraggableGroupElement: Remove ARIA roles & attributes (Volker E.)
+* FieldsetLayout: Use `<legend>` now that Chrome 55 bug is less important (James D. Forrester)
+* Apex theme: Align remaining values to coding convention (Volker E.)
+* WikimediaUI theme: Align `*-fallback` var with notation elsewhere (Volker E.)
+* WikimediaUI theme: Code comment hygiene (Volker E.)
+* WikimediaUI theme: Directly use the Less values rather than via copy-paste (James D. Forrester)
+* demos: Add examples of TextInputWidget with dynamic label (Bartosz Dziewoński)
+* demos: Demo.DraggableItemWidget should not inherit from OO.ui.OptionWidget (Bartosz Dziewoński)
+* demos: Show example link on `:focus` (Volker E.)
+* docs: Fix some PHPDoc `@return` tags (Ricordisamoa)
+* build: Add a script to print the dependency tree of everything (Bartosz Dziewoński)
+
+
+## v0.22.3 / 2017-07-11
+### Features
+* Tag-/CapsuleMultiselectWidget: Avoid visual focusTrap feedback (Volker E.)
+* WindowManager: Avoid inconsistent state due to asynchronous promise resolution (Bartosz Dziewoński)
+* WindowManager: fix closing promise state check (David Lynch)
+
+### Styles
+* icons: Align ongoingConversation to grid (Ed Sanders)
+* icons: Replace the puzzle icon, using the one from VisualEditor (James D. Forrester)
+* icons: Vertically center mapPin icon (Volker E.)
+* Apex theme: Add 'article' icon, copied from WikimediaUI (Moriel Schottlender)
+
+### Code
+* DropdownWidget, MenuSelectWidget: Set `aria-expanded` attribute (Prateek Saxena)
+* FieldLayout: Add `role='alert'` for error messages (Prateek Saxena)
+* FieldLayout: Set `aria-describedby` on the fieldWidget (Prateek Saxena)
+* PopupWidget: Update function name in a comment (Bartosz Dziewoński)
+* TagMultiselectWidget: Skip `updateInputSize()` for invisible inputs (Roan Kattouw)
+* Toolbar: Add comment for greppability of dynamic CSS classes (Bartosz Dziewoński)
+* themes: Align read-only variable names to pseudo-class selector scheme (Volker E.)
+* themes: Align variable names to WikimediaUI Base scheme (Volker E.)
+* WikimediaUI theme: Align `@opacity-icon*` variable names to WikimediaUI Base (Volker E.)
+* WikimediaUI theme: Align checked variable names to pseudo-class scheme (Volker E.)
+* WikimediaUI theme: Align disabled variable names to pseudo-class scheme (Volker E.)
+* WikimediaUI theme: Align variable pseudo classes names to WikimediaUI Base (Volker E.)
+* WikimediaUI theme: Replace `@color-base-light` with `@color-base--inverted` (Volker E.)
+* WikimediaUI theme: Variablize PopupWidget values (Volker E.)
+* WikimediaUI theme: Pull in the upstream WikimediaUI package (James D. Forrester)
+* build: Updating mediawiki/mediawiki-codesniffer to 0.10.0 (Kunal Mehta)
+* phpcs: Enable more rules, or document why they are disabled (Bartosz Dziewoński)
+* testsuitegenerator: Blacklist deprecated `multiline` config option (Bartosz Dziewoński)
+
+
+## v0.22.2 / 2017-06-28
+### Deprecations
+* [DEPRECATING CHANGE] TextInputWidget: Move multi-line support out (Prateek Saxena)
+* [DEPRECATING CHANGE] icons: Move and rename 'stripeSideMenu' to 'draggable' (Volker E.)
+
+### Features
+* DropdownInputWidget: Unbreak setting 'value' via config options (Bartosz Dziewoński)
+* Element: Work around browsers that set fractional scrollTop values (Roan Kattouw)
+
+### Styles
+* BookletLayout: Workaround for horizontal scrollbars on menu when editable (Bartosz Dziewoński)
+* icons: Let's stop referring to removed icons, hmm? (James D. Forrester)
+* Rewrite all styling for "outline controls" (Bartosz Dziewoński)
+* Apex theme: Align appearance of tags' close icon to WikimediaUI theme (Volker E.)
+* Apex theme: Fix HorizontalLayout containing FieldLayouts (Bartosz Dziewoński)
+* WikimediaUI theme: Remove default DraggableElement styling (Ed Sanders)
+* WikimediaUI theme: Use icon instead of indicator in Tag-/CapsuleItemWidget (Volker E.)
+* WikimediaUI: Strengthen Radio*Widget's `:checked` state (Volker E.)
+
+### Code
+* MenuSelectWidget: Fix item hiding when menu contents change (Roan Kattouw)
+* MultilineTextInputWidget: Fix autosizing (Bartosz Dziewoński)
+* PopupWidget: Replace CSS with Less comments for smaller dist (Volker E.)
+* SearchInputWidget: Fix ability to clear the input (Bartosz Dziewoński)
+* TabIndexedElement: Fix validation and make consistent in PHP and JS (Bartosz Dziewoński)
+* Use javascript-stringify instead of JSON.stringify (Ed Sanders)
+* Apex theme: Fix order of selectors for :first-child FieldLayout (Bartosz Dziewoński)
+* demos: Add links to documentation from code examples (Prateek Saxena)
+* demos: Allow linking to specific widgets (Bartosz Dziewoński)
+* demos: Indicate code toggle clearer (Volker E.)
+* demos: Pull out all links to docs/sources to the top of the code (Bartosz Dziewoński)
+* demos: Simplify code generation, now that we use javascript-stringify (Bartosz Dziewoński)
+* demos: Use URL 'query' part for linking to demo sections rather than URL 'fragment' (Bartosz Dziewoński)
+* docs: Fix some typos in documentation (Bartosz Dziewoński)
+* docparser: Fix handling for fake trait constructors (Bartosz Dziewoński)
+* docparser: Make matching '(default: ...)' case-insensitive (Bartosz Dziewoński)
+* docparser: Tighter check for 'use' statements in PHP (Bartosz Dziewoński)
+
+
+## v0.22.1 / 2017-05-31
+### Code
+* WindowManager: Do not use return value of `#closeWindow` as promise (Bartosz Dziewoński)
+* WindowManager: Fix check for a window already closing (Bartosz Dziewoński)
+* WindowManager: Fix error handling for `#openWindow` with string argument (Bartosz Dziewoński)
+* WindowManager: Fix important typo in deprecation warning (Bartosz Dziewoński)
+* WindowManager: Fix incorrect checks for promise state (Bartosz Dziewoński)
+* WindowManager: Provide other `jQuery.Promise` methods on the b/c promise too (Bartosz Dziewoński)
+* demos: Clarify code comment (Bartosz Dziewoński)
+* demos: Clean up the global window manager too when destroying (Bartosz Dziewoński)
+* demos: Load icon packs in the PHP demo (Bartosz Dziewoński)
+* demos: Replace abandoned icon name 'remove' to current one 'trash' (Volker E.)
+
+## v0.22.0 / 2017-05-30
+### Breaking changes
+* [BREAKING CHANGE] TextInputWidget: Remove search related methods (Prateek Saxena)
+* [BREAKING CHANGE] icons: Drop the core icon pack (James D. Forrester)
+* [BREAKING CHANGE] icons: Remove unused 'bookmark' icon (Volker E.)
+* [BREAKING CHANGE] Depend on OOjs v2.1.0, up from v2.0.0 (James D. Forrester)
+
+### Deprecations
+* [DEPRECATING CHANGE] Rename the 'MediaWiki' theme to 'WikimediaUI' (James D. Forrester)
+* [DEPRECATING CHANGE] WindowManager: Deprecate using `openWindow`/`closeWindow` returns as promises (Bartosz Dziewoński)
+
+### Features
+* Add HiddenInputWidget to generate hidden input (Victor Barbu)
+* InputWidget: Introduce `#setInputId` and `inputId` config option (Bartosz Dziewoński)
+* MenuTagMultiselectWidget: Clear text field after adding an item from it (Bartosz Dziewoński)
+* MenuTagMultiselectWidget: Handle the 'selected' config option (Bartosz Dziewoński)
+* NumberInputWidget: Use icons instead of labels (Volker E.)
+* PopupButtonWidget: Handle empty configuration (Bartosz Dziewoński)
+* PopupWidget: Position close button in head absolutely (David Lynch)
+* PopupWidget: Sensibly position anchor-less popups (Roan Kattouw)
+* WindowManager: Add `WindowInstance` - a Promise-based lifecycle object (Timo Tijhof)
+* WindowManager: Handle errors better in `#closeWindow` (Bartosz Dziewoński)
+
+* Allow *even more* widgets to be focussed programatically (Bartosz Dziewoński)
+* Only cancel mouse down event if tool in toolgroup clicked on (Ed Sanders)
+* Re-introduce `.simulateLabelClick()` as a separate method from .focus() (Bartosz Dziewoński)
+
+### Styles
+* themes: Field*Layout help position perfectly aligned (Volker E.)
+* themes: Improve frameless button in size and behaviour (Volker E.)
+* themes: Increase FieldsetLayout header's `font-size` (Volker E.)
+* Apex theme: Ensure vertical centering of ButtonElement's icon (Volker E.)
+* Apex theme: Make OptionWidget icon override more specific (Moriel Schottlender)
+* Apex theme: Start Apex's 'user' icon pack, with just 'userAvatar' for now (Ed Sanders)
+* WikimediaUI theme: Align `@background-color-destructive` to WikimediaUI Base (Volker E.)
+* WikimediaUI theme: Align ButtonInputWidget's `line-height` to ButtonWidget (Volker E.)
+* WikimediaUI theme: Align inline label's position (Volker E.)
+* WikimediaUI theme: Ensure icon aligns in dropdown menu (Volker E.)
+* WikimediaUI theme: Remove incorrect comments (Volker E.)
+
+### Code
+* MenuTagMultiselectWidget: Add test for 'selected' config option (Bartosz Dziewoński)
+* windows: Add tests for OO.ui.alert/confirm/prompt (Timo Tijhof)
+* AUTHORS: Update for the past two years' work (James D. Forrester)
+* build: Add the README/AUTHORS/LICENCE files to dist (James D. Forrester)
+* demos: Add TextInputWidget examples with inline labels but no indicators (Ed Sanders)
+* demos: Add viewport meta tag to PHP demo too (Volker E.)
+* demos: Avoid inline CSS for the overlay (Bartosz Dziewoński)
+* demos: Fix code generation for more complicated cases (Bartosz Dziewoński)
+* demos: Fix up a couple of minor things in demo widgets (Bartosz Dziewoński)
+* demos: Fix `z-index` with fixed demo header (Volker E.)
+* demos: Increase and strengthen responsive support (Volker E.)
+* demos: Indicate widgets clearer by sections (Volker E.)
+* demos: Make disabled progress bar in demo determinate (Ed Sanders)
+* demos: Show code that can be used to create the widget (Prateek Saxena)
+* testsuitegenerator: Handle classes with no constructor (Bartosz Dziewoński)
+
+
+## v0.21.4 / 2017-05-16
+### Features
+* Allow more widgets to be focussed programatically (Bartosz Dziewoński)
+* Generalize `.getInputId()` for all widgets (Bartosz Dziewoński)
+* Use `.focus()` method when possible instead of looking inside widgets (Bartosz Dziewoński)
+* TagMultiselectWidget: Fix `Ctrl`+`Backspace` to delete last item (Bartosz Dziewoński)
+* TagMultiselectWidget: Fix order of checks for `allowArbitrary`/`allowDuplicates` (Bartosz Dziewoński)
+
+### Styles
+* MediaWiki theme: Separate two active ToggleButton siblings visually (Volker E)
+
+### Code
+* LabelWidget: Fix label click handling (Bartosz Dziewoński)
+* RadioSelectInputWidget: When generating a unique 'name', don't make it random (Bartosz Dziewoński)
+* Use glaringly wrong tags for elements that are supposed to be unused (Bartosz Dziewoński)
+* README: Clarify and simplify descriptions (Volker E)
+* build: Upgrade eslint-config-wikimedia from 0.3.0 to 0.4.0 and make pass (James D. Forrester)
+* demos: Add ARIA roles (Volker E)
+* demos: Clean up the window manager when destroying the dialogs demo (Bartosz Dziewoński)
+* demos: Preserve scroll position when changing non-page options (Bartosz Dziewoński)
+* demos: Rename deprecated Card to current TabPanel (Volker E)
+* demos: Tame buggy mobile browser behaviour on `position: fixed` (Volker E)
+* demos: Turn the menu into a fixed header (Bartosz Dziewoński)
+* docs: Fix `OO.ui.IndexLayout` example (Volker E)
+* tests: Order the `attributes` object keys, for less noisy diffs (Bartosz Dziewoński)
+
+
+## v0.21.3 / 2017-05-09
+### Deprecations
+* [DEPRECATING CHANGE] Merge functionality of FloatingMenuSelectWidget into MenuSelectWidget (Bartosz Dziewoński)
+* [DEPRECATING CHANGE] Rename CardLayout to TabPanelLayout (Prateek Saxena)
+* [DEPRECATING CHANGE] icons: Deprecate 'bookmark' icon (Volker E)
+* [DEPRECATING CHANGE] icons: Merge 'caret' into regular movement icons (James D. Forrester)
+
+### Styles
+* OptionWidget: Use parent selector for icon/indicator/label styles (Roan Kattouw)
+* Apex theme: Follow same FieldLayout `margin` logic as MediaWiki theme (Volker E)
+* MediaWiki theme: Bring styling to design spec in Safari/iOS (Volker E)
+* MediaWiki theme: Fix ButtonInputWidget appearance in Saf/iOS (Volker E)
+* MediaWiki theme: Fix `padding` for frameless buttons in ProcessDialogs (Ed Sanders)
+* MediaWiki theme: Provide focus indicator to TagMultiselectWidget (Volker E)
+* MediaWiki theme: Unify and harmonize `padding`/position of Tag*Widgets (Volker E)
+
+### Code
+* Fix some errors flagged by ESLint's 'valid-jsdoc' option (Bartosz Dziewoński)
+* NumberInputWidget: Followup db801c55f0 – clean up backward compat vars (Moriel Schottlender)
+* MenuSectionOptionWidget: Remove unsupported ARIA attribute (Volker E)
+* MenuSelectWidget: Scroll to the top if filtering and no exact match (David Lynch)
+* MenuSelectWidgets: Don't unconditionally hide all descendant inputs (Roan Kattouw)
+* TagMultiselectWidget: Actually use the focus trapping element (Bartosz Dziewoński)
+* TagMultiselectWidget: Fix `#addTag` return value to match docs (Bartosz Dziewoński)
+* TagMultiselectWidget: Fix keyboard navigation between items (Bartosz Dziewoński)
+* ToggleButtonWidget: Remove misleading `aria-checked` attribute (Volker E)
+* Unbreak FloatingMenuSelectWidget when `$container` is not given (Bartosz Dziewoński)
+* build: Fix invalid ecmaVersion setting (Timo Tijhof)
+* build: Use source maps in coverage report (James D. Forrester)
+* icons: Add first/last to complement previous/next in movement pack (Ed Sanders)
+* icons: Provide 'clip', 'unClip', and 'pushPin' in moderation (James D. Forrester)
+* tests: Do not set `QUnit.config.requireExpects = true` (Bartosz Dziewoński)
+
+
+## v0.21.2 / 2017-04-25
+### Features
+* Element: New method `#getElementId` (Bartosz Dziewoński)
+* NumberInputWidget: Remake as an actual TextInputWidget child (Moriel Schottlender)
+
+### Styles
+* ProgressBarWidget: Switch to `box-sizing: border-box` (Volker E)
+* TabOptionWidget: Cleanup & align paddings/position to dialog environment (Volker E)
+* MediaWiki theme: Decrease selector specificity and fix invalid appearance (Volker E)
+* MediaWiki theme: Fix IE 7 oversized buttons (Volker E)
+* MediaWiki theme: Improve SearchWidget design (Volker E)
+
+### Code
+* Do not use `role=menu`/`menuitem` for MenuSelectWidget/MenuOptionWidget (Bartosz Dziewoński)
+* PopupTagMultiselectWidget: Update popup position on resize (Prateek Saxena)
+* ProcessDialog: Display error messages on top of footer action buttons (Bartosz Dziewoński)
+* SelectWidget/MenuSelectWidget: Maintain `aria-activedescendant` attribute on focus owner (Bartosz Dziewoński)
+* Set ARIA `role=combobox` on DropdownWidget and LookupElement too (Bartosz Dziewoński)
+* Set `aria-owns` for everything with a dropdown list (ARIA `role=combobox`) (Bartosz Dziewoński)
+* Follow-up d22d23311: Don't reference OO.ui.ToolGroup blindly (James D. Forrester)
+* build: Bump grunt-stylelint, bring in stylelint explicitly (James D. Forrester)
+* demos: Add some more examples with 'accessKey' (Bartosz Dziewoński)
+* docs: Document Window#$overlay property (Bartosz Dziewoński)
+* tests: Drop unnecessary hints to qunit about the number of tests (James D. Forrester)
+
+
+## v0.21.1 / 2017-04-18
+### Styles
+* PopupWidget: Do not leave space for anchor if there's no anchor (Bartosz Dziewoński)
+* MediaWiki theme: Ensure WCAG level AA contrast on unsupported SelectFileWidget (Volker E)
+* MediaWiki theme: Fit icon/indicator & label in DecoratedOptionWidget (Volker E)
+* MediaWiki theme: Fix standalone, disabled sibling ButtonWidgets (Volker E)
+* MediaWiki theme: Fix white `border-color` of frameless buttons (Volker E)
+* MediaWiki theme: Make readonly TextInputWidget appearance clearer (Volker E)
+* MediaWiki theme: TagMultiselectWidget outlined UI improvements (Volker E)
+* MenuOptionWidget: Remove theme-independent 'check' icon (Prateek Saxena)
+
+### Code
+* environment: Upgrade jQuery from 1.11.3 to 3.2.1 (James D. Forrester)
+* DropdownInput-/RadioSelectInputWidget: Remove unnecessary ARIA attributes (Volker E)
+* Element: Use `JSON.parse` rather than the deprecated `$.parseJSON` (James D. Forrester)
+* Fix typo in frameless button mixin (David Lynch)
+* FloatingMenuSelectWidget: Add 'ready' event after menu is clipped (Moriel Schottlender)
+* MediaWiki theme: Clarify `@min-height-widget-default` usage (Volker E)
+* PopupToolGroup: Mixin flaggable (David Lynch)
+* TagMultiselectWidget: Allow preset InputWidget (Moriel Schottlender)
+* TagMultiselectWidget: Redo data validation for Tag* and Menu* (Moriel Schottlender)
+* themes: Align `@size-*-min` variable to naming scheme and rename (Volker E)
+* build: Drop the csscomb task (James D. Forrester)
+* docs: Fix numbering in Quick start (Kartik Mistry)
+* demos: Polish demo labels, styles and add frameless button tests (Volker E)
+* tests: Update OO.ui.Process tests for jQuery 3 compatibility (Bartosz Dziewoński)
+
+
+## v0.21.0 / 2017-04-11
+### Breaking changes
+* [BREAKING CHANGE] ActionWidget: Remove resize event (IvanFon)
+* [BREAKING CHANGE] dependencies: Drop support for ES3 browsers via es5-shim (James D. Forrester)
+
+### Features
+* Create a TagMultiselectWidget (Moriel Schottlender)
+* FloatingMenuSelectWidget: Add `width` config option (Moriel Schottlender)
+* MenuSelectWidget: Add `config.$autoCloseIgnore` (Roan Kattouw)
+
+### Styles
+* PopupWidget: Center the anchor for vertical (above/below) popups too (Bartosz Dziewoński)
+* MediaWiki theme: Add separator when toolbar items break on narrow (Volker E)
+* MediaWiki theme: Fix IE < 11 icon/indicator position in SelectFileWidget (Volker E)
+* MediaWiki theme: Fix overflow ellipsis on small DropdownWidget sizes (Volker E)
+* MediaWiki theme: Fix selector regression on DraggableElement (Volker E)
+* MediaWiki theme: Fix Toolbars containing ButtonGroups (David Lynch)
+* MediaWiki theme: Replace arrows with chevrons and increase contrast (Volker E)
+* MediaWiki theme: Unify `padding` across widgets and variablize (Volker E)
+* MediaWiki theme: Unify `padding` on ButtonElement (Volker E)
+* MediaWiki theme: Unify `padding` on DecoratedOptionWidget and descendants (Volker E)
+* Follow-up eceb6f20: MediaWiki theme: Remove unused indicator flags (Volker E)
+
+### Code
+* Remove remnants of PHP-5.3-style `array()` literals (Bartosz Dziewoński)
+* ClippableElement: Fix progressive width loss bug (Roan Kattouw)
+* ComboBoxInputWidget: Fix minor JS/PHP differences (Bartosz Dziewoński)
+* ComboBoxInputWidget: Redo the 'down' indicator in PHP (Bartosz Dziewoński)
+* DraggableElement: Only apply focus when widget is not disabled (Moriel Schottlender)
+* DraggableElement: Toggle style on `$handle`, not `$element` (Andrew Green)
+* DropdownInputWidget: Only allow setting values actually in the dropdown (Bartosz Dziewoński)
+* MenuSelectWidget: Highlight the first result when searching (Moriel Schottlender)
+* MessageDialog: Accept proposed size dialog on `getSetupProcess` (Ebrahim Byagowi)
+* TextInputWidget: Reduce unnecessary duplicated CSS output (Volker E)
+* TextInputWidget: Use `.prop()` rather than `.attr()` for 'required' (Bartosz Dziewoński)
+* Apex theme: Align coding style to conventions (Volker E)
+* Apex theme: Simplify color usage through Less variables (Volker E)
+* demos: Remove scaling restrictions (Volker E)
+* docparser: Improve trait/mixin handling (Bartosz Dziewoński)
+* docparser: Properly handle default values in PHP (Bartosz Dziewoński)
+* docs: Add detail to documentation of core.js utilities (Ed Sanders)
+* docs: Minor documentation tweaks (Bartosz Dziewoński)
+* tests: Comparison tests for infusing previously untestable classes (Bartosz Dziewoński)
+
+
+## v0.20.2 / 2017-03-30
+### Styles
+* DraggableElement: Fix regression on selectors (Volker E)
+
+### Code
+* GroupElement: Fix insertion bugs (Bartosz Dziewoński)
+* icons: Drop unused 'invert' variant from Apex 'icons-interactions' pack (Bartosz Dziewoński)
+* build: Add exec:composer and add it to `_ci` (Prateek Saxena)
+
+
+## v0.20.1 / 2017-03-28
+### Deprecations
+* [DEPRECATING CHANGE] icons: Deprecate and/or move all the core icons (James D. Forrester)
+* [DEPRECATING CHANGE] icons: Rename 'wikitrail' to 'mapTrail' (Volker E)
+* Follow-up b12205ac: Add deprecation notices to icons moved in v0.16.2 (James D. Forrester)
+* Follow-up da8d99af: Add deprecation notice to icon moved in v0.14.0 (James D. Forrester)
+
+### Features
+* DraggableGroupElement: Make draggable conditional (Moriel Schottlender)
+* build: Implement `grunt add-theme` task to ease theme creation (Bartosz Dziewoński)
+
+### Styles
+* ButtonElement: Normalize appearance in Firefox (Volker E)
+* Blank theme: Fix up the 'blank' theme (Bartosz Dziewoński)
+* MediaWiki theme: Position PopupToolGroup indicator similar to other widgets (Volker E)
+
+### Code
+* Element: Add special case for document root in getClosestScrollableContainer (Bartosz Dziewoński)
+* FloatableElement: Abort positioning if no longer attached (David Lynch)
+* GroupElement: Transform to be an OO.EmitterList mixin (Moriel Schottlender)
+* MenuOptionWidget: Remove inherited, duplicated property (Volker E)
+* OO.ui.isFocusableElement: Update for jQuery 3 deprecations (Bartosz Dziewoński)
+* PopupWidget: Add 'ready' event when the popup is ready (Moriel Schottlender)
+* Use Node.DOCUMENT_NODE rather than magic number (Bartosz Dziewoński)
+* Follow-up 4bc67351c5: Unbreak FloatableElement positioning (Roan Kattouw)
+* Follow-up Iaa7dffc13: *Actually* allow `$returnFocusTo` to be `null` (Ed Sanders)
+* themes: Reorder Less rules alphabetically (Volker E)
+* MediaWiki theme: Remove obsolete ButtonOptionWidget styles (Volker E)
+* MediaWiki theme: Remove unnecessary OptionWiget `border` property (Volker E)
+* build: Add a new jenkins script (Prateek Saxena)
+* build: Bump grunt-cssjanus to master (Volker E)
+* build: Match file order between tests/index and karma (Timo Tijhof)
+* build/demos: Generalize demos and build so that it's easier to add new themes (Bartosz Dziewoński)
+
+
+## v0.20.0 / 2017-03-15
+### Breaking changes
+* [BREAKING CHANGE] Element#scrollIntoView: Drop `complete` config option (James D. Forrester)
+* [BREAKING CHANGE] Element#scrollIntoView: Remove deprecated `complete` config parameter (James D. Forrester)
+* [BREAKING CHANGE] LabelElement: Remove deprecated `fitLabel` function (James D. Forrester)
+* [BREAKING CHANGE] MessageDialog: Drop the deprecated '`verbose`' flag (James D. Forrester)
+* [BREAKING CHANGE] PopupWidget#setAlignment: Remove backwards-compatibility (James D. Forrester)
+* [BREAKING CHANGE] Remove CapsuleMultiSelectWidget (James D. Forrester)
+* [BREAKING CHANGE] Remove TextInputMenuSelectWidget (James D. Forrester)
+* [BREAKING CHANGE] TextInputWidget: Remove `type=date`/`month` support (Geoffrey Mon)
+* [BREAKING CHANGE] icons: Drop '…Undo' icons, deprecated in 0.18.3 (James D. Forrester)
+* [BREAKING CHANGE] icons: Drop 'beta' and 'ribbonPrize', deprecated in 0.18.3 (James D. Forrester)
+* [BREAKING CHANGE] icons: Drop 'betaLaunch', deprecated in 0.18.3 (James D. Forrester)
+* [BREAKING CHANGE] icons: Drop status flags from Wikimedia (logos) icon pack (Volker E)
+
+### Deprecations
+* [DEPRECATING CHANGE] ActionWidget/Set: Warn for methods using the `resize` event (Prateek Saxena)
+
+### Features
+* Use `<span>` rather than `<div>` for inline-ish widgets (Bartosz Dziewoński)
+* CapsuleMultiselectWidget: Call `updateInputSize` when adding, removing items (Prateek Saxena)
+* DropdownInputWidget: Add support for `optgroup` (Prateek Saxena)
+* FieldLayout: Use `<span>` rather than `<div>` when possible (Bartosz Dziewoński)
+
+### Styles
+* DropdownInputWidget: Tweak PHP widget's disabled styling (Bartosz Dziewoński)
+* NumberInputWidget: Set input to 100% height (Volker E)
+* MediaWiki theme: Add unit to `line-height` for Chrome (Volker E)
+* MediaWiki theme: Align “framed” ButtonWidgets cross-browser (Volker E)
+* MediaWiki theme: Ensure theme color in disabled TextInputWidget on Safari (Volker E)
+* MediaWiki theme: Ensure vertical alignment of dialog top bar items (Volker E)
+* MediaWiki theme: Fix TextInputWidget's IconElement `max-height` (Volker E)
+* MediaWiki theme: Fix appearance of ComboBoxInputWidget PHP (Volker E)
+* MediaWiki theme: Use color palette color for dialog top bar (Volker E)
+* MediaWiki theme: Vertically align label in SelectFileWidget (Volker E)
+
+### Code
+* DropdownInputWidget: Remove accidental patterned background in PHP (Bartosz Dziewoński)
+* MediaWiki theme: Align WindowManager to CSS Coding Guidelines (Volker E)
+* MediaWiki theme: Indicators shouldn't provide global `progressive` flag (Volker E)
+* MediaWiki theme: Simplify Radio- & Checkbox…optionWidget label rules (Volker E)
+* build: Bump various devDependencies to master (James D. Forrester)
+* build: Exclude demos/vendor from composer test too (James D. Forrester)
+* demos: Add ButtonGroupWidget (icon and text) demo (Volker E)
+* demos: Add disabled DropdownInputWidget demo (Bartosz Dziewoński)
+
+
+## v0.19.5 / 2017-03-07
+### Deprecations
+* [DEPRECATING CHANGE] icons: Move 'add' from core to 'interactions' pack (James D. Forrester)
+
+### Features
+* FloatableElement: Add config for `hideWhenOutOfView` (Moriel Schottlender)
+
+### Styles
+* MediaWiki theme: Add visual feedback on focussed Outlined Booklet Dialog (Volker E)
+* OutlinedBookletDialog: Bring visual order into levels (Volker E)
+* icons: Add 'highlight' to 'editing-styling' pack (Moriel Schottlender)
+* icons: Add 'substract' icon, in interactions pack (Volker E)
+* icons: Fix vertical alignment of 'journal' (Volker E)
+* icons: Remove 'teardrop' from MediaWiki theme 'close' icon (Volker E)
+
+### Code
+* CapsuleMultiselectWidget: Update popup position if height changed (Prateek Saxena)
+* ComboBoxInputWidget: Improve documentation example (Bartosz Dziewoński)
+* ListToolGroup: Re-clip when expanding/collapsing (Roan Kattouw)
+* MenuSelectWidget#filterFromInput: Clear MenuSectionOptionWidgets if empty (Roan Kattouw)
+* PopupElement: Set `$floatableContainer` to `this.$element` by default (Roan Kattouw)
+* PopupTool: For bottom toolbars, make the popup go up, like toolgroups (Bartosz Dziewoński)
+* PopupWidget: Make popups able to actually pop *up*, as well as sideways (Roan Kattouw)
+* PopupWidget: Position anchor relative to popup, not popup relative to anchor (Roan Kattouw)
+* TextInputWidget: Fix documentation for 'maxRows' type (Bartosz Dziewoński)
+* Use `options` in ComboBoxInputWidget demo (Moriel Schottlender)
+* Follow-up 442ffe73, 7f21350d, 9dfa5dd5: Mention in icon definitions they're deprecated (James D. Forrester)
+* demos: Make demo consoles LTR, even in the RTL demo (Roan Kattouw)
+* demos: Add demo/test for PopupWidget/PopupButtonWidget placements (Bartosz Dziewoński)
+* demos: Add sections to dialogs demo (Bartosz Dziewoński)
+* demos: Extract widgets, dialogs and layouts from dialogs.js (Bartosz Dziewoński)
+* demos: Reuse some widgets in the dialogs demo (Bartosz Dziewoński)
+* styles: Replace stylelint block with inline comments everywhere (Volker E)
+
+
+## v0.19.4 / 2017-02-28
+### Features
+* Add `OO.ui.Element.static.getScrollLeft` (Bartosz Dziewoński)
+* FloatableElement: Support positioning relative to all edges (Roan Kattouw)
+
+### Styles
+* MediaWiki theme: Align DraggableElement focus with standard appearance (Volker E)
+* MediaWiki theme: Align appearance of PHP DropdownInputWidget to JS (Volker E)
+* MediaWiki theme: Fix TextInputWidget inline label misalignment (Volker E)
+* MediaWiki theme: Fix ToolGroupTool's label alignment (Volker E)
+* MediaWiki theme: Fix button layout in ButtonGroup-/SelectWidgets in IE 9 (Volker E)
+* MediaWiki theme: Fix styling for FieldLayout inside HorizontalLayout (Bartosz Dziewoński)
+* styles: Improve vertical alignment of elements' & widgets' icons (Ed Sanders/Volker E)
+* icons: Add 'feedback' icon, in interactions pack (Roan Kattouw)
+* icons: Add 'searchDiacritic' icon, in editing-advanced pack (Ed Sanders)
+
+### Code
+* Make generic placeholder pseudo-class browser-prefix mixin (Ed Sanders)
+* BookletLayout: When continuous, properly make the inner PageLayouts non-scrollable (Bartosz Dziewoński)
+* Element: Fix `scrollLeft()` for body/html/window (Roan Kattouw)
+* OutlineOptionWidget: Remove unused and misplaced values (Volker E)
+* PopupWidget: Remove `left: 0;` breaking floatable popups (Roan Kattouw)
+* MediaWiki theme: Remove obsolete ComboBoxInputWidget selectors (Volker E)
+* README: Encourage direct release in the instructions (James D. Forrester)
+* build: Test the 'minify' task in CI (James D. Forrester)
+* demos: Add 'label' to ToolGroupTool example (Bartosz Dziewoński)
+* demos: Extract ButtonStyleShowcaseWidget from the demo code (Bartosz Dziewoński)
+* demos: Extract CapsuleNumberPopupMultiselectWidget from the demo code (Bartosz Dziewoński)
+* demos: Extract remaining widgets from widgets.js (Bartosz Dziewoński)
+
+
+## v0.19.3 / 2017-02-21
+### Features
+* FieldLayout, FieldsetLayout: Add support for `$overlay` for help popups (Bartosz Dziewoński)
+* MenuSelectWidget: Add config option to not close on choose (Roan Kattouw)
+
+### Styles
+* MediaWiki theme: Make CapsuleItemWidget behave similar to other widgets (Volker E)
+* MediaWiki theme: SelectFileWidget drop target aligned to UX patterns (Volker E)
+
+### Code
+* BookletLayout: Remove unnecessary overrides (Bartosz Dziewoński)
+* Element#getClosestScrollableContainer: Update code comment (Bartosz Dziewoński)
+* FieldLayout, LabelWidget: If input has no ID, focus on element on label click (Prateek Saxena)
+* PopupWidget (and similar): Document why it is unwise to show unattached widgets, and emit warnings (Bartosz Dziewoński)
+* build: Bump stylelint and make pass (James D. Forrester)
+* demos: Add DropdownWidget (with MenuSectionOptionWidget) (Prateek Saxena)
+* demos: Further improve responsive layout (Volker E)
+* demos: Minor tweaks for button style showcase code (Bartosz Dziewoński)
+* demos: Rename OO.ui.Demo to just Demo (Bartosz Dziewoński)
+* demos: Replace `table` in button style showcase with responsive layout (Volker E)
+* demos: Set the default page in demo.js (Bartosz Dziewoński)
+
+
+## v0.19.2 / 2017-02-14
+### Features
+* CapsuleMultiselectWidget: Make labels work (Prateek Saxena)
+* FloatableElement, PopupWidget: Do positioning from the right in RTL (Roan Kattouw)
+* TextInputWidget: getValidity: Check browser validation first (Prateek Saxena)
+
+### Styles
+* icons: Fix vertical alignment of eye icon (Ed Sanders)
+
+### Code
+* core: Do not clear unrelated flags when clearing 'progressive' (Bartosz Dziewoński)
+* ActionWidget: Remove event listening code for widget's 'resize' event (Prateek Saxena)
+* ClippableElement: Order matters (inexplicably) (Bartosz Dziewoński)
+* demos: Use longer text in popup in $overlay demo (Bartosz Dziewoński)
+
+
+## v0.19.1 / 2017-02-07
+### Features
+* Dialog: Support meta as well as ctrl for modifier on enter key (David Lynch)
+
+### Styles
+* FieldLayout: Fix styling for disabled widgets in PHP (Bartosz Dziewoński)
+* MediaWiki theme: Align tab navigation to color palette (Volker E)
+* MediaWiki theme: Fix RTL version of largerText icon to be, well, RTL (James D. Forrester)
+* MediaWiki theme: Fix direction of shadow on position:bottom toolbars (Ed Sanders)
+* MediaWiki theme: Use correct `border-color` on PopupWidget anchor (Volker E)
+* Mediawiki theme: Fix focus inset to overlap scrollbars (Volker E)
+* icons: Provide a 'halfStar' vertical split star (codynguyen1116)
+
+### Code
+* CheckboxMultiselectInputWidget: Allow disabling specific options (Huji Lee)
+* DraggableGroupElement: Add mandatory ARIA role (Volker E)
+* FieldLayout: Move `<label>` from `$body` to `$label` (Bartosz Dziewoński)
+* FieldLayout: Remove the need for `simulateLabelClick` (Prateek Saxena)
+* InputWidget: Fix 'id' attribute setting for `<label>` (Bartosz Dziewoński)
+* LabelWidget: Remove the need for `simulateLabelClick` (Prateek Saxena)
+* Toolbar: Make toolbar position selectors more specific (Ed Sanders)
+* WindowManager: Clarify `#addWindows` documentation (Bartosz Dziewoński)
+* Windows: Use the "recommended" `WindowManager#addWindows` usage (Bartosz Dziewoński)
+* Apex theme: Get rid of toolbar-shadow div (only used by Apex) (Ed Sanders)
+* MediaWiki theme: Remove unnecessary `font-weight` property (Volker E)
+* build: Bump various dev dependencies to latest (James D. Forrester)
+* colorize-svg: Colorize using a method compatible with rsvg (Bartosz Dziewoński)
+* demos: Load icons stylesheets with correct directionality (LTR/RTL) (Bartosz Dziewoński)
+* demos: Follow-up a02979ad: Load the icons-content pack in the PHP demo (James D. Forrester)
+* demos: Remove 'Constructive' button from the icons page (Prateek Saxena)
+* demos: Add link to documentation (Prateek Saxena)
+* demos: Fix regression on toolbars demo (Volker E)
+* docs: Add quotes around `PROJECT_NAME` setting (Ricordisamoa)
+* docs: Document for JSDuck various overridden inherited properties (Bartosz Dziewoński)
+* docs: Fix `OO.ui.prompt()` documentation (Bartosz Dziewoński)
+* docs: Set `.static.name` in all dialog examples that need it (Bartosz Dziewoński)
+
+
+## v0.19.0 / 2017-01-31
+### Breaking changes
+* [BREAKING CHANGE] ButtonWidget: Switch `box-sizing` over to `border-box` (Volker E)
+* [BREAKING CHANGE] LabelElement: Drop no-op fitLabel() method. (James D. Forrester)
+* [BREAKING CHANGE] WindowManager: Error if `.static.name` is not defined when adding a window (Bartosz Dziewoński)
+
+### Features
+* PopupButtonWidget: Add `$overlay` config option (Bartosz Dziewoński)
+* SelectWidget: Allow OptionWidget subclasses to provide custom match text (Roan Kattouw)
+* Toolbar: Support `position:bottom` (Ed Sanders)
+
+### Styles
+* CapsuleMultiselectWidget: Fix focussing when inside BookletLayout with popup (Bartosz Dziewoński)
+* CapsuleMultiselectWidget: Styling tweaks related to popups (Bartosz Dziewoński)
+* MenuSelectWidget: Override ClippableElement's `min-height` (Bartosz Dziewoński)
+* PopupWidgets: Unify paddings and line-height (Bartosz Dziewoński)
+* TextInputWidget/MediaWiki theme: Revert "Improve Less code and align labels" (Bartosz Dziewoński)
+* PanelLayout/Apex theme: Revert regression (Volker E)
+
+### Code
+* CapsuleMultiSelectWidget: Call correct parent constructor (Ricordisamoa)
+* CapsuleMultiselectWidget: Make popup really work with $overlay (Bartosz Dziewoński)
+* FieldsetLayout: Swap 'max-width' and 'width' (Bartosz Dziewoński)
+* FloatableElement: More correctly decide if we need custom position (Bartosz Dziewoński)
+* MenuSelectWidget: Hide menu if all items are hidden (Bartosz Dziewoński)
+* ProcessDialog: Account for `config.flags` being undefined (Ed Sanders)
+* Follow-up 1dc6a45: {Booklet,Index}Layout: Avoid deprecated `config.complete` (Roan Kattouw)
+* Follow-up d21cf8a: unbreak popups with no $floatableContainer (Roan Kattouw)
+* PHP: Avoid unique ID conflicts between PHP and JS code (Bartosz Dziewoński)
+* demos: Failing demo for DropdownWidget with an overlay (Roan Kattouw)
+* demos: Fix vertical spacing in icons demo (Bartosz Dziewoński)
+* demos: Improve layout on mobile and fix various glitches (Volker E)
+* demos: Make the icon page easier to use (Prateek Saxena)
+* demos: Use longer text in PopupWidgets to showcase line wrapping (Bartosz Dziewoński)
+
+
+## v0.18.4 / 2017-01-17
+### Deprecations
+* [DEPRECATING CHANGE] MessageDialog: Default 'verbose' option to true (James D. Forrester)
+* Follow-up 1dc6a45: Emit deprecations from Element#scrollIntoView callback (James D. Forrester)
+* Follow-up 4518bcf: Emit deprecation warnings for LabelElement#fitLabel (James D. Forrester)
+* Follow-up 574fd34: Emit deprecations for use of CapsuleMultiSelectWidget (James D. Forrester)
+* Follow-up ea9a4ac: Throw deprecation warnings for TextInputMenuSelectWidget (James D. Forrester)
+* Follow-up f69a2ad: Emit deprecations for old PopupWidget#setAlignment values (James D. Forrester)
+
+### Features
+* CapsuleMultiSelectWidget: Add allowDuplicates option (Brad Jorsch)
+* CapsuleMultiSelectWidget: Remove onFocusForPopup, call focus directly (Roan Kattouw)
+* ClippableElement: Add `min-height` for usability in edge cases (Volker E)
+* TextInputWidget: Disable hiding focus when clicking indicator/label (Volker E)
+
+### Styles
+* ActionFieldLayout: Limit the 'max-width: 50em' to align: top (Bartosz Dziewoński)
+* ButtonGroupWidget: Limit default cursor to active ButtonWidgets (Volker E)
+* FieldLayout, FieldsetLayout: Limit width of label+help to 50em (Bartosz Dziewoński)
+* FieldLayout: Correct styling regressions for align: 'inline' (Bartosz Dziewoński)
+* FieldLayout: Fix positioning of 'help' with align: left/right (Bartosz Dziewoński)
+* MediaWiki theme: Unify box-shadows to one visual appearance (Volker E)
+* PanelLayout: Remove 3D appearance of framed panels and harmonise padding (Volker E)
+* PopupWidget: Change margins to prevent click blocking (Ed Sanders)
+
+### Code
+* ClippableElement: Also clean up `maxWidth`, `maxHeight` when turning clipping off (Bartosz Dziewoński)
+* Element#updateThemeClasses: Batch `setTimeout()` calls (Bartosz Dziewoński)
+* MediaWiki theme: Use variable for disabled ProgressBar (Volker E)
+* PopupWidget#setAlignment: Tweak docs to indicate default parameter value (James D. Forrester)
+* PHP: Add method Tag::generateElementId() to match JS OO.ui.generateElementId() (Bartosz Dziewoński)
+* styles: Improve and clarify GPU composite layer mixin (Volker E)
+* demos: Add a LabelWidget that has a corresponding TextInputWidget (Prateek Saxena)
+* demos: Add lots more FieldLayout demos (Bartosz Dziewoński)
+* demos: Add test for ClippableElements at the bottom of their containers (Prateek Saxena)
+* docs: Use 'an' instead of 'a' before 'HTML' (Prateek Saxena)
+* docs: Include an i18n example in OO.ui.msg documentation (David Lynch)
+* tests: Improve ignoring expected differences in JS/PHP comparison tests (Bartosz Dziewoński)
+* tests: Tweaks to the display of failed tests (Bartosz Dziewoński)
+* testsuitegenerator: Allow testing LabelWidget's 'input' (Bartosz Dziewoński)
+* testsuitegenerator: Specify sensible values to test for 'align' (Bartosz Dziewoński)
+* testsuitegenerator: Test FieldLayout etc. also with TextInputWidget (Bartosz Dziewoński)
+
+
+## v0.18.3 / 2017-01-03
+### Deprecations
+* [DEPRECATING CHANGE] icons: Deprecate the 'beta' and 'ribbonPrize' icons (James D. Forrester)
+* [DEPRECATING CHANGE] icons: Rename '*Undo' to 'un*' (James D. Forrester)
+* [DEPRECATING CHANGE] icons: Rename 'betaLaunch' to 'logoWikimediaDiscovery', move pack (James D. Forrester)
+
+### Features
+* ComboBoxInputWidget: Make it impossible to set `multiline` to true (Prateek Saxena)
+* Introduce `OO.ui.isMobile()` (Ed Sanders)
+* Provide `OO.ui.prompt()` method to complement `confirm()`/`alert()` (Ed Sanders)
+
+### Styles
+* FloatableElement: Replace superfluous class with general one (Volker E)
+* MediaWiki theme: Change custom error border color to `destructive` (Volker E)
+* MediaWiki theme: Change error/invalid color to alias of `destructive` (Volker E)
+* MediaWiki theme: Fix PHP CheckboxMultiselectInputWidget/RadioSelectInputWidget option spacing (Bartosz Dziewoński)
+* MediaWiki theme: Indicate normal, flagged ButtonWidgets' `:hover` clearer (Volker E)
+* MediaWiki theme: Set `line-height` explicitly on legends and labels (Volker E)
+
+### Code
+* BarToolGroup: Remove obsolete CSS selectors (Volker E)
+* ClippableElement: Compatibility with jQuery 3 (Bartosz Dziewoński)
+* Element: Do not try to scroll invisible/unattached elements into view (Bartosz Dziewoński)
+* LabelWidget: Properly hide labels if they are set to null (Ed Sanders)
+* NumberInputWidget: Avoid bitwise tricks when checking for integers (Bartosz Dziewoński)
+* PopupButtonWidget: Remove unnecessary CSS property (Volker E)
+* ProgressBarWidget: Use CSS transforms for indeterminate widget (Bartosz Dziewoński)
+* TextInputWidget: Do nothing in `#adjustSize`/`#positionLabel` if not attached (Bartosz Dziewoński)
+* TextInputWidget: Only call `#onElementAttach` on focus if it wasn't called (Bartosz Dziewoński)
+* TextInputWidget: Use `Element#isElementAttached` (Bartosz Dziewoński)
+* styles: Replace `transform` with dedicated mixin (Volker E)
+* MediaWiki theme: Make `box-shadow` LESS vars follow naming scheme (Volker E)
+* MediaWiki theme: Simplify frameless ButtonWidget selectors (Volker E)
+* performance: Apply webkit GPU hack to scrollable panels (Ed Sanders)
+* demos: Add disabled Progress bar (Volker E)
+* demos: Add examples for `OO.ui.alert()`/`confirm()`/`prompt()` (Bartosz Dziewoński)
+* demos: Avoid using 'required' as a test indicator (Ed Sanders)
+* build: Bump file copyright notices for 2017 (James D. Forrester)
+* docs: Fix small typo (Amir Sarabadani)
+
+
+## v0.18.2 / 2016-12-06
+### Styles
+* MediaWiki theme: Address sub-pixel rendering issues of RadioInputWidgets (Volker E)
+* MediaWiki theme: Improve `:active:focus` states on ButtonElements (Volker E)
+* MediaWiki theme: Reduce MapPin icons' hole for better recognisability (Volker E)
+
+### Code
+* FieldsetLayout: Temporarily remove use of `<legend>` due to Chrome 55 bug (Bartosz Dziewoński)
+* TextInputWidget/MediaWiki theme: Improve Less code and align labels (Volker E)
+
+
+## v0.18.1 / 2016-11-29
+### Features
+* PopupElement: Allow $autoCloseIgnore to be overridden (Roan Kattouw)
+* WindowManager: Allow $returnFocusTo to be null (Ed Sanders)
+
+### Styles
+* MediaWiki theme: Reduce, align `margin` and `padding` of form elements (Volker E)
+* MediaWiki theme: Replace color function with palette color (Volker E)
+* MediaWiki theme: Standard placeholder colours for CapsuleMultiselectWidget too (Bartosz Dziewoński)
+* MediaWiki theme: Tweak destructive red for background-independent contrast (Volker E)
+
+### Code
+* Field & Fieldset: Make help popup code consistent (Ed Sanders)
+* PopupWidget: Consistently use OO.ui.contains() for auto-closing (Roan Kattouw)
+* build: Bump eslint-config-wikimedia to v0.3.0 and make pass (James D. Forrester)
+* eslint: Re-enable wrap-iife and partially enable dot-notation (Ed Sanders)
+
+
+## v0.18.0 / 2016-11-08
+### Breaking changes
+* [BREAKING CHANGE] ComboBoxWidget: Remove this deprecated alias for ComboBoxInputWidget (James D. Forrester)
+* [BREAKING CHANGE] core: Remove {add|remove}CaptureEventListener (James D. Forrester)
+* [BREAKING CHANGE] icons: Remove deprecated alias 'photoGallery' (Ed Sanders)
+* [BREAKING CHANGE] InputWidget: Remove deprecated #setRTL function (James D. Forrester)
+* [BREAKING CHANGE] MediaWiki theme: Remove deprecated `constructive` variables (Volker E)
+* [BREAKING CHANGE] TextInputWidget: remove isValid() method, deprecated since v0.12.3 (Ricordisamoa)
+
+### Deprecations
+* [DEPRECATING CHANGE] Break out parts of TextInputWidget into a new SearchInputWidget (Prateek Saxena)
+
+### Features
+* ButtonElement: Add `role="button"` only when needed (Prateek Saxena)
+* ButtonWidget: Remove code to not let the button get focus after clicking (Prateek Saxena)
+* CapsuleMultiselectWidget: Add placeholder option (Prateek Saxena)
+* CapsuleMultiselectWidget: Don't discard current input value when editing an item (Bartosz Dziewoński)
+* ComboBoxInputWidget: Hide dropdown indicator when there is no dropdown (Volker E)
+* TextInputWidget: Add methods #setRequired / #isRequired (Bartosz Dziewoński)
+* TextInputWidget: Allow type="month" (Geoffrey Mon)
+* WindowManager: Add a $returnFocusTo property (Prateek Saxena)
+* Add OO.ui.warnDeprecation method (Prateek Saxena)
+
+### Styles
+* ButtonElement: Normalize `:focus` appearance in Firefox (Volker E)
+* ButtonGroupWidget: Change `cursor` on `.oo-ui-buttonElement-active` (Volker E)
+* CapsuleItemWidget: Make interactivity of label clearer (Volker E)
+* ComboBoxInputWidget: Align to design specification (Volker E)
+* PopupToolGroup: Fix border colour (Ed Sanders)
+* MessageDialog: Improve `-actions` buttons by resetting `border-radius` (Volker E)
+* SelectFileWidget: Don't show action-indicating cursor on empty state (Volker E)
+* MediaWiki theme: Fix border colours in toolbar (Ed Sanders)
+* MediaWiki theme: Address subpixel rendering errors in buttoned widgets (Volker E)
+* MediaWiki theme: Align readonly TextInputWidget to overhauled color palette (Volker E)
+* MediaWiki theme: Fix `:hover` in ComboBoxInput- & CapsuleMultiselectWidget (Volker E)
+* MediaWiki theme: Fix ButtonElement's `:active:focus` state visually (Volker E)
+* MediaWiki theme: Fix FieldsetLayouts' icon position (Volker E)
+* MediaWiki theme: Fix SelectFileWidget's label visibility in IE11 (Volker E)
+* MediaWiki theme: Fix visual glitch CheckboxInputWidget's `:active` state (Volker E)
+* MediaWiki theme: Fix visual glitch on `:active:focus` widgets state (Volker E)
+* MediaWiki theme: Fix wrong colored `box-shadow` on ToggleSwitchWidget (Volker E)
+* MediaWiki theme: Make colors follow color palette (Volker E)
+* MediaWiki theme: Make placeholder follow WCAG 2.0 level AA contrast ratio (Volker E)
+* MediaWiki theme: Replace abandoned color from early palette iteration (Volker E)
+* MediaWiki theme: Use `@color-progressive` for progress bar (Volker E)
+* MediaWiki theme: Use `color-progressive` for switched-on binary inputs (Volker E)
+* icons: Replace bigger/smaller with more obvious forms (Ed Sanders)
+
+### Code
+* CapsuleMultiSelectWidget: Always keep input as wide as placeholder text (Prateek Saxena)
+* CapsuleMultiselectWidget: Fix crash on right-click when no input (Moriel Schottlender)
+* OutlineOptionWidget: Follow-up de9058299f: don't duplicate parent's logic (Roan Kattouw)
+* Toolbar: Defer computation of the narrow threshold (Roan Kattouw)
+* Window: Update `-content` CSS so that child elements can give it focus (Prateek Saxena)
+* Window#withoutSizeTransitions: Build transition property using sub-properties (Prateek Saxena)
+* WindowManager: Warn if .static.name is not defined when adding a window (Bartosz Dziewoński)
+* Tag: Generate valid HTML for self-closing tags (Bartosz Dziewoński)
+* OO.ui.warnDeprecation: Fix how we use getProp (Prateek Saxena)
+* MediaWiki theme: Add W3C Standards Notation for placeholder pseudo class (Volker E)
+* MediaWiki theme: Clarify usage of `@max-width-*` Less variables (Volker E)
+* MediaWiki theme: Refactor z-index inside ButtonSelectWidget/ButtonGroupWidget (Bartosz Dziewoński)
+* demo: Add FieldsetLayout with icon (Bartosz Dziewoński)
+* demo: Align to color palette (Volker E)
+* demo: Fix for IE 9 (Bartosz Dziewoński)
+* demo: Remove deprecated TextInputWidget (type=search) (Volker E)
+* demo: Fix PHP demo directionality (Bartosz Dziewoński)
+* demo: Remove PHP 5.3 compatibility, version check and PHPCS exception (Bartosz Dziewoński)
+* build: Make MediaWiki the default theme in doc live previews (Ed Sanders)
+* build: Remove obsolete csscomb rules (Volker E)
+* build: Remove upstreamed rules and fix documentation (Ed Sanders)
+* build: Update eslint-config-wikimedia to v0.2.0 (Ed Sanders)
+
+## v0.17.10 / 2016-10-03 (special release)
+### Styles
+* FieldsetLayout: Styling fixes for `<legend>` labels (Bartosz Dziewoński)
+* FieldsetLayout: Work around positioning problems in Firefox (Bartosz Dziewoński)
+
+## v0.17.9 / 2016-09-13
+### Features
+* DropdownWidget: Add CSS class to widgets with open dropdown menus (Volker E)
+* SelectFileWidget: Remove MIME type information (Volker E)
+* TextInputWidget: Make disabled fields' inner labels unselectable (Volker E)
+
+### Styles
+* ActionToolGroup: Show left border, instead of right (Ed Sanders)
+* ButtonElement: Centralize styling properties (Volker E)
+* ButtonOptionWidget: Make active state carry default cursor (Volker E)
+* Radio- and CheckboxInputWidget: Fix visual disabled state on labels (Volker E)
+* ToggleButtonWidget: Use inverted variant when initially active (Leszek Manicki)
+
+* MediaWiki theme: Adjust CheckboxInputWidget to match M30 design (Volker E)
+* MediaWiki theme: Adjust RadioInputWidget to match M29 design (Volker E)
+* MediaWiki theme: Align Dropdown- & CapsuleMultiSelectWidget `:focus` state (Volker E)
+* MediaWiki theme: Align disabled text contrast to WCAG compliance (Volker E)
+* MediaWiki theme: Enhance button styles and align them to new color palette (Volker E)
+* MediaWiki theme: Fix ButtonElement-active on flagged & primary buttons (Volker E)
+* MediaWiki theme: Fix `:hover` state of ComboBoxInputWidget (Volker E)
+* MediaWiki theme: Fix regression on `border` of active (selected) buttons (Volker E)
+* MediaWiki theme: Improve appearance of CapsuleMultiselectWidget with child (Volker E)
+* MediaWiki theme: Make ToggleSwitchWidget's disabled state follow enabled (Volker E)
+* MediaWiki theme: Make colors' contrast compliant to WCAG 2.0 level AA (Volker E)
+* MediaWiki theme: Toolbar: Use progressive colors for active and active-hover (Prateek Saxena)
+* MediaWiki theme: Unify `-pressed` and `-emphasized` color var (Volker E)
+* MediaWiki theme: Unify different widgets' selected menu state (Volker E)
+* MediaWiki theme: Use a solid border for disabled SelectFile drop target (Volker E)
+
+### Code
+* FieldsetLayout: Make use of `<fieldset>` and `<legend>` tags (Volker E)
+* NumberInputWidget: Clean-up Less code & remove style properties (Volker E)
+* NumberInputWidget: Simplify CSS selectors & fix button text alignment (Volker E)
+* TextInputWidget: Treat `rows: 0` the same in PHP and in JS (Bartosz Dziewoński)
+* Toolbar: Simplify and concatenate selectors (Volker E)
+* MediaWiki theme: Align tools' variables to common vars naming convention (Volker E)
+* MediaWiki theme: Clean-up unnecessary properties in ToolGroup (Volker E)
+* build: Align csscomb configuration with CSS coding conventions (Volker E)
+* build: Introduce eslint to replace jshint and jscs (James D. Forrester)
+* build: Limit the file list of jsonlint (Ed Sanders)
+* build: Remove jshint and jscs, now done in eslint (James D. Forrester)
+* docs: IndexLayout: Fix ReferenceError in code sample (Prateek Saxena)
+* git: Add .idea directory to .gitignore (Florian)
+* testsuitegenerator: Also support 'int' and 'bool' (Bartosz Dziewoński)
+* testsuitegenerator: Simplify code generating all possible config options (Bartosz Dziewoński)
+
+
+## v0.17.8 / 2016-08-16
+### Features
+* ProgressBarWidget: Do not make zero progress indeterminate (Leszek Manicki)
+* ProgressBarWidget: Add PHP version (Leszek Manicki)
+* TextInputWidget: Show state as valid (no matter the case) on focus (Prateek Saxena)
+
+### Styles
+* ButtonElement: Fix 'active' state icon variants in MediaWiki theme (Bartosz Dziewoński)
+* FieldLayout: Use saner line-height for errors/notices (Bartosz Dziewoński)
+* SelectFileWidget: Improve thumbnail appearance (Volker E)
+* styles: Inherit specific `font` properties, not all (Volker E)
+* MediaWiki theme: Clear border on selected framed buttons (Volker E)
+* MediaWiki theme: Fix ButtonWidget (frameless, indicator) `:focus` appearance (Volker E)
+* MediaWiki theme: Fix ToggleSwitchWidget's sub-pixel rounding errors (Volker E)
+
+
+### Code
+* MediaWiki theme: Improve CapsuleMultiselectWidget Less code and behaviour (Volker E)
+* MediaWiki theme: Improve DropdownWidget Less code and behaviour (Volker E)
+* MediaWiki theme: Removing never applied styles on BarToolGroup (Volker E)
+* MediaWiki theme: Simplify ToolGroup selectors (Volker E)
+* testsuitegenerator: Specify sensible values to test for 'progress' (Bartosz Dziewoński)
+
+
+## v0.17.7 / 2016-08-03
+### Styles
+* MediaWiki theme: Apply `border-color` on `:hover` to textInputWidgets (Volker E)
+* MediaWiki theme: Decrease `margin`/`padding` on `legend` replacement (Volker E)
+* MediaWiki theme: Decrease distance between label and Checkbox*-/Radio*Widget (Volker E)
+* MediaWiki theme: Improve UX on ToggleSwitchWidget (Volker E)
+* icons: Fix vertical alignment of 'bell' by moving up 1px (Ed Sanders)
+* icons: Provide a 'tray' icon in alerts pack (James D. Forrester)
+* icons: Provide the alerts pack for Apex theme too (James D. Forrester)
+
+### Code
+* CheckboxMultiselectWidget: Rewrite Shift-clicking code (Bartosz Dziewoński)
+* NumberInputWidget: Merge object literals being passed as config for buttons (Prateek Saxena)
+* SelectFileWidget: Reduce div soup when 'showDropTarget' is enabled (Prateek Saxena)
+* styles: Replace unprefixed `box-sizing` property with mixin (Volker E)
+* MediaWiki theme: Disable vendor UI extensions on every `type=number` input (Volker E)
+* MediaWiki theme: Remove unnecessary toolGroup selector (Volker E)
+* MediaWiki theme: Replace `border` property values with Less variables (Volker E)
+* MediaWiki theme: Replace static `color` value with Less variable (Volker E)
+* build: Add 'prep-test' task to be run before running tests in the browser (Prateek Saxena)
+* build: Align to stylelint-config-wikimedia for `!important` (James D. Forrester)
+* build: Align to stylelint-config-wikimedia for string quotes (James D. Forrester)
+* build: Bump stylelint-related devDependencies to latest (James D. Forrester)
+* build: Downgrade grunt-jscs to 2.8.0 to avoid cst bug (James D. Forrester)
+* docs: Correct some code comments in PHP mixins (Bartosz Dziewoński)
+* standalone tests: Correct error message (Bartosz Dziewoński)
+
+
+## v0.17.6 / 2016-07-12
+### Features
+* CapsuleMultiselectWidget: Allow ignoring user input for 'allowArbitrary' widgets (Bartosz Dziewoński)
+* Dialog: Set the 'title' attribute on the title LabelWidget (Prateek Saxena)
+* ToolFactory: Allow '\*' as an item in a toolgroup include list (Ed Sanders)
+* Window: make the focus trap smarter (David Lynch)
+
+### Styles
+* Add aria-hidden to several Layouts (David Lynch)
+* Add dialog transition duration to theme JS file (Ed Sanders)
+* ButtonGroupWidget: Fix border on button's CSS states (Volker E)
+* MediaWiki theme: Normalize [placeholder] appearance x-browser and ensure a11y (Volker E)
+* MediaWiki theme: Unify ButtonWidget focus `border-radius` values (Volker E)
+* styles: Set `line-height` to unitless values to follow best practice (Volker E)
+* icons: Give "Stop" a filled background, aligned with others in the pack (Volker E)
+* icons: Unify cross-out lines direction to top-left/bottom-right (Volker E)
+
+### Code
+* README: Replace git.wikimedia.org URL with Phabricator one (Paladox)
+* build: Bump stylelint devDependencies to latest (James D. Forrester)
+* build: Update karma and karma-coverage to latest (Paladox)
+* demo: Dialogs: Removing title from SimpleDialog as it'll never show (Prateek Saxena)
+* docs: Remove self-closing tag syntax in comments and demos (Volker E)
+* docs: LabelWidget: Add TitledElement mixin (Prateek Saxena)
+* package: Replace git.wikimedia.org url with diffusion url (Paladox)
+
+
+## v0.17.5 / 2016-06-19
+### Styles
+* Dropdown,SelectFileWidget: Improve user experience on disabled widgets (Volker E)
+* MediaWiki theme: Fix ToggleSwitchWidget's grip circle shape (Volker E)
+* MediaWiki theme: Fix focus states of ActionWidget's buttons (Volker E)
+* MediaWiki theme: Improve focus states of primary buttons & ToggleSwitchWidget (Volker E)
+
+### Code
+* DraggableGroupWidget: Remove unnecessary `cursor` property (Volker E)
+* GroupElement#removeItems: Fix to actually unbind events (Ed Sanders)
+* ProcessDialog: Change DOM ordering of actions (David Lynch)
+* MediaWiki theme: Remove `line-height` from TextInputWidget `input` (Volker E)
+* MediaWiki theme: Remove obsolete `color` property, which never gets applied (Volker E)
+* build: Bump devDependencies to latest and make pass (James D. Forrester)
+* composer: Exclude copied demo PHP from phpcs test (James D. Forrester)
+* demos: Add descriptive hints on navigation types to dialog names (Volker E)
+
+
+## v0.17.4 / 2016-05-31
+### Features
+* DropdownWidget: Handle type-to-search when menu is not expanded (Bartosz Dziewoński)
+* Implement MultiselectWidget, CheckboxMultiselectWidget and CheckboxMultiselectInputWidget (Bartosz Dziewoński)
+* SelectWidget: Improve focus behaviour (Bartosz Dziewoński)
+
+### Styles
+* icons: Use B/I/S/U icons for British and Candian English variants (Ed Sanders)
+* MediaWiki theme: Provide an adjacent disabled ButtonGroup/SelectWidget button border (Volker E)
+* MediaWiki theme: Make iconed and non-iconed buttons have the same height (Roan Kattouw)
+
+### Code
+* ButtonElement: Remove unnecessary inheritance duplication of `display` (Volker E)
+* GroupWidget: Mix in GroupElement, rather than inherit from it (Bartosz Dziewoński)
+* LookupElement: Add missing `@mixins` documentation (Bartosz Dziewoński)
+* SelectWidget: Implement `#getFirstSelectableItem` in terms of `#getRelativeSelectableItem` (Bartosz Dziewoński)
+* SelectWidget: Optimize `#getRelativeSelectableItem` without filter (Bartosz Dziewoński)
+* styles: Remove unnecessary CSS rules on disabled buttons (Volker E)
+* styles: Simplify disabled `.oo-ui-tool-link` rules (Volker E)
+
+
+## v0.17.3 / 2016-05-24
+### Deprecations
+* [DEPRECATING CHANGE] CapsuleMultiSelectWidget: Rename to CapsuleMultiselectWidget (Bartosz Dziewoński)
+
+### Features
+* SelectWidget/OptionWidget: Implement selecting by accesskey (Bartosz Dziewoński)
+* TextInputWidget: Stop returning 'multiline' from 'getSaneType' (Prateek Saxena)
+
+### Styles
+* SelectFileWidget: Improve consistency to other widgets (Volker E)
+* MediaWiki theme: Align styles of normal and not-supported SelectFileWidgets (Volker E)
+
+### Code
+* CapsuleMultiselectWidget: Prefer Array#map to jQuery.map (Bartosz Dziewoński)
+* CapsuleMultiselectWidget: Use OO.ui.findFocusable() (Bartosz Dziewoński)
+* dependencies: Update es5-shim to v4.5.8 (James D. Forrester)
+* build: Bump grunt-stylelint to v0.3.0 (James D. Forrester)
+* build: Bump various devDependencies to latest (James D. Forrester)
+* build: Fix watch path for css (Ed Sanders)
+* build: Remove grunt-cli (Ed Sanders)
+* build: Upgrade stylelint-config-wikimedia to 0.2.0 and make pass (James D. Forrester)
+* build: Use stylelint instead of csslint (Volker E)
+* docs: Add some missing @mixins documentation (Bartosz Dziewoński)
+* stylelint: Add `@` whitespace and name case rules (Volker E)
+* stylelint: Add `@media` whitespace rules (Volker E)
+* stylelint: Add block formatting rules (Volker E)
+* stylelint: Add font rules (Volker E)
+* stylelint: Add no duplicate property rule (Volker E)
+* stylelint: Add selector whitespace (Volker E)
+* stylelint: Add whitespace rules (Volker E)
+* stylelint: Change to use central Wikimedia configuration (Volker E)
+* stylelint: Use null instead of false to disable rules (Ed Sanders)
+
+
+## v0.17.2 / 2016-05-10
+### Features
+* ButtonWidget: Implement, document and demonstrate the 'active' config option (Bartosz Dziewoński)
+
+### Styles
+* ToggleSwitchWidget: Align focus state with other widgets (Volker E)
+* MediaWiki theme: Remove `border-radius` from disabled numberInputWidget buttons (Volker E)
+
+### Code
+* TextInputWidget: Remove proprietary `<input results>` attribute styles (Volker E)
+* MediaWiki theme: Align `input` & `textarea` coding style to Less way (Volker E)
+
+
+## v0.17.1 / 2016-05-03
+### Styles
+* CapsuleMultiSelectWidget: Fix cross-browser inconsistencies and improve UX (Volker E)
+* SelectFileWidget: Add `no-drop` cursor where it belongs (Volker E)
+* MediaWiki theme: Align focus state of capsuleItemWidget with other widgets (Volker E)
+* MediaWiki theme: Custom `:focus` state for SelectWidgets (Bartosz Dziewoński)
+* MediaWiki theme: Standardize `:focus` states of ButtonWidgets (Volker E)
+
+### Code
+* DraggableGroupElement: Simplify and improve drag logic (Ed Sanders)
+
+
+## v0.17.0 / 2016-04-26
+### Breaking changes
+* [BREAKING CHANGE] PHP: Use traits instead of custom mixin system (Kunal Mehta)
+* [BREAKING CHANGE] TitledElement.php: Remove $element::$title fallback (Kunal Mehta)
+
+### Styles
+* MenuToolGroup: Correct display of checkmarks (Bartosz Dziewoński)
+* OutlineOptionWidget: Correct the size of the icons (David Lynch)
+* OutlineOptionWidget: Don't apply italics to "placeholder" status (James D. Forrester)
+* SelectFileWidget: Fix UI glitches on over-long filenames (Volker E)
+* TabOptionWidget: Disabled OptionWidget should receive default cursor (Volker E)
+* styles: Add fullScreen icon to media group (Ed Sanders)
+
+### Code
+* ButtonElement.php: Fix toggleFramed() to actually be chainable (Bartosz Dziewoński)
+* GroupElement::$targetPropertyName: Remove, no longer needed (Kunal Mehta)
+* IconElement.php: Rename protected "icon" property (Kunal Mehta)
+* IndicatorElement.php: Rename protected "indicator" property (Kunal Mehta)
+* LabelElement.php: Rename protected "label" property (Kunal Mehta)
+* build: Update grunt-svg2png to v0.2.7-wmf.1 (Paladox)
+* demos: Split off demos.php from widgets.php (Bartosz Dziewoński)
+* docparser: Remove commented-out line of code (Bartosz Dziewoński)
+* styles: Factor out `max-width-input-default` variable (Volker E)
+
+
+## v0.16.6 / 2016-04-19
+### Features
+* ButtonOptionWidget: Inherit OptionWidget, not DecoratedOptionWidget (Bartosz Dziewoński)
+* ClippableElement: Gracefully handle failure to call clip() after natural height change (Roan Kattouw)
+* NumberInputWidget: Disable onWheel action unless the widget has focus (Bartosz Dziewoński)
+* NumberInputWidget: Disable onWheel action when the widget is disabled (Prateek Saxena)
+* NumberInputWidget: Use input type="number" (Prateek Saxena)
+* TextInputWidget: Allow type="number" (Prateek Saxena)
+* TextInputWidget: Set step to 'any' if the type is set to 'number' (Prateek Saxena)
+* styles: Give icons, indicators `min-width/-height` for cross-browser support (Volker E)
+
+### Styles
+* Apex, MediaWiki themes: Properly center PopupButtonWidget anchors (Roan Kattouw)
+* MediaWiki theme: Use disabled color variable for disabled label (Volker E)
+* styles: Use transparent rather than white in icons (Bartosz Dziewoński)
+
+### Code
+* SelectFileWidget: Merge identical CSS rules (Volker E)
+* SelectFileWidget: Simplify CSS selector specificity (Volker E)
+* TextInputWidget: Clarify comment about affected browsers (Volker E)
+* TextInputWidget: Consolidate selectors with the same property rules (Volker E)
+* TextInputWidget: Stop claiming to fire non existent events in the documentation (Prateek Saxena)
+* styles: Centralise the width/height properties of icons and indicators (Volker E)
+* Apex theme: Change variable names to match MediaWiki theme (Bartosz Dziewoński)
+* README: Update with new build process (Matthew Flaschen)
+* typo: texfield -> textfield (Derk-Jan Hartman)
+
+
+## v0.16.5 / 2016-04-07
+### Styles
+* Prevent modal windows from exceeding available height on Firefox (Bartosz Dziewoński)
+* Apex, MediaWiki themes: Add "articles" icon (Marc A. Pelletier)
+* DropdownInputWidget: Give un-infused widget cursor:pointer (Ed Sanders)
+* RadioSelectInputWidget: Match PHP styling to JS (Bartosz Dziewoński)
+
+### Code
+* ComboBoxInputWidget: Disable autocomplete by default (James D. Forrester)
+* GroupElement: Add change event (Prateek Saxena)
+* GroupElement.php: Use strict mode in array_search (James D. Forrester)
+* styles: Lower specifity of CSS type attribute selectors (Volker E)
+* styles: Minor cleanup and unification of values and comments (Volker E)
+* styles: Remove unnecessary `resize` property from `select` (Volker E)
+* MediaWiki theme: Exchange `rgba()` with hex CSS colors to support IE 8 (Volker E)
+* MediaWiki theme: Replace fixed CSS property values with variables (Volker E)
+* RadioSelectInputWidget: Don't try to reuse DOM when infusing (Bartosz Dziewoński)
+* TextInputWidget: Use getValidity in demos (Ricordisamoa)
+* Window: Correct documentation (Bartosz Dziewoński)
+* build: Add browserNoActivityTimeout to karma (Paladox)
+* build: For grunt-svg2png use a tag instead of git hash (Paladox)
+* build: Update demos script to also run grunt publish-build (Paladox)
+* build: Use a version of grunt-svg2png without a rate-limited CDN (Paladox)
+
+
+## v0.16.4 / 2016-03-22
+### Features
+* NumberInputWidget: Optionally don't show the increment buttons (Thalia Chan)
+
+### Styles
+* NumberInputWidget: Fix rounded corners when showButtons=false (Ed Sanders)
+
+### Code
+* core: Add tests for throttle (David Lynch)
+* Tag: Allow appendContent and prependContent to accept an array (Moriel Schottlender)
+* LabelElement: Cast label to string before check if it is empty (Florian)
+* README.md: Add note about needing composer, clean up more generally (James D. Forrester)
+* build: Bump grunt-karma to 0.12.2 (Paladox)
+* build: Drop the 'npm prepublish' task which runs pre-install as well (James D. Forrester)
+* demos: Restore constructive widgets (James D. Forrester)
+* rubocop: Re-run todos, upgrade to newer rule names (James D. Forrester)
+* rubocop: Review todos (Bartosz Dziewoński)
+
+
+## v0.16.3 / 2016-03-16
+### Features
+* core: Add `#throttle` to complement `#debounce` (David Lynch)
+* ClippableElement: Never exceed the dimensions of the browser viewport (Bartosz Dziewoński)
+* FloatableElement: Hide if the anchor element is outside viewport (Bartosz Dziewoński)
+
+### Styles
+* Apex, MediaWiki themes: Fix vertical alignment of close icon (Ed Sanders)
+* MediaWiki theme: Disabled ButtonElement icon should not be colored (Bartosz Dziewoński)
+
+### Code
+* ButtonInputWidget: Actually disallow non-plaintext labels in 'useInputTag' mode (Bartosz Dziewoński)
+* Element: Preserve `OOUI\HtmlSnippet( '' )` when infusing (Bartosz Dziewoński)
+* InputWidget: Actually reuse parts of the DOM when infusing (Bartosz Dziewoński)
+* MediaWiki theme: Remove broken remnant of d6b05bc0 (Bartosz Dziewoński)
+* TextInputWidget: Treat empty placeholder the same in PHP and JS (Bartosz Dziewoński)
+* TitledElement: Treat empty title the same in PHP and JS (Bartosz Dziewoński)
+* build: Bump devDependencies to latest (James D. Forrester)
+* build: Bump devDependencies to latest (Paladox)
+* build: Update grunt-svg2png to commit 2fe1dad07eaec4b655263f8b487a672df4b668b4 (Paladox)
+* demo: Expand the dialog $overlay demo for testing scrolling things off-screen (Bartosz Dziewoński)
+* tests: Emulated setTimeout for unit testing (David Chan)
+* testsuitegenerator: Always test empty values for 'string' type, not just for 'label' (Bartosz Dziewoński)
+* testsuitegenerator: Change values tested for 'flags' config options (Bartosz Dziewoński)
+* testsuitegenerator: Test 'HtmlSnippet' type (mostly for labels) (Bartosz Dziewoński)
+
+
+## v0.16.2 / 2016-03-08
+### Deprecations
+* [DEPRECATING CHANGE] MediaWiki theme: Scrap `constructive` flag (Volker E)
+* [DEPRECATING CHANGE] Move some editing icons from core to editing-* (James D. Forrester)
+
+### Features
+* Dialog: trigger the primary action with ctrl-enter (David Lynch)
+* TextInputWidget: Allow type="date" (Geoffrey Mon)
+
+### Styles
+* Apex, MediaWiki themes: Add markup '<>' icon in editing-advanced (Ed Sanders)
+* Apex, MediaWiki themes: Drop padding from buttons in MessageDialogs (James D. Forrester)
+* editing-styling pack: Have uk fallback to use ru bold and italic icons (Paladox)
+* styles: Remove superflous pseudo-class and unitize comments (Volker E)
+
+### Code
+* CapsuleMultiSelectWidget: Emit 'resize' when widget height changes (Bartosz Dziewoński)
+* TextInputWidget: Prevent uncaught errors when using #selectRange in IE (Ed Sanders)
+* TextInputWidget: Update comment about Blink height miscalculation (Bartosz Dziewoński)
+* Follow-up I0667fbc: Fix draggable element CSS (Ed Sanders)
+* Add Element::configFromHtmlAttributes() helper method (Bartosz Dziewoński)
+* Clean-up duplicate properties across widgets (Volker E)
+* docs: Clarify the lack of `.oo-ui-box-shadow()` mixin (Volker E)
+
+
+## v0.16.1 / 2016-03-01
+### Styles
+* CapsuleItemWidget: Revert regression on "remove" button in Firefox (Volker E)
+
+### Code
+* ActionFieldLayout: Add max-width: 50em; (Florian)
+* DraggableGroupElement: Don't emit reorder event when action is a no-op (Ed Sanders)
+* Element: Fix #gatherPreInfuseState called incorrectly, causing TypeErrors (Thiemo Mättig)
+* NumberInputWidget: fix example (Ricordisamoa)
+* SelectWidget: fix incorrect `@return` that should be `@param` (Ricordisamoa)
+* build: Compress PNGs with Zopfli etc. after they are built (James D. Forrester)
+* build: Enable all passing jscs jsDoc rules (Ricordisamoa)
+* build: Enable jscs jsDoc rule 'checkAnnotations' and make pass (Ricordisamoa)
+* build: Enable jscs jsDoc rule 'checkParamNames' and make pass (Ricordisamoa)
+* build: Enable jscs jsDoc rule 'checkTypes' and make pass (Ricordisamoa)
+* build: Enable jscs jsDoc rule 'requireNewlineAfterDescription' and make pass (Ricordisamoa)
+* build: Enable jscs jsDoc rule 'requireReturnTypes' and make pass (Ricordisamoa)
+* demos: Display a nicer error message on old PHP versions (Kunal Mehta)
+
+
+## v0.16.0 / 2016-02-22
+### Breaking changes
+* [BREAKING CHANGE] DraggableGroupElement: Add default implementation of reorder (Ed Sanders)
+* [BREAKING CHANGE] Remove 'noimages' distribution (Bartosz Dziewoński)
+* [BREAKING CHANGE] Require PHP 5.5.9+; drop old array syntax (James D. Forrester)
+* [BREAKING CHANGE] SelectFileWidget: Remove deprecated config 'dragDropUI' (Prateek Saxena)
+
+### Deprecations
+* [DEPRECATING CHANGE] MenuOptionsWidgets: Drop jQuery autoEllipsis support (Bartosz Dziewoński)
+
+### Features
+* core#debounce: If an immediate timeout is already waiting, don't re-set it (Bartosz Dziewoński)
+* LabelElement: Bring in highlightQuery method from VE (Ed Sanders)
+* DraggableElement: Defer adding of -dragging class so it isn't applied to copy (Ed Sanders)
+* DraggableElement: Introduce $handle config option (Ed Sanders)
+* DraggableGroupElement: Live reorder list while dragging (Ed Sanders)
+* DraggableGroupElement: Only show meaningful drop positions (Ed Sanders)
+
+### Styles
+* CapsuleItemWidget: Tweak styles for the "remove" button (Bartosz Dziewoński)
+* MenuSelectWidget: Bring some sanity styling when inside different widgets (Bartosz Dziewoński)
+* NumberInputWidget: Apex: Round the correct corners in the disabled state (Prateek Saxena)
+* styles: Use block rather than inline-block to avoid line height issues (Bartosz Dziewoński)
+* MediaWiki theme: Restore non-broken version of eye.svg (Bartosz Dziewoński)
+
+### Code
+* Avoid parsing HTML when creating <input> nodes (Bartosz Dziewoński)
+* tests: Actually run core test suite in standalone mode (Bartosz Dziewoński)
+* Compress PNGs with zopflipng (Ori Livneh)
+* DraggableGroupElement: Cache directionality (Ed Sanders)
+* DraggableGroupElement: Fix offset calculation (Ed Sanders)
+* DraggableGroupElement: Reduce flicker when dragging (Ed Sanders)
+* TextInputWidget: Don't call #updatePosition if there's no label to position (Bartosz Dziewoński)
+* PHP: Take advantage of PHP 5.5 understanding ( new Foo )->foo (Bartosz Dziewoński)
+* README: Update Phabricator URL broken by upgrade (James D. Forrester)
+* build: Bump grunt-svg2png to a newer (still personal) version; lots faster (James D. Forrester)
+
+## v0.15.4 / 2016-02-16
+### Deprecations
+* [DEPRECATING CHANGE] Element#scrollIntoView: Replace callback with promise (Ed Sanders)
+
+### Features
+* SelectWidget: Prevent mouse highlighting while typing-to-select (Bartosz Dziewoński)
+
+### Styles
+* PHP DropdownInputWidget: Match height of <option> to JS MenuOptionWidget (Bartosz Dziewoński)
+
+### Code
+* DraggableElement: Remove 'HACK' comment, this isn't a hack (Bartosz Dziewoński)
+* Element: Expand variable names in scrollIntoView (Ed Sanders)
+* Element, ListToolGroup: Add some missing documentation (Ed Sanders)
+* Element#scrollIntoView: Make the promise version actually work (Bartosz Dziewoński)
+* PopupWidget: Only build head and footer if we're going to use it (Bartosz Dziewoński)
+* PopupWidget: Tweak some comments (Bartosz Dziewoński)
+* styles: Remove initial value `ease` from `transition` (Volker E)
+
+## v0.15.3 / 2016-02-09
+### Features
+* CapsuleItemWidget: Let user tab through items, edit and delete them (Prateek Saxena)
+* CapsuleMultiSelectWidget: Edit instead of remove on backspace (Prateek Saxena)
+* CapsuleWidgets: Edit on click and remove on Ctrl+Backspace (Prateek Saxena)
+* CapsuleWidgets: Toggle through capsules and the input with arrow keys (Prateek Saxena)
+* DropdownWidget: Open menu on up and down arrow keys (Prateek Saxena)
+* MenuSelectWidget: Ensure currently selected element is visible when menu opens (Bartosz Dziewoński)
+* SelectFileWidget: Show thumbnail when dropTarget is shown (Prateek Saxena)
+* Really preserve dynamic state of widgets when infusing (Bartosz Dziewoński)
+
+### Styles
+* MediaWiki, Apex themes: Replace 'language' icon with tweaked version (Mun May Tee)
+
+### Code
+* CapsuleItemWidget: Use Button instead of an Indicator (Prateek Saxena)
+* CapsuleMultiSelectWidget: Extend config instead of when setting property (Prateek Saxena)
+* InputWidget: Remove the 'setAccessKey' method (Prateek Saxena)
+* SelectWidget: Really prevent default action during type-to-select (Bartosz Dziewoński)
+* Put '@keyframes' rules inside a mixin to avoid duplicating them (Bartosz Dziewoński)
+* Apex theme: Remove unnecessary '@keyframes' prefixing (Bartosz Dziewoński)
+* Mediawiki theme: Align button mixins/states to CSS guidelines/standard (Volker E)
+* Correct code using plain DOM events documented as jQuery events (Bartosz Dziewoński)
+* demo: Add a long DropdownInputWidget demo (Bartosz Dziewoński)
+* demo: In PHP demo, load oojs-ui-core only instead of whole oojs-ui (Bartosz Dziewoński)
+* demo: Measure time needed to construct the demo (Bartosz Dziewoński)
+* demo: widgets: OO.ui.CapsuleMultiSelectWidget: Remove non-existent 'values' config (Prateek Saxena)
+* docparser: Recognize and ignore '@uses' (Bartosz Dziewoński)
+* docs: OO.ui.CapsuleMultiSelectWidget: Config options (Prateek Saxena)
+* docs: OO.ui.CapsuleMultiSelectWidget: Link to the widget it uses (Prateek Saxena)
+* docs: OO.ui.SelectFileWidget: Minor language change (Prateek Saxena)
+
+
+## v0.15.2 / 2016-02-02
+### Features
+* DropdownWidget: Prevent label from overflowing the handle (Bartosz Dziewoński)
+
+### Styles
+* Ensure gradient filter rendering on IE 8&9 (Bartosz Dziewoński)
+* Remove unused CSS classes .oo-ui-ltr and .oo-ui-rtl (Bartosz Dziewoński)
+* Update `.oo-ui-vertical-gradient` mixin to modern times (Volker E)
+
+### Code
+* Unify SVG icon color values to CSS/Less coding standards (Volker E)
+* ComboBoxInputWidget: Don't make the 'datalist' infusable (Bartosz Dziewoński)
+* Move OO.ui.alert and OO.ui.confirm methods to separate file (Bartosz Dziewoński)
+* README: Add "Loading the library" wherein we apologise for the mess that is the dist/ directory (Bartosz Dziewoński)
+* build: Actually check that all required files are not missing (Bartosz Dziewoński)
+* build: Add intro.js.txt and outro.js.txt to all distribution JS files (Bartosz Dziewoński)
+* build: De-duplicate per-theme modules lists (Bartosz Dziewoński)
+* build: Only define one 'less' task, not one per-distribution (Bartosz Dziewoński)
+* build: Remove unused 'ieCompat' options from 'less' (Bartosz Dziewoński)
+* build: Remove unused 'report' options from 'less' (Bartosz Dziewoński)
+* build: Small modules.yaml tweaks (Bartosz Dziewoński)
+* build: Split the library into four parts (Bartosz Dziewoński)
+* build: Switch modules.json to YAML to document some of the weird stuff we've put in there (Bartosz Dziewoński)
+* build: Unbreak `grunt build --graphics=vector` (Bartosz Dziewoński)
+* build: Update phpunit/phpunit to 4.8 (Paladox)
+* docparser: Parse '@class Foo' annotations, not just '@class' (Bartosz Dziewoński)
+
+
+## v0.15.1 / 2016-01-26
+### Features
+* Really filter out unsafe URLs, but don't throw silly exceptions (Bartosz Dziewoński)
+* ClippableElement: Try to prevent unnecessary scrollbars (Bartosz Dziewoński)
+* Dialog: Don't set `overflow:hidden;` on `.oo-ui-window-body` elements (Alex Monk)
+* TextInputWidget: Don't fail if 'validate' function returns null (Bartosz Dziewoński)
+
+### Styles
+* WindowManager: Only apply `top: 1em; bottom: 1em;` to non-fullscreen windows (Bartosz Dziewoński)
+* Align mixin whitespace to CSS/Less coding guidelines (Volker E)
+* Enable `cursor: pointer` just on enabled widgets (Volker E)
+* Apex, MediaWiki themes: Fix size of templateAdd icon (Ed Sanders)
+* Apex, MediaWiki themes: Quotes icon fixes (Ed Sanders)
+* Apex, MediaWiki themes: Re-crush SVGs, removing useless ID values and empty groups (James D. Forrester)
+* Apex theme: Fix FieldLayout padding in inline mode (Ed Sanders)
+* Apex theme: NumberInputWidget: Fix width of +/- buttons (Ed Sanders)
+* MediaWiki theme: Add invert variant to 'accessibility' icon pack icons (Bartosz Dziewoński)
+* MediaWiki theme: Align `@input-*` vars to coding guidelines (Volker E)
+* MediaWiki theme: Align `rgba()` values to CSS/Less guidelines (Volker E)
+* MediaWiki theme: Align size variables to CSS/Less guidelines (Volker E)
+* MediaWiki theme: Consolidate emphasized color values into variable (Volker E)
+* MediaWiki theme: Establish new `@border-default` variable (Volker E)
+* MediaWiki theme: Make icon variants actually work for all icons (Bartosz Dziewoński)
+* MediaWiki theme: Make transition of text input fields smoother (Volker E)
+* MediaWiki theme: Merge `@oo-ui-toolbar-bar-text` & `@color-default` vars (Volker E)
+* MediaWiki theme: Replace fixed & consolidate disabled values with vars (Volker E)
+* MediaWiki theme: Update avatar icon (Pau Giner)
+
+### Code
+* NumberInputWidget: Replace `box-sizing` property with mixin as anywhere else (Volker E)
+* SelectFileWidget: Order name and type spans in the order they are shown (Prateek Saxena)
+* TextInputWidget: Simplify `#getValidity` (Bartosz Dziewoński)
+* README: Add a 'Contributing' section (James D. Forrester)
+* build: Don't generate .min.js and .min.css files by default (Bartosz Dziewoński)
+* build: Only build one graphics distribution (mixed/vector/raster), not all (Bartosz Dziewoński)
+* build: Update jakub-onderka/php-parallel-lint to 0.9.2 (Paladox)
+* build: Update mediawiki/mediawiki-codesniffer to 0.5.1 (Paladox)
+* demo: Extend compounded form in widget.js demo (Volker E)
+
+## v0.15.0 / 2016-01-12
+### Breaking changes
+* [BREAKING CHANGE] Drop Internet Explorer 8 support from JavaScript code (Ricordisamoa)
+* [BREAKING CHANGE] Delete deprecated aliases 'picture' and 'insert' (Ed Sanders)
+
+### Deprecations
+* [DEPRECATING CHANGE] Create single icon for language/translation (Ed Sanders)
+* [DEPRECATING CHANGE] Move 'redirect' icon to 'articleRedirect' and cleanup (Ed Sanders)
+* [DEPRECATING CHANGE] core: Deprecate add/removeCaptureEventListener (Bartosz Dziewoński)
+
+### Features
+* Send escape key cancel events through action handler (Alex Monk)
+
+### Styles
+* MediaWiki theme: Align variable values & properties to CSS/Less guidelines (Volker E)
+* MediaWiki theme: Align `@neutral-button-border` to CSS/Less guidelines (Volker E)
+* MediaWiki theme: Align `transition` variables with coding guidelines (Volker E)
+* MediaWiki theme: Change color value to Less variable (Volker E)
+* MediaWiki theme: Clarify `@active` variable by renaming it (Volker E)
+* MediaWiki theme: Clarify `@background` var by renaming it (Volker E)
+* MediaWiki theme: Clarify `@select` variable by renaming it (Volker E)
+* MediaWiki theme: Clarify `@text` variable by renaming it (Volker E)
+* MediaWiki theme: Consolidate stray `margin` and `padding` properties (Volker E)
+* MediaWiki theme: Remove unnecessary `@-ms-keyframes` vendor rule (Volker E)
+* MediaWiki theme: Replace fixed `invalid` color value with variable (Volker E)
+* MediaWiki theme: Unify `border` property values (Volker E)
+* MediaWiki theme: Unify `border-radius` values (Volker E)
+* MediaWiki theme: Unify `-disabled` variables usage (Volker E)
+
+### Code
+* core: Add constants for MouseEvent.which button codes (Ed Sanders)
+* demo: Remove IE 8 support (Bartosz Dziewoński)
+* build: Fix typos ("overridden") (Ed Sanders)
+* build: Bump file copyright notices for 2016 (James D. Forrester)
+* build: Update most devDependencies to latest (James D. Forrester)
+* build: Updating development dependencies (Kunal Mehta)
+
+## v0.14.1 / 2015-12-08
+
+### Features
+* Implement OO.ui.alert() and OO.ui.confirm() (Bartosz Dziewoński)
+
+### Styles
+* CapsuleMultiSelectWidget: Interface tweaks (Bartosz Dziewoński)
+* CapsuleMultiSelectWidget: Make the text field span all available area (Bartosz Dziewoński)
+* CapsuleMultiSelectWidget: Update menu position when typing (Bartosz Dziewoński)
+* HorizontalLayout: Synchronise behaviour between themes (Bartosz Dziewoński)
+* Apex theme: Enlarge 'search' icon (Bartosz Dziewoński)
+* MediaWiki theme: Correct text color in MessageDialog, TabOptionWidget (Volker E)
+
+### Code
+* Tool*: Consolidate and cross-link some documentation (Bartosz Dziewoński)
+* Tool*: Expand, correct docs for #onUpdateState and the related event (Bartosz Dziewoński)
+* core.js: Extract a large chunk of the file incorrectly in a closure (Bartosz Dziewoński)
+* Apex, MediaWiki themes: Standardize XML structure for various 'search' images (Bartosz Dziewoński)
+* MediaWiki theme: Add missing theme mixin placeholder (no-op) (Bartosz Dziewoński)
+* build: Test PHP documentation with Doxygen via composer and make pass (James D. Forrester)
+* demo: Quit using the 'image' icon in documentation examples (Bartosz Dziewoński)
+
+## v0.14.0 / 2015-11-24
+### Breaking changes
+* [BREAKING CHANGE] Depend on OOjs v1.1.10, up from v1.1.9 (James D. Forrester)
+* [BREAKING CHANGE] TextInputWidget: Remove old deprecated alias #setPosition (Ed Sanders)
+
+### Deprecations
+* [DEPRECATING CHANGE] De-duplicate 'trash' and 'remove' icons (James D. Forrester)
+
+### Features
+* TextInputWidget: Add insertContent method (Thalia Chan)
+* TextInputWidget: Add encapsulateContent method to insert new content around a selection (Thalia Chan)
+
+### Styles
+* Apex theme: Provide the 'interactions' icon pack (James D. Forrester)
+* MediaWiki theme: Make dialog and panel box-shadows outset rather than inset (Ed Sanders)
+
+### Code
+* FlaggedElement.php: Fix type hint (Reedy)
+* SelectFileWidget: Remove sometimes-incorrect 'title' on the <input> (Bartosz Dziewoński)
+* SelectFileWidget: Use i18n string for button label (Ed Sanders)
+* TextInputWidget: Fix documentation of insertContent method (Thalia Chan)
+* \*.php: Replace `@chainable` jsduck-ism with `@return` $this (Reedy)
+* .gitattributes: Ignore both `/doc` and `/docs` directories (James D. Forrester)
+* AUTHORS: Update for the past few months' work (James D. Forrester)
+* build: Added Rakefile (Željko Filipin)
+
+## v0.13.3 / 2015-11-17
+### Deprecations
+* [DEPRECATING CHANGE] Duplicate icons: Unify 'picture' and 'image' (Ed Sanders)
+
+### Features
+* RequestManager: Introduce a mixin for widgets that need to do API calls (David Lynch)
+* TextInputWidget: Add getRange method (Ed Sanders)
+* WindowManager: Allow getSetup/ReadyProcess to reject (Ed Sanders)
+* WindowManager: Fade in overlay after 'setup' not 'ready' (Ed Sanders)
+
+### Styles
+* MediaWiki, Apex themes: Remove small 0.1em vertical margin from buttons (Bartosz Dziewoński)
+* MediaWiki theme: Add destructive variant to the 'cancel' icon (James D. Forrester)
+* MediaWiki theme: Reduce whitespace between FieldLayouts (Bartosz Dziewoński)
+
+### Code
+* TitledElement: Behave like its docs say it should (David Lynch)
+* Use null for abstract methods and correct documentation (Ed Sanders)
+* demo: Make button style showcase a table (Bartosz Dziewoński)
+
+## v0.13.2 / 2015-11-10
+### Deprecations
+* [DEPRECATING CHANGE] ComboBoxWidget: Refactor into ComboBoxInputWidget (Bartosz Dziewoński)
+* [DEPRECATING CHANGE] MediaWiki, Apex themes: Unify add/insert icons (Ed Sanders)
+
+### Features
+* ComboBoxInputWidget: Implement PHP version (Bartosz Dziewoński)
+* LookupElement: Make auto-highlighting the first term configurable (Florian)
+
+### Styles
+* Add some missing white backgrounds and use variables when possible (Bartosz Dziewoński)
+* MediaWiki theme: Make the menu icon identical to Apex's (Ed Sanders)
+* MediaWiki theme: Specify 'line-height' for DropdownWidget's handle (Bartosz Dziewoński)
+* WikiText icon: Make slightly narrower (Ed Sanders)
+
+### Code
+* Apex theme: Remove dead styles for ComboBoxWidget (Bartosz Dziewoński)
+* build: Make copy:fastcomposerdemos work again (Bartosz Dziewoński)
+
+## v0.13.1 / 2015-11-03
+### Deprecations
+* [DEPRECATING CHANGE] InputWidget: Replace `#setRTL` with `#setDir` (Ed Sanders)
+
+### Features
+* Allow widgets to re-use parts of the DOM when infusing; use for InputWidget's `$input` (Bartosz Dziewoński)
+* FieldLayout: Allow setting errors and notices dynamically (Bartosz Dziewoński)
+* InputWidget: Add '`dir`' to config (Ed Sanders)
+
+### Styles
+* TextInputWidget: Account for scroll bar width when positioning indicators/labels (Ed Sanders)
+* TextInputWidget: Ensure icon+indicator+label are top aligned in multi-line mode (Ed Sanders)
+
+### Code
+* FieldLayout: Mark `#makeMessage` as `@protected` (Bartosz Dziewoński)
+* History.md: wrap `<select>` tag in backticks (Ricordisamoa)
+* tests: Refactor property->attribute copying (Ed Sanders)
+
+## v0.13.0 / 2015-10-27
+### Breaking changes
+* [BREAKING CHANGE] Remove aliases for OO.ui.mixins, deprecated in 0.11.4 (C. Scott Ananian)
+* [BREAKING CHANGE] Turn Element#gatherPreInfuseState into a static method (Bartosz Dziewoński)
+
+### Features
+* Update outline widget when current item is scrolled out of view (Ed Sanders)
+* TextInputWidget: Emit 'resize' events (Ed Sanders)
+* TextInputWidget: Fix scrollbars in `<textarea>`s in IE8-11 (Ed Sanders)
+* TextInputWidget: Improve selection API (Ed Sanders)
+
+### Styles
+* MediaWiki theme: Adjust ToggleSwitchWidget to match M61 design (Volker E)
+* Follow-up I54f1e3c92: Fix placement of cursors on checkbox/radio widgets (Volker E)
+* Follow-up I598e7b25a: Apply MenuToolGroup missing styles fix to Apex theme (Ed Sanders)
+
+### Code
+* Consistently use '`//`' rather than '`/* */`' for Less comments (Bartosz Dziewoński)
+* Remove obsolete Opera<12.1 vendor prefixes (Volker E)
+* Remove unnecessary IE10beta vendor-prefixes from OOjs UI (Volker E)
+* build: Switch back to upstream version of grunt-contrib-concat (Timo Tijhof)
+* build: Updating development dependencies (Kunal Mehta)
+* build: Use my Gmail address for attribution (Timo Tijhof)
+
+## v0.12.12 / 2015-10-13
+### Features
+* CapsuleMultiSelectWidget: When 'allowArbitrary' is true, don't require 'Enter' to confirm (Bartosz Dziewoński)
+* SelectFileWidget: Add a focus method (Ed Sanders)
+
+### Styles
+* CapsuleMultiSelectWidget: Set 'background-color' rather than 'background' (Bartosz Dziewoński)
+* DropdownWidget: Fix vertical alignment of handle's text (Volker E)
+* MediaWiki theme: Get transitions on ButtonWidget's `:hover` states in sync (Volker E)
+* MediaWiki theme: Unbreak checkbox/radio 'cursor: pointer' (Bartosz Dziewoński)
+* MediaWiki theme: Use inverted icon for 'active' buttons (Ed Sanders)
+
+### Code
+* ButtonElement: Actually use 'active' property and add getter (Ed Sanders)
+* Element: Document $element config option (Thalia)
+* composer.json: Add author names & e-mails (Alangi Derick)
+* demo: Correct some typos (Bartosz Dziewoński)
+
+## v0.12.11 / 2015-10-06
+### Styles
+* MediaWiki theme: Make shadows translucent black instead of light grey (Ed Sanders)
+* MediaWiki theme: Make PHP DropdownInputWidget look closer to JS version (Bartosz Dziewoński)
+
+### Code
+* Follow-up I4acbe69420: BookletLayout: Fix focus of page switching (Ed Sanders)
+* IndexLayout: Fix focus of panel switching (Ed Sanders)
+* TextInputWidget: Remove 'autocomplete' attribute on page navigation (Bartosz Dziewoński)
+* build: Bump es5-shim and various devDependencies to master (James D. Forrester)
+
+## v0.12.10 / 2015-09-29
+### Styles
+* Fix icon/indicator padding on TextInputWidget/SelectFileWidget (Ed Sanders)
+
+### Code
+* CapsuleItemWidget: Remove 'click' event preventing (Bartosz Dziewoński)
+* FloatableElement: Don't try unbinding events before we bind them (Bartosz Dziewoński)
+* SelectWidget: Ensure 'choose' never emits null (Ed Sanders)
+* Remove old textInputWidget-decorated classes (Ed Sanders)
+* build: Upgrade MediaWiki-Codesniffer to 0.4.0 (Kunal Mehta)
+
+## v0.12.9 / 2015-09-22
+### Features
+* BookletLayout, IndexLayout: Make autoFocus and focussing more reliable (Bartosz Dziewoński)
+* CapsuleMultiSelectWidget: Allow using CapsuleItemWidget subclasses (Bartosz Dziewoński)
+* CardLayout: Add a 'label' config option (Ed Sanders)
+* FloatableElement: Introduce mixin (Bartosz Dziewoński)
+* FloatingMenuSelectWidget: Update position of menus within overlay while scrolling (Bartosz Dziewoński)
+* IndexLayout: Add 'expanded' option, passed through to StackLayout (Ed Sanders)
+* MenuLayout: Use child selectors to allow nesting menus (Ed Sanders)
+* Re-attempt I31ab2bace4: Try to stop user from tabbing outside of open dialog box (Ed Sanders)
+
+### Styles
+* SelectFileWidget: Move file type over to the right in secondary text colour (Ed Sanders)
+* Fix focus styles on disabled widgets (Volker E)
+* Apex, MediaWiki themes: Make most borders on table icon thinner (Ed Sanders)
+* Apex, MediaWiki themes: Make picture icon border thinner (Ed Sanders)
+* MediaWiki theme: Alter buttons' padding and position icons absolutely (nirzar)
+* MediaWiki theme: Fix height of IndexLayout tab widget (Ed Sanders)
+* MediaWiki theme: Unify box-shadows for PopupWidget and DropdownWidget (Volker E)
+
+### Code
+* #isFocusableElement: Rewrite for performance and correctness (Ed Sanders)
+* BookletLayout: Remove unnecessary JSHint override (Bartosz Dziewoński)
+* DropdownWidget: Update example doc to show #getMenu usage (Ed Sanders)
+* Follow-up bf1497be: Fix PopupToolGroup use of renamed Clippable property (Ed Sanders)
+* PopupWidget: Add missing `@mixins` doc entry (Bartosz Dziewoński)
+* SelectFileWidget: Fix DOM order of file type label (Ed Sanders)
+* Widget: Fix docs for disable event (Ed Sanders)
+* docs: Remove excess empty lines in comments (Bartosz Dziewoński)
+* docs: Add quotes around PROJECT_BRIEF setting (Timo Tijhof)
+
+## v0.12.8.1 / 2015-09-18 (special release)
+### Code
+* build: Update version requirement for mediawiki/at-ease: 1.0.0 → 1.1.0 (Ori Livneh)
+
+## v0.12.8 / 2015-09-08
+### Styles
+* SelectFileWidget: Overflow and ellipsis for label (Ed Sanders)
+* Apex theme: Move transition timing to common variables (Prateek Saxena)
+* MediaWiki theme: Move window transition to `@medium-ease` variable (Prateek Saxena)
+* MediaWiki theme: Add missing `width` and `height` attributes to icons (Ed Sanders)
+* Clean up CSS values in .oo-ui-transition calls (Timo Tijhof)
+* Use 'ease' instead of 'ease-in-out' for CSS transitions (Timo Tijhof)
+
+### Code
+* Toolbar: Prevent double initialization (Roan Kattouw)
+* build: Bump grunt-contrib-jshint from 0.11.2 to 0.11.3 to fix upstream issue (James D. Forrester)
+* build: Upgrade grunt-banana-checker to v0.3.0 (James D. Forrester)
+
+## v0.12.7 / 2015-09-01
+### Deprecations
+* [DEPRECATING CHANGE] SelectFileWidget: Re-design to use a clearly clickable button (Ed Sanders)
+
+### Styles
+* FieldLayout: Don't add `margin-bottom` when in a HorizontalLayout (Florian)
+* SelectFileWidget: Use gray for hover and `@progressive-fade` for drop active (Prateek Saxena)
+* Apex, MediaWiki themes: Fix scale of external link icon (Ed Sanders)
+* Apex, MediaWiki themes: Re-crush all SVG files with SVGO (James D. Forrester)
+* Apex, MediaWiki themes: Reduce size of 'close' icon by 1px (Ed Sanders)
+* Apex, MediaWiki themes: Remove Inkscape-ism from SVG files (James D. Forrester)
+* Apex, MediaWiki themes: Standardise XML prolog for SVG files (Bartosz Dziewoński)
+* MediaWiki theme: Fix viewBox of arrow indicators (Ed Sanders)
+* MediaWiki theme: Fix viewBox of several icons (James D. Forrester)
+
+### Code
+* LookupElement: Really disallow editing of `readOnly` TextInputWidgets (Bartosz Dziewoński)
+* SelectFileWidget: Fix drop and drop hover exception in Firefox (Ed Sanders)
+* SelectFileWidget: Improve type checking (Ed Sanders)
+
+## v0.12.6 / 2015-08-25
+### Features
+* AccessKeyedElement: Introduce (Florian)
+* ButtonOptionWidget: Mixin TitledElement (Bartosz Dziewoński)
+* ClippableElement: Allow $clippableContainer to be different from $clippable (Roan Kattouw)
+* Dialog: Listen for Escape key on $element, not document (Roan Kattouw)
+* InputWidget: Add TitledElement and AccessKeyedElement mixins (Florian)
+* PopupWidget: Make it possible to add static footers (Moriel Schottlender)
+* SelectFileWidget: Add drag drop UI as a config (Prateek Saxena)
+* TextInputWidget: Add moveCursorToEnd() (Roan Kattouw)
+
+### Styles
+* MenuToolGroup: Add some missing styles for tools' 'check' icons (Bartosz Dziewoński)
+* PopupWidget: don't apply header styles to footer (Roan Kattouw)
+* SelectFileWidget: Mute the drag and drop design (Ed Sanders)
+* Add colour to neutral state of MW frameless buttons (Ed Sanders)
+* Editing-advanced icon pack: Add 'calendar' (Bartosz Dziewoński)
+
+### Code
+* DropdownInputWidget: Allow users to pass config options to DropdownWidget (Alex Monk)
+* Theme: Add theme classes to $icon and $indicator only (Bartosz Dziewoński)
+* Use OO.ui.debounce() for Element#updateThemeClasses (Roan Kattouw)
+* Document browser-specific code with support comments (Timo Tijhof)
+* Update OOjs to v1.1.9 (James D. Forrester)
+* Fix file permissions (Southparkfan)
+* Fix inArray test in drag handler (Ed Sanders)
+* Prefer ES5 over jQuery methods (Bartosz Dziewoński)
+* build: Enable jscs rule 'requireSpacesInsideBrackets' and make pass (James D. Forrester)
+* build: Enable jscs rule 'requireVarDeclFirst' and make pass (James D. Forrester)
+* build: Make `quick-build` build the 'mixed' distribution (James D. Forrester)
+* build: Update jscs devDependency from 1.8.0 to 2.1.0 (James D. Forrester)
+* build: Update various devDependencies to latest (James D. Forrester)
+* core: Remove spurious "[description]" placeholder from documentation (Timo Tijhof)
+* demos, tests: Use es5-shim for IE8 compatibility (Bartosz Dziewoński)
+* phpcs.xml: Ignore JS demo files in the PHP distribution (James D. Forrester)
+* testsuitegenerator: Do not generate nonsensical tests for 'maxLength' (Bartosz Dziewoński)
+
+## v0.12.5 / 2015-08-18
+### Features
+* CapsuleMultiSelectWidget: Unbreak $overlay config option (Bartosz Dziewoński)
+* FloatingMenuSelectWidget: Introduce, based on TextInputMenuSelectWidget (Bartosz Dziewoński)
+* FieldLayout: Throw an error if no widget is provided (Prateek Saxena)
+* MessageDialog: Focus primary action button when the dialog opens (Prateek Saxena)
+
+### Styles
+* DropdownWidget: Remove additional vertical margin, for consistency (Bartosz Dziewoński)
+* FieldLayout: Correct rendering of multiline messages in MediaWiki theme (Bartosz Dziewoński)
+* Move base icon/indicator styles out of themes (Roan Kattouw)
+* MediaWiki theme: Correct styling of nested buttons (Bartosz Dziewoński)
+
+### Code
+* DropdownWidget: Add $overlay config option (Bartosz Dziewoński)
+* IconElement, IndicatorElement: Apply base styles to the right selector (Bartosz Dziewoński)
+* Add background-repeat: no-repeat; to default icon/indicator styles (Roan Kattouw)
+* Remove redundant background rules for icons/indicators (Roan Kattouw)
+* Revert "TextInputWidget: Update doc'ed requirements for validate function" (Prtksxna)
+* Don't directly use #addEventListener for compatibility with IE 8 (Bartosz Dziewoński)
+* demos: Add a demo of the $overlay config option of various widgets (Bartosz Dziewoński)
+
+## v0.12.4 / 2015-08-13
+### Styles
+* CapsuleMultiSelectWidget: Style tweaks (Ed Sanders)
+
+### Code
+* MenuSelectWidget: Call #updateItemVisibility in more cases (Bartosz Dziewoński)
+* PopupWidget: Remove 'focusout' handling again, limit to CapsuleMultiSelectWidget (Bartosz Dziewoński)
+
+## v0.12.3 / 2015-08-11
+### Deprecations
+* [DEPRECATING CHANGE] TextInputWidget: Add getValidity function, deprecate isValid (Prateek Saxena)
+
+### Features
+* Add OO.ui.isSafeUrl() to make sure url targets are safe client-side (Kunal Mehta)
+* CapsuleMultiSelectWidget: Introduce (Brad Jorsch)
+* FieldLayout: Allow displaying errors or notices next to fields (Bartosz Dziewoński)
+* HorizontalLayout: Introduce (Bartosz Dziewoński)
+* If ProcessDialog#fitLabel is called before dialog is open, defer (Ed Sanders)
+* Mixin TitledElement into DropdownInputWidget and FieldLayout (Florian)
+* Preserve dynamic state of widgets when infusing (Bartosz Dziewoński)
+* TextInputWidget: Don't forget to positionLabel() after it's been unset (Bartosz Dziewoński)
+
+### Styles
+* FieldLayout: Kill 'list-style-image' too for messages list (Bartosz Dziewoński)
+* PopupToolGroup: Handle popup position on very narrow screens (Ed Sanders)
+* ToggleSwitchWidget: Update according to spec (Prateek Saxena)
+* MediaWiki, Apex themes: Fix height of frameless toolbar button (Ed Sanders)
+* Apex theme: Correct disabled iconed button tool's text colour (Ed Sanders)
+* Revert "Dialog: Increase z-index of .oo-ui-dialog to 1000+" (Ed Sanders)
+
+### Code
+* ButtonOptionWidget: Make it more difficult to set an inappropriate 'tabIndex' (Bartosz Dziewoński)
+* TextInputWidget: Update doc'ed requirements for validate function (Prateek Saxena)
+* TextInputWidget: Use getValidity in setValidityFlag (Prateek Saxena)
+* Element: DWIM when repeatedly infusing the same node (Bartosz Dziewoński)
+* Element: Preserve 'classes' config option through infusion (Bartosz Dziewoński)
+* demo: Make compatible with IE 8 (Bartosz Dziewoński)
+* build: Exclude irrelevant files from Composer PHP package (Timo Tijhof)
+* build: Move phpcs config from composer.json to phpcs.xml (Timo Tijhof)
+* build: Output doxygen to "doc" for consistency with other PHP libraries (Kunal Mehta)
+* build: Switch svg2png to personal build which fixes long lines (James D. Forrester)
+* demos, tests: Use `.parent` instead of `.super` (Bartosz Dziewoński)
+* docparser: Add rudimentary error handling (Bartosz Dziewoński)
+* doxygen: Use default directory for HTML_OUTPUT (Kunal Mehta)
+* tests: Twist the time in comparison tests in a different manner (Bartosz Dziewoński)
+* testsuitegenerator: Output the number of generated test cases (Bartosz Dziewoński)
+
+## v0.12.2 / 2015-07-28
+
+### Styles
+* Dialog: Increase z-index of .oo-ui-dialog to 1000+ (Prateek Saxena)
+* MediaWiki theme: Create new 'accessibility' icon pack (Violetto)
+
+### Code
+* SelectWidget: Fix @mixins documentation (Roan Kattouw)
+* Update OOjs to v1.1.8 (James D. Forrester)
+
+## v0.12.1 / 2015-07-22
+
+### Features
+* PendingElement: Make this actually useful (Roan Kattouw)
+* TextInputWidget: Handle required: true better (Bartosz Dziewoński)
+* TextInputWidget: Handle type: 'search' better (Bartosz Dziewoński)
+
+### Styles
+* PanelLayout: Add some vertical margin when 'padded' and 'framed' (Bartosz Dziewoński)
+* MediaWiki, Apex themes: Add 'clear' indicator (Bartosz Dziewoński)
+* MediaWiki theme: Align colour of toolbar and dropdown buttons (Prateek Saxena)
+
+### Code
+* Window: Compute directionality only when needed (Roan Kattouw)
+* Standardise some common comments (Bartosz Dziewoński)
+* build: Add clean:demos task (Bartosz Dziewoński)
+* build: Add clean:tests task (Bartosz Dziewoński)
+* build: Have copyright header reference "OOjs UI" team (Kunal Mehta)
+* build: Use new grunt-tyops package rather than local original (James D. Forrester)
+* Gruntfile: Fix 'pgk' to 'pkg' and add to typos list (James D. Forrester)
+* package.json: Use proper SPDX license notation (Derk-Jan Hartman)
+
+## v0.12.0 / 2015-07-13
+### Breaking changes
+* [BREAKING CHANGE] SearchWidget: Remove deprecated event re-emission (Ed Sanders)
+
+### Features
+* Allow infusion of widgets in other namespaces (Kunal Mehta)
+* Only allow construction of classes that extend OO.ui.Element in infusion (Kunal Mehta)
+* ButtonInputWidget: Disable generating `<label>` elements (Bartosz Dziewoński)
+* FieldLayout: Support HTML help messages through HtmlSnippet (Kunal Mehta)
+* RadioSelectWidget: Improve accessibility (Bartosz Dziewoński)
+* SelectWidget: Call #chooseItem instead of #selectItem when enter is pressed (Ed Sanders)
+
+### Styles
+* MediaWiki, Apex themes: Add a 'notice' icon, same as the 'alert' indicator (James D. Forrester)
+* MediaWiki, Apex themes: Re-crush with svgo 0.5.3 (James D. Forrester)
+* PopupWidget: Use child selectors to apply rules correctly (Ed Sanders)
+* TextInputWidget: Use 'text' cursor for icon/indicator rather than 'pointer' (Bartosz Dziewoński)
+* Set Scots to use bold-b and italic-i (baud/italeec) (Ed Sanders)
+
+### Code
+* ClippableElement: Fix horizontal clipping in nested scrollable elements (Roan Kattouw)
+* ClippableElement: Only call reconsiderScrollbars() if we actually *stopped* clipping (Roan Kattouw)
+* Follow-up 3ddb3603: unbreak nesting of autosizing or labeled TextInputWidgets (Roan Kattouw)
+* InputWidget: Add additional `<span/>` only for subclasses that need it (Bartosz Dziewoński)
+* LookupElement: Disallow editing of readOnly TextInputWidgets (Bartosz Dziewoński)
+* History: Re-write into new B/D/F/S/C format and clean up (James D. Forrester)
+* build: Don't run phpcs over demos/php (Kunal Mehta)
+* build: Update development dependencies (James D. Forrester)
+* build: Update watch rules (Kunal Mehta)
+
+## v0.11.8 / 2015-07-07
+### Features
+* DropdownInputWidget, RadioSelectInputWidget: Consistently call `#cleanUpValue` (Bartosz Dziewoński)
+* TextInputWidget: Allow setting the HTML autocomplete attribute (Florian)
+* TextInputWidget: Support `rows` option when in multiline mode (Kunal Mehta)
+* Make scroll into view work in scrollable divs in Firefox (Roan Kattouw)
+
+### Styles
+* MediaWiki theme: Remove support for frameless primary buttons (Bartosz Dziewoński)
+
+### Code
+* Use at-ease instead of PHP's @ (Kunal Mehta)
+* Use composer's autoloader in exec:phpGenerateJSPHPForKarma (Kunal Mehta)
+* build: Don't lint demos/{dist,node_modules,vendor} (Kunal Mehta)
+* build: Build demos as part of `grunt build` too (Kunal Mehta)
+* build: Build demos as part of `grunt quick-build` (Kunal Mehta)
+* build: Only build test files (`build-tests` task) when going to run tests (Bartosz Dziewoński)
+* demos: Make self-contained in demos/ directory (Kunal Mehta)
+* tests: Provide better output when running infusion test under Karma (Bartosz Dziewoński)
+
+## v0.11.7 / 2015-07-01
+### Features
+* Element.php: Strip all namespaces from infused PHP widgets (Kunal Mehta)
+* OptionWidget: Explicitly set aria-selected to `false` on init (Bartosz Dziewoński)
+
+### Styles
+* MediaWiki theme: Add support for frameless primary buttons (Ed Sanders)
+* MediaWiki theme: Align and center the advanced icon (Roan Kattouw)
+* MediaWiki, Apex themes: Fix styling for frameless process dialog actions (Ed Sanders)
+
+### Code
+* Element.php: Add test case to verify class name in infused widgets (Kunal Mehta)
+* Element.php: Only variables may be passed by reference (Kunal Mehta)
+* Theme.php: Actually make abstract in PHP (Kunal Mehta)
+* Theme.php: Add missing doc comments (Kunal Mehta)
+* documentation: Use bold in comments instead of h4 (Ed Sanders)
+
+## v0.11.6 / 2015-06-23
+### Features
+* NumberInputWidget: Don't use `Math.sign()` (Brad Jorsch)
+* SelectWidget: Fix invalid escape sequence `\s` (Roan Kattouw)
+
+### Styles
+* DropdownWidget: Add white background in MediaWiki theme (Prateek Saxena)
+* SelectFileWidget: Add white background in MediaWiki theme (Prateek Saxena)
+* MediaWiki theme: Add constructive variants for star and unStar icons (Roan Kattouw)
+* MediaWiki theme: Add invert variant to all icons (Roan Kattouw)
+* MediaWiki theme: Add progressive variant to ongoingConversation icon (Stephane Bisson)
+
+### Code
+* Use `.parent` instead of `.super` (Stephane Bisson)
+* build: Updating development dependencies (Kunal Mehta)
+
+## v0.11.5 / 2015-06-16
+### Features
+* ButtonInputWidget: Render frameless button correctly (Bartosz Dziewoński)
+* ComboBoxWidget: Add a getter method for text inputs (Mr. Stradivarius)
+* FieldsetLayout: Make rule for disabled label color more precise (Bartosz Dziewoński)
+* MenuSelectWidget: Explain what the widget config option is for (Roan Kattouw)
+* RadioSelectInputWidget: Unbreak form submission in JS version (Bartosz Dziewoński)
+
+### Styles
+* MediaWiki theme: Add destructive variant to check icon (Matthew Flaschen)
+* MediaWiki, Apex themes: Add ongoingConversation icon (Matthew Flaschen)
+
+### Code
+* build: Configure jsonlint (Kunal Mehta)
+
+## v0.11.4 / 2015-06-09
+### Deprecations
+* [DEPRECATING CHANGE] Introduce oo.ui.mixin namespace for mixins, and put them src/mixins (C. Scott Ananian)
+
+### Features
+* ActionFieldLayout: Add PHP version (Bartosz Dziewoński)
+* ButtonWidget: Fix not having tabindex updated when enabled/disabled (Brad Jorsch)
+* ClippableElement: Fix behavior of clippables in nested scrollables (Bartosz Dziewoński)
+* ClippableElement: Fix behavior of long clippables (Bartosz Dziewoński)
+* Dialog: Label in aria terms (Prateek Saxena)
+* DropdownWidget: Adjust height to other widgets (Bartosz Dziewoński)
+* DropdownWidget: Blank widget when no item is selected (Brad Jorsch)
+* Element#reconsiderScrollbars: Preserve scroll position (Bartosz Dziewoński)
+* GroupElement: pass correct event name to disconnect() from aggregate() (Roan Kattouw)
+* NumberInputWidget: Create, for numeric input (Brad Jorsch)
+* NumberInputWidget: Use keydown, not keypress (Brad Jorsch)
+* ProcessDialog: Don't center the title label if there's not enough space (Bartosz Dziewoński)
+* RadioOptionWidget: Control focus more strictly (Bartosz Dziewoński)
+* RadioSelectInputWidget: Create (Bartosz Dziewoński)
+* SelectFileWidget: Create (Brad Jorsch)
+* SelectWidget: Listen to keypresses and jump to matching items (Brad Jorsch)
+* TextInputWidget: Adjust height to other widgets (Bartosz Dziewoński)
+* Widget: Add `#supportsSimpleLabel` static property to control `<label>` usage (Bartosz Dziewoński)
+* Window: Clear margins for actions in horizontal/vertical groups (Ed Sanders)
+* `OOUI\Tag`: Avoid 'Potentially unsafe "href" attribute value' exceptions for relative URLs (Bartosz Dziewoński)
+
+### Styles
+* MessageDialog: Remove unintentional action button margin (Bartosz Dziewoński)
+* styles: Change gradient mixin syntax to W3C standards' syntax (Volker E)
+* styles: Remove obsolete "-ms-linear-gradient" declaration (Volker E)
+* Apex theme: Use matching 'lock' and 'unLock' icons (Bartosz Dziewoński)
+* MediaWiki and Apex themes: Force background color of `<select>` to white (Ed Sanders)
+* MediaWiki and Apex themes: Re-crush SVG files (James D. Forrester)
+
+### Code
+* ActionFieldLayout: Dead code removal and cleanup (Bartosz Dziewoński)
+* BarToolGroup: Add description and example (Kirsten Menger-Anderson)
+* ButtonInputWidget and TextInputWidget: Document and enforce allowed types (Bartosz Dziewoński)
+* DropdownInputWidget: Tweak documentation (Bartosz Dziewoński)
+* InputWidget#getInputElement: Mark as `@protected`, not `@private` (Bartosz Dziewoński)
+* ListToolGroup: Add description and example (Kirsten Menger-Anderson)
+* MenuToolGroup: Add description, example and mark private method (Kirsten Menger-Anderson)
+* PendingElement: Add description (Kirsten Menger-Anderson)
+* PopupTool: Add description and example (Kirsten Menger-Anderson)
+* PopupToolGroup: Add description and mark protected methods (Kirsten Menger-Anderson)
+* Tool: Add description (Kirsten Menger-Anderson)
+* ToolFactory: Add description (Kirsten Menger-Anderson)
+* ToolGroup: Add description and mark protected methods (Kirsten Menger-Anderson)
+* ToolGroupFactory: Add description (Kirsten Menger-Anderson)
+* ToolGroupTool: Add description and example (Kirsten Menger-Anderson)
+* Toolbar: Add description (Kirsten Menger-Anderson)
+* `OOUI\Element::mixins`: Improve doc comment (Kunal Mehta)
+* `OOUI\Tag`: Add basic phpunit tests (Kunal Mehta)
+* build: Update MediaWiki codesniffer to 0.2.0 (Kunal Mehta)
+* build: Updating development dependencies (James D. Forrester)
+* demo: Add 'layout' variable to the consoles (Bartosz Dziewoński)
+* demo: Link JS and PHP demos (Bartosz Dziewoński)
+* docs: Update name of upstream OOjs project in jsduck documentation (C. Scott Ananian)
+* mailmap: Add an additional e-mail for Bartosz per request (James D. Forrester)
+* test: Use -p option to phpcs instead of -v (Kunal Mehta)
+
+## v0.11.3 / 2015-05-12
+### Features
+* BarToolGroup: Don't use "pointer" cursor for disabled tools in enabled toolgroups (Bartosz Dziewoński)
+* Tool: Support icon+label in bar tool groups (Bartosz Dziewoński)
+* ToolGroupTool: Correct opacity of disabled nested tool group handle (Bartosz Dziewoński)
+* ToolGroupTool: Synchronize inner ToolGroup disabledness state (Bartosz Dziewoński)
+
+### Styles
+* MediaWiki theme: Add a powerful default text color for tools (Trevor Parscal)
+* MediaWiki theme: Adjust quotes icon to match other icons (nirzar)
+* MediaWiki theme: Give names to some more toolbar colours (Bartosz Dziewoński)
+* MediaWiki theme: Provide all variants of the 'tag' icon (James D. Forrester)
+* MediaWiki theme: Rejigger some toolbar coloring (Bartosz Dziewoński)
+* MediaWiki theme: Remove box-shadow from nested toolbars (Bartosz Dziewoński)
+* MediaWiki theme: Remove unusued toolbar shadow (Trevor Parscal)
+* MediaWiki theme: Update button specification (nirzar)
+
+## v0.11.2 / 2015-05-11
+### Features
+* Don't select lookup items on initialize (Ed Sanders)
+* ListToolGroup, MenuToolGroup: Set accelTooltips = false (Bartosz Dziewoński)
+* PopupWidget: Add setAlignment (Moriel Schottlender)
+* Simplify default action prevention in buttons and forms (Bartosz Dziewoński)
+* TextInputWidget: Allow override of #setValidityFlag (Ed Sanders)
+* TextInputWidget: Use aria-required along with the required attribute (Prateek Saxena)
+
+### Styles
+* TabOptionWidget: Fix disabled styles to not react to hover/select (Ed Sanders)
+* Toolbar: Fix shadow styling (Bartosz Dziewoński)
+* Toolbar: Remove some useless code from the example (Bartosz Dziewoński)
+* Toolbar: Rework example and add 'menu' tool group example (Bartosz Dziewoński)
+* MediaWiki theme: Change highlight color for selected menu option (nirzar)
+* MediaWiki theme: Polish the toolbar design (nirzar)
+* MediaWiki theme: Remove accidentally duplicated styles for SelectWidget (Bartosz Dziewoński)
+
+### Code
+* SelectWidget: Mark as @abstract, which it is (Bartosz Dziewoński)
+* Toolbar: Move some tweaks from demo to actual implementation (Bartosz Dziewoński)
+
+## v0.11.1 / 2015-05-04
+### Features
+* Add IndexLayout (Trevor Parscal)
+* SelectWidget: Add #selectItemByData method (Moriel Schottlender)
+* TextInputWidget: Annotate input validation with aria-invalid (Prateek Saxena)
+* TextInputWidget: Don't set 'invalid' flag on first focus, even if invalid (Bartosz Dziewoński)
+* TextInputWidget: Support 'required' config option in PHP (Bartosz Dziewoński)
+
+### Styles
+* MediaWiki theme: Add 'destructive' variant to block icon (Moriel Schottlender)
+* MediaWiki theme: Better vertical alignment of 'search' icon (Ed Sanders)
+* MediaWiki theme: Tweak 'search' icon size (Ed Sanders)
+* MediaWiki theme: Use variable for transition time and easing function (Prateek Saxena)
+* MediaWiki theme: input: Use variable for transition time and easing function (Prateek Saxena)
+* MediaWiki theme: radio/checkbox: Use variable for transition time and easing function (Prateek Saxena)
+* MediaWiki, Apex themes: Switch icons: clear → cancel, closeInput → clear (Bartosz Dziewoński)
+* MediaWiki, Apex themes: Switch over 'magnifyingGlass' icon to be 'search' (James D. Forrester)
+
+### Code
+* CardLayout: Fix typo (Kirsten Menger-Anderson)
+* LabelElement: Document that label config option can take an HtmlSnippet (Roan Kattouw)
+* PopupButtonWidget: Update align config in example (Kirsten Menger-Anderson)
+* Remove GridLayout remnants (Bartosz Dziewoński)
+* TabOptionWidget: Change link to card layout (Kirsten Menger-Anderson)
+* build: Add clean:doc task (Bartosz Dziewoński)
+* build: Bump grunt-jscs to latest version (James D. Forrester)
+* core: Add OO.ui.debounce() utility (Roan Kattouw)
+* demo: Add icons with variants to icons demo (Bartosz Dziewoński)
+
+## v0.11.0 / 2015-04-29
+### Breaking changes
+* [BREAKING CHANGE] Do not set font-size: 0.8em anywhere in the library (Bartosz Dziewoński)
+
+### Deprecations
+* [DEPRECATING CHANGE] Create rtl-ready alignments in PopupWidget (Moriel Schottlender)
+
+### Features
+* MediaWiki theme: Adding variants to several icons (Moriel Schottlender)
+* TextInputWidget: Allow functions to be passed as 'validate' config option (Bartosz Dziewoński)
+
+### Styles
+* TextInputWidget: Styles for 'invalid' flag (Bartosz Dziewoński)
+
+### Code
+* Update OOjs to v1.1.7 (James D. Forrester)
+* Update jQuery from v1.11.1 to v1.11.3 (James D. Forrester)
+* build: Use jquery and oojs from npm instead of embedded lib (Timo Tijhof)
+
+## v0.10.1 / 2015-04-27
+### Features
+* Correct `tabindex` attribute setting (Bartosz Dziewoński)
+* Make toolbars keyboard-accessible (Bartosz Dziewoński)
+
+### Code
+* ToggleButtonWidget: Unbreak horizontal alignment (Bartosz Dziewoński)
+
+## v0.10.0 / 2015-04-22
+### Breaking changes
+* [BREAKING CHANGE] ButtonWidget: remove deprecated `nofollow` option alias (C. Scott Ananian)
+* [BREAKING CHANGE] Convert ToggleWidget from a mixin to an abstract class (Bartosz Dziewoński)
+* [BREAKING CHANGE] MenuLayout: Reimplement without inline styles (Bartosz Dziewoński)
+
+### Deprecations
+
+### Features
+* BarToolGroup: Allow tools with labels instead of icons (Bartosz Dziewoński)
+* BookletLayout: Find first focusable element and add focusable utility (Moriel Schottlender)
+* ButtonWidget: Remove href to make unclickable when disabled (Bartosz Dziewoński)
+
+### Styles
+* MediaWiki, Apex themes: Add viewCompact, viewDetails, visionSimulator icons (Mun May Tee)
+
+### Code
+* ButtonInputWidget: Don't double-mixin FlaggedElement (Bartosz Dziewoński)
+* ButtonWidget: Remove pointless #isHyperlink property (Bartosz Dziewoński)
+* FormLayout: Better document how this works with InputWidgets (Bartosz Dziewoński)
+* MenuLayout: Add example (Kirsten Menger-Anderson)
+* MenuLayout: Fix initialization order (Bartosz Dziewoński)
+* PHP: More useful debugging information on unsafe tag attributes (Chad Horohoe)
+* SelectWidget#getTargetItem: Simplify (Ed Sanders)
+* Toolbar: Add example (Bartosz Dziewoński)
+* demo: Remove VisualEditor references from toolbar demo, use generic icons (Ed Sanders)
+* demo: Remove outline controls from outlined BookletLayout demo (Bartosz Dziewoński)
+* demo: Simplify ButtonGroupWidget and ButtonSelectWidget examples (Bartosz Dziewoński)
+
+## v0.9.8 / 2015-04-12
+### Features
+* BookletLayout: Allow focus on any item (Moriel Schottlender)
+
+### Styles
+* Apex theme: Correctly position popups in RTL; follows-up v0.9.5 (Moriel Schottlender)
+* Apex, MediaWiki themes: Correct or delete unused SVG files (James D. Forrester)
+
+### Code
+* Error: Add description (Kirsten Menger-Anderson)
+* ProcessDialog: Remove stray `this.$` from documentation code example (Roan Kattouw)
+* ProgressBarWidget: Remove spurious styles from CSS output (Bartosz Dziewoński)
+
+* build: Add explicit dependency upon grunt-cli (Kunal Mehta)
+* build: Move coverage output from "/dist/coverage" to "/coverage" (Timo Tijhof)
+* build: Run lint before build in grunt-test (Timo Tijhof)
+* colorize-svg: Generate language-specific rules for images even if equal to default ones (Bartosz Dziewoński)
+* colorize-svg: Sprinkle `/* @noflip */` on language-specific rules (Bartosz Dziewoński)
+* demo: Change html dir property when direction changes (Moriel Schottlender)
+
+## v0.9.7 / 2015-04-03
+### Code
+* build: Generate correct paths to fallback images (Bartosz Dziewoński)
+
+## v0.9.5 / 2015-04-02
+### Deprecations
+* [DEPRECATING CHANGE] Deprecate search widget event re-emission (Ed Sanders)
+
+### Features
+* Process: Allow rejecting with single Error (Matthew Flaschen)
+* Correctly position popups in RTL (Moriel Schottlender)
+
+### Styles
+* ButtonElement: Increase specificity of icon and indicator styles (Bartosz Dziewoński)
+* DecoratedOptionWidget: Fix opacity of icons/indicators when disabled (Ed Sanders)
+
+* Balance padding now that focus highlight is balanced (Ed Sanders)
+* Remove line height reset for windows (Ed Sanders)
+* Restore font family definitions to form elements (Ed Sanders)
+
+* Apex theme: Tweak `check.svg` syntax (Bartosz Dziewoński)
+* MediaWiki, Apex themes: Bring in remaining VisualEditor icons (James D. Forrester)
+* MediaWiki, Apex themes: Provide an RTL variant for the help icon (James D. Forrester)
+* MediaWiki theme: Add vertical spacing to RadioSelectWidget (Ed Sanders)
+* MediaWiki theme: Allow intention flags for non-buttons (Andrew Garrett)
+* MediaWiki theme: Fix icon opacity for disabled ButtonOptionWidgets (Bartosz Dziewoński)
+* MediaWiki theme: Revert "Syncing some button styles with MediaWiki UI" (Bartosz Dziewoński)
+* MediaWiki theme: Use checkbox icon per mockups (Bartosz Dziewoński)
+
+### Code
+* ActionFieldLayout: Add description and example (Kirsten Menger-Anderson)
+* BookletLayout: Add description and example (Kirsten Menger-Anderson)
+* IconWidget: Mix in FlaggedElement (Bartosz Dziewoński)
+* MenuLayout: Correct documentation (Bartosz Dziewoński)
+* OutlineOption: Add description (Kirsten Menger-Anderson)
+* PageLayout: Add description (Kirsten Menger-Anderson)
+* Process: Add description (Kirsten Menger-Anderson)
+* StackLayout: Add description and example (Kirsten Menger-Anderson)
+* Choose can't emit with a null item (Ed Sanders)
+* Refactor icon handling again (Bartosz Dziewoński)
+* build: Add a 'generated automatically' banner to demo.rtl.css (Bartosz Dziewoński)
+* build: Generate prettier task names for 'colorizeSvg' (Bartosz Dziewoński)
+* build: Have separate 'cssjanus' target for demo.rtl.css (Bartosz Dziewoński)
+* build: Make colorize-svg.js actually work more often (Bartosz Dziewoński)
+* build: Properly support LTR/RTL icon versions in colorize-svg.js (Bartosz Dziewoński)
+* build: Simplify 'fileExists' task configuration (Bartosz Dziewoński)
+* build: Support (poorly) per-language icon versions in colorize-svg.js (Bartosz Dziewoński)
+* build: Update grunt-banana-checker to v0.2.1 (James D. Forrester)
+
+## v0.9.4 / 2015-03-25
+### Breaking changes
+
+### Deprecations
+
+### Features
+* ProcessDialog#executeAction: Don't eat parent's return value (Roan Kattouw)
+* Compensate for loss of margin when opening modals (Ed Sanders)
+* Make outline controls' abilities configurable (Trevor Parscal)
+
+### Styles
+* MediaWiki theme: Reduce thickness of toolbar border (Ed Sanders)
+
+### Code
+* ButtonElement: Clarify description (Kirsten Menger-Anderson)
+* ButtonElement: Disable line wrapping on buttons (Ed Sanders)
+* FieldLayout: Clarify description and mark private methods (Kirsten Menger-Anderson)
+* FieldsetLayout: Add description and example (Kirsten Menger-Anderson)
+* FormLayout: Add description, example, and mark private method (Kirsten Menger-Anderson)
+* Layout: Add description (Kirsten Menger-Anderson)
+* LookupElement: Add description and mark private and protected methods (Kirsten Menger-Anderson)
+* LookupElement: Fix typo in docs (Bartosz Dziewoński)
+* MenuLayout: Reorder styles (Bartosz Dziewoński)
+* MenuSectionOptionWidget: Add description and example (Kirsten Menger-Anderson)
+* PanelLayout: Add description and example (Kirsten Menger-Anderson)
+* SearchWidget: Add description and mark private methods (Kirsten Menger-Anderson)
+* TabIndexElement: Mark private method (Kirsten Menger-Anderson)
+
+## v0.9.3 / 2015-03-19
+### Features
+* LookupElement: Add optional config field for suggestions when empty (Matthew Flaschen)
+* ProcessDialog: send an array to showErrors in failed executeAction (Moriel Schottlender)
+
+### Code
+* Dialog: Fix links to static properties (Kirsten Menger-Anderson)
+* DraggableGroupElement: Clarify description and mark private methods (Kirsten Menger-Anderson)
+* Fix code style in `@examples` (Ed Sanders)
+* FlaggedElement: Add example and clarify description (Kirsten Menger-Anderson)
+* GroupElement: Clarify description (Kirsten Menger-Anderson)
+* IndicatorElement: Clarify description (Kirsten Menger-Anderson)
+* MenuSelectWidget: Clarify description (Kirsten Menger-Anderson)
+* TabIndexedElement: Clarify description (Kirsten Menger-Anderson)
+* TitledElement: Clarify description (Kirsten Menger-Anderson)
+* Widget: Clarify description (Kirsten Menger-Anderson)
+* Window: Clarify description of setDimensions method (Kirsten Menger-Anderson)
+* WindowManager: Clarify description and mark private methods (Kirsten Menger-Anderson)
+* Update OOjs to v1.1.6 (James D. Forrester)
+* Add .mailmap file (Roan Kattouw)
+* Add Kirsten to AUTHORS.txt (Roan Kattouw)
+* demo: Add one more toolbars demo (Bartosz Dziewoński)
+
+## v0.9.2 / 2015-03-12
+### Styles
+* Toolbar: Be less aggressive with `white-space: nowrap` (Bartosz Dziewoński)
+
+### Code
+* Window: Revert changes from 521061dd (Bartosz Dziewoński)
+
+## v0.9.1 / 2015-03-11
+### Features
+* PanelLayout: Add `framed` config option (Bartosz Dziewoński)
+* TextInputWidget: Use MutationObserver for #onElementAttach support (Bartosz Dziewoński)
+* Only prevent default for handled keypresses (Brad Jorsch)
+
+### Styles
+* Toolbar: Tighten whitespace on narrow displays (Bartosz Dziewoński)
+* MediaWiki theme: Add the progressive variant to the check icon (Prateek Saxena)
+* MediaWiki theme: Add warning variant to icon set (Mark Holmquist)
+* MediaWiki theme: Add "Wikicon" icons (Mun May Tee)
+* MediaWiki theme: Synchronise button styles between OOJS and MW (nirzar)
+* MediaWiki theme: Syncing some button styles with MediaWiki UI (kaldari)
+* MediaWiki theme: textInputWidget: Update focus state (Prateek Saxena)
+
+### Code
+* ActionSet: Add description for events and clarify method descriptions (Kirsten Menger-Anderson)
+* ActionSet: Clarify description (Kirsten Menger-Anderson)
+* ActionWidget: Clarify description and mark private method (Kirsten Menger-Anderson)
+* ActionWidget: Fix bad copy-paste in documentation (Bartosz Dziewoński)
+* ButtonElement: Use #setButtonElement correctly (Bartosz Dziewoński)
+* ButtonInputWidget: Clarify description of configs and methods (Kirsten Menger-Anderson)
+* Dialog: Mark private methods and add description of methods and configs (Kirsten Menger-Anderson)
+* InputWidget: Clarify description (Kirsten Menger-Anderson)
+* MessageDialog: Add description, example, and mark private methods (Kirsten Menger-Anderson)
+* OutlineControlsWidget: Add description (Kirsten Menger-Anderson)
+* OutlineSelectWidget: Add description (Kirsten Menger-Anderson)
+* ProcessDialog: Add description and example and mark private methods (Kirsten Menger-Anderson)
+* TextInputMenuSelectWidget: Add description and mark private methods (Kirsten Menger-Anderson)
+* TextInputWidget: Adjust size and label on first focus, too (Bartosz Dziewoński)
+* Window: Clarify descriptions of methods and configs (Kirsten Menger-Anderson)
+* WindowManager: Documentation typo (Ed Sanders)
+* Icon width should only be applied if there is an icon (Moriel Schottlender)
+* Remove half-baked touch event handling (Bartosz Dziewoński)
+* Remove remnants of window isolation (Bartosz Dziewoński)
+* AUTHORS: Add Derk-Jan Hartman (Derk-Jan Hartman)
+* build: Implement basic image flipping support in colorize-svg (Bartosz Dziewoński)
+* build: Move pre/post 'doc' task into package.json (Timo Tijhof)
+* build: Remove obsolete 'build' task from grunt-doc (Timo Tijhof)
+* build: Set 'generateExactDuplicates: true' for CSSJanus (Bartosz Dziewoński)
+* demo: Fix typo in toolbars demo (Bartosz Dziewoński)
+* demo: Load styles before building demo widgets (not asynchronously) (Bartosz Dziewoński)
+* demo: Simplify `@media` styles (Bartosz Dziewoński)
+* demo: Use popup with head in the toolbars demo (Bartosz Dziewoński)
+* jsduck: Add MouseEvent and KeyboardEvent to externals (Timo Tijhof)
+* jsduck: Set --processes=0 to fix warnings-exit-nonzero (Timo Tijhof)
+* package.json: Bump grunt-svg2png to 0.2.7 (Bartosz Dziewoński)
+
+## v0.9.0 / 2015-03-04
+### Breaking changes
+* [BREAKING CHANGE] Remove innerOverlay (Ed Sanders)
+* [BREAKING CHANGE] TextInputWidget: Remove `icon` and `indicator` events (Bartosz Dziewoński)
+* [BREAKING CHANGE] Remove deprecated LookupInputWidget (Bartosz Dziewoński)
+* [BREAKING CHANGE] Remove deprecated GridLayout (Bartosz Dziewoński)
+
+### Features
+* Move `OO.ui.infuse` to `OO.ui.Element.static.infuse`. (C. Scott Ananian)
+* Fake toolbar group nesting (Bartosz Dziewoński)
+* Infer retry button action flags from symbolic name (Trevor Parscal)
+* InputWidget: Focus checkboxes and radios, too, when the label is clicked (Bartosz Dziewoński)
+* ProcessDialog: Dismiss errors on teardown (Moriel Schottlender)
+
+### Styles
+* Make icon and indicator container sizes consistent (Ed Sanders)
+* Restore previous toolbar items margins and padding (Bartosz Dziewoński)
+* Use the correct color for gray buttons (Prateek Saxena)
+
+### Code
+* CheckboxInputWidget: Add description and example (Kirsten Menger-Anderson)
+* ComboBoxWidget: Add description, example, and mark private methods (Kirsten Menger-Anderson)
+* DecoratedOptionWidget: Add description and example (Kirsten Menger-Anderson)
+* DropdownInputWidget: Add description, example, and mark private method (Kirsten Menger-Anderson)
+* FieldLayout: Fix display of documentation's bulleted list (Kirsten Menger-Anderson)
+* GroupWidget and ItemWidget: Mark `private` (Kirsten Menger-Anderson)
+* IndicatorWidget: Add description and example (Kirsten Menger-Anderson)
+* LabelElement: Don't call constructor twice for ActionFieldLayouts (Roan Kattouw)
+* LabelWidget: Add description, example, and mark private method (Kirsten Menger-Anderson)
+* PopupElement: Add description (Kirsten Menger-Anderson)
+* PopupTool: Tool constructor takes a toolGroup, not a toolbar (Bartosz Dziewoński)
+* PopupWidget: Add description, example, and mark private methods (Kirsten Menger-Anderson)
+* PopupWidget: Add keydown listener and hide popup on ESC (Prateek Saxena)
+* ProgressBar: Add description and example (Kirsten Menger-Anderson)
+* RadioInputWidget: Add description and example (Kirsten Menger-Anderson)
+* SelectWidget: Add example and link to decorated option widget (Kirsten Menger-Anderson)
+* SelectWidget: Marked protected methods and clarified choose/press descriptions (Kirsten Menger-Anderson)
+* TextInputWidget: Add description, example, and mark private methods (Kirsten Menger-Anderson)
+* ToggleButtonWidget: Add description, example, and mark private method (Kirsten Menger-Anderson)
+* ToggleSwitchWidget: Add description, example, and mark private methods (Kirsten Menger-Anderson)
+* ToggleWidget: Add description (Kirsten Menger-Anderson)
+* Fix invalid use of border shorthand syntax (Timo Tijhof)
+* Only modify body class when first/last window opens/closes (Ed Sanders)
+* Use only two variables each for each semantic color (Prateek Saxena)
+* build: Add disconnect tolerance to karma config (James D. Forrester)
+* build: Remove footer override from jsduck (Timo Tijhof)
+* demo: Add PopupTool to toolbar demo (Bartosz Dziewoński)
+* demo: Call Toolbar#initialize in toolbar demo (Bartosz Dziewoński)
+* tests: Add infusion tests (Bartosz Dziewoński)
+* tests: Run JS/PHP tests for widgets with required parameters, too (Bartosz Dziewoński)
+
+## v0.8.3 / 2015-02-26
+### Features
+* Revert "Unbreak form submission in JavaScript" (Bartosz Dziewoński)
+
+## v0.8.2 / 2015-02-26
+### Features
+* PHP TitledElement: Actually set $this->title (Bartosz Dziewoński)
+* PHP PanelLayout: Fix getConfig() for `expanded` config option (Bartosz Dziewoński)
+
+### Code
+* testsuitegenerator: Exclude 'text' parameter from tests, like 'content' (Bartosz Dziewoński)
+* WindowManager: Don't pass `this` to window factory method (Bartosz Dziewoński)
+
+## v0.8.1 / 2015-02-25
+### Deprecations
+* [DEPRECATING CHANGE] Rename setPosition to setLabelPosition (Ed Sanders)
+
+### Features
+* Allow passing positional parameters inside the config object (Bartosz Dziewoński)
+* ComboBox: Use combobox role (Derk-Jan Hartman)
+* Element.php: Add "data" property (C. Scott Ananian)
+* Element.php: Add "text" configuration option (C. Scott Ananian)
+* Element: Add `content` config option, matching PHP side. (C. Scott Ananian)
+* FormLayout: Allow adding child layouts via config (Bartosz Dziewoński)
+* Implement OO.ui.infuse to reconstitute PHP widgets in client-side JS (C. Scott Ananian)
+* Serialize PHP widget state into data-ooui attribute (C. Scott Ananian)
+* TextInputWidget: Fix appearance of icons and labels when disabled (Ed Sanders)
+* Unbreak form submission in JavaScript (Bartosz Dziewoński)
+
+### Styles
+* Set proper spacing between interleaved FieldsetLayouts and FormLayouts (Bartosz Dziewoński)
+* MediaWiki theme: Drop unnecessary pseudo-element of CheckboxInputWidget (Timo Tijhof)
+* MediaWiki theme: Drop unnecessary pseudo-element of RadioInputWidget (Timo Tijhof)
+* MediaWiki theme: Simplify spacing of checkboxes/radios in FieldLayouts (Bartosz Dziewoński)
+
+### Code
+* ButtonOptionWidget: Add description (Kirsten Menger-Anderson)
+* ButtonSelectWidget: Add description and example (Kirsten Menger-Anderson)
+* DraggableElement: Mark private methods and add description to events (Kirsten Menger-Anderson)
+* Element.php: Tweak docs (Bartosz Dziewoński)
+* Element: Add description for configs and static property (Kirsten Menger-Anderson)
+* Error: Fix function name (Bartosz Dziewoński)
+* Fix typo: contian → contain (Bartosz Dziewoński)
+* FlaggedElement: Add description of event and config option (Kirsten Menger-Anderson)
+* Follow-up bade83bfdfc: actually remove ../ (Roan Kattouw)
+* IconElement: Add description for config options (Kirsten Menger-Anderson)
+* IconElement: Add description of methods (Kirsten Menger-Anderson)
+* IndicatorElement: Add description for configs and static properties (Kirsten Menger-Anderson)
+* LabelElement: Add description, config description, static property description (Kirsten Menger-Anderson)
+* MenuOptionWidget: Add description (Kirsten Menger-Anderson)
+* MenuSelectWidget: Add description and mark protected method (Kirsten Menger-Anderson)
+* Move toggle() from Widget to Element (Moriel Schottlender)
+* OptionWidget: Add description and descriptions of methods (Kirsten Menger-Anderson)
+* PopupButtonWidget: Add description and example and mark private method (Kirsten Menger-Anderson)
+* Prefer OO.isPlainObject to $.isPlainObject (Bartosz Dziewoński)
+* RadioOptionWidget: Add description (Kirsten Menger-Anderson)
+* RadioOptionWidget: Make disabling single options work (Bartosz Dziewoński)
+* RadioSelectWidget: Add description and example (Kirsten Menger-Anderson)
+* Remove '$: this.$' from code examples (Bartosz Dziewoński)
+* Remove loop length check (Ed Sanders)
+* SelectWidget: Add description for config, methods, events (Kirsten Menger-Anderson)
+* TabIndexelement: Add description, example, and mark private method (Kirsten Menger-Anderson)
+* TitledElement: Add description and config and static descriptions (Kirsten Menger-Anderson)
+* Update OOjs to v1.1.5 (James D. Forrester)
+* Work around Safari 8 mis-rendering checkboxes in SVG-only distribution (Bartosz Dziewoński)
+* build: Give docparser.rb Ruby 1.9.3 compatibility (Bartosz Dziewoński)
+* build: Include 'lib' and 'dist' in jsduck output (Timo Tijhof)
+* build: Teach docparser about `@member`, `@see`, and PHP pass-by-reference (`&$foo`). (C. Scott Ananian)
+* build: Unbreak docparser.rb (Bartosz Dziewoński)
+* build: Use grunt-contrib-copy instead of custom 'copy' task (Timo Tijhof)
+* composer.json: Add description field (Kunal Mehta)
+* demo: Add disabled RadioInputWidget to demo (Bartosz Dziewoński)
+* tests: Add "composer test" command to lint PHP files and run phpcs (Kunal Mehta)
+* tests: Reduce timeout in Process test from 100 to 10 (Timo Tijhof)
+* tests: Run JS/PHP comparison tests using karma (Bartosz Dziewoński)
+
+## v0.8.0 / 2015-02-18
+### Breaking changes
+* [BREAKING CHANGE] Make default distribution provide SVG with PNG fallback (Bartosz Dziewoński)
+
+### Deprecations
+* [DEPRECATING CHANGE] ButtonWidget: Rename nofollow config option to noFollow (C. Scott Ananian)
+* [DEPRECATING CHANGE] TextInputWidget: Deprecate `icon` and `indicator` events (Bartosz Dziewoński)
+
+### Features
+* TabIndexedElement: Allow tabIndex property to be null (C. Scott Ananian)
+* TextInputWidget: Allow maxLength of 0 in JS (matching PHP) (Bartosz Dziewoński)
+
+### Styles
+* MediaWiki theme: Add focus state for frameless button (Prateek Saxena)
+* MediaWiki theme: Fix border width for frameless buttons' focus state (Prateek Saxena)
+* MediaWiki theme: Resynchronize PHP with JS (Bartosz Dziewoński)
+* MediaWiki theme: Use white icons for disabled buttons (Bartosz Dziewoński)
+
+### Code
+* ActionSet: Add `@private` to onActionChange method (Kirsten Menger-Anderson)
+* ActionSet: Add description and example (Kirsten Menger-Anderson)
+* ActionSet: Add description for specialFlags property (Kirsten Menger-Anderson)
+* ActionWidget: Add description (Kirsten Menger-Anderson)
+* Add missing ButtonInputWidget.less and corresponding mixin (Bartosz Dziewoński)
+* ButtonElement: Add description (Kirsten Menger-Anderson)
+* ButtonElement: add `protected` to event handlers (Kirsten Menger-Anderson)
+* ButtonGroupWidget: Add description and example (Kirsten Menger-Anderson)
+* ButtonInputWidget: Add description and example (Kirsten Menger-Anderson)
+* ButtonWidget: Add example and link (Kirsten Menger-Anderson)
+* Dialog: Add description and example (Kirsten Menger-Anderson)
+* DraggableElement: Add description (Kirsten Menger-Anderson)
+* DraggableGroupElement: Add description (Kirsten Menger-Anderson)
+* DropdownWidget: Add `@private` to private methods (Kirsten Menger-Anderson)
+* DropdownWidget: Add description and example (Kirsten Menger-Anderson)
+* DropdownWidget: Simplify redundant code (Bartosz Dziewoński)
+* Element: Add description (Kirsten Menger-Anderson)
+* FieldLayout: Add description (Kirsten Menger-Anderson)
+* FieldLayout: Clean up and remove lies (Bartosz Dziewoński)
+* FlaggedElement: Add description (Kirsten Menger-Anderson)
+* Follow-up 6a6bb90ab: Update CSS file path in eg-iframe.html (Roan Kattouw)
+* Follow-up c762da42: fix ProcessDialog error handling (Roan Kattouw)
+* GroupElement: Add description (Kirsten Menger-Anderson)
+* IconElement: Add description (Kirsten Menger-Anderson)
+* IconElement: Add description and fix display of static properties (Kirsten Menger-Anderson)
+* IconWidget: Add description and example (Kirsten Menger-Anderson)
+* IndicatorElement: Add description (Kirsten Menger-Anderson)
+* InputWidget: Add description (Kirsten Menger-Anderson)
+* PHP: Remove redundant documentation for getInputElement() (Bartosz Dziewoński)
+* Refactor keyboard accessibility of SelectWidgets (Bartosz Dziewoński)
+* SelectWidget: Add description (Kirsten Menger-Anderson)
+* Some documentation tweaks (Bartosz Dziewoński)
+* TextInputWidget: Add missing LabelElement mixin documentation (Ed Sanders)
+* TextInputWidget: Don't add label position classes when there's no label (Bartosz Dziewoński)
+* TextInputWidget: Hide mixin components when unused (Ed Sanders)
+* TextInputWidget: Only put $label in the DOM if needed (Bartosz Dziewoński)
+* TextInputWidget: Use margins for moving the label (Ed Sanders)
+* Update PHP widgets for accessibility-related changes in JS widgets (Bartosz Dziewoński)
+* Use Array.isArray instead of $.isArray (C. Scott Ananian)
+* Various fixes to the PHP implementation (C. Scott Ananian)
+* Widget: Add description (Kirsten Menger-Anderson)
+* Window: Add description (Kirsten Menger-Anderson)
+* WindowManager: Add description (Kirsten Menger-Anderson)
+* build: Pass RuboCop, customize settings (Bartosz Dziewoński)
+* demo: Add horizontal alignment test (Bartosz Dziewoński)
+* PHP demo: Correct path to CSS files (Bartosz Dziewoński)
+* tests: Update JS/PHP comparison test suite (Bartosz Dziewoński)
+* docparser: Add support for `protected` methods (Bartosz Dziewoński)
+* docs: Make `@example` documentation tag work (Roan Kattouw)
+* tests: Fix the check for properties (Bartosz Dziewoński)
+* testsuitegenerator: Only test every pair of config options rather than every triple (Bartosz Dziewoński)
+
+## v0.7.0 / 2015-02-11
+### Breaking changes
+* [BREAKING CHANGE] Remove window isolation (Trevor Parscal)
+
+### Deprecations
+* [DEPRECATING CHANGE] GridLayout should no longer be used, instead use MenuLayout (Bartosz Dziewoński)
+
+### Features
+* ButtonWidget: Add `nofollow` option (C. Scott Ananian)
+* ButtonWidget: Better handle non-string parameters in setHref/setTarget (C. Scott Ananian)
+* PopupWidget: Set $clippable only once, correctly (Bartosz Dziewoński)
+* SelectWidget: `listbox` wrapper role, `aria-selected` state on contents (Derk-Jan Hartman)
+* TabIndexedElement: Actually allow tabIndex of -1 (Bartosz Dziewoński)
+* TextInputWidget: Add required attribute on the basis of required config (Prateek Saxena)
+* TextInputWidget: Use aria-hidden for extra autosize textarea (Prateek Saxena)
+* ToggleSwitchWidget: Accessibility improvements (Bartosz Dziewoński)
+
+### Styles
+* FieldsetLayout: Tweak positioning of help icon (Bartosz Dziewoński)
+* Fade in window frames separately from window overlays (Ed Sanders)
+* MediaWiki theme: Consistent toggle button `active` state (Bartosz Dziewoński)
+* MediaWiki theme: Correct flagged primary button text color when pressed (Bartosz Dziewoński)
+* MediaWiki theme: Fix background color for disabled buttons (Prateek Saxena)
+* MediaWiki theme: Fix non-clickability of radios and checkboxes (Bartosz Dziewoński)
+* MediaWiki theme: Rename `@active` to `@pressed` in button mixins (Prateek Saxena)
+* MediaWiki theme: Rename `@highlight` to `@active` (Prateek Saxena)
+* MediaWiki theme: Rename active-* variables to pressed-* (Prateek Saxena)
+* MediaWiki theme: Use darker color for frameless buttons (Prateek Saxena)
+* MediaWiki theme: Use distribution's image type for backgrounds (Bartosz Dziewoński)
+
+### Code
+* ButtonWidget: Add documentation (Kirsten Menger-Anderson)
+* {Checkbox,Radio}InputWidget: Add missing configuration initialization (Bartosz Dziewoński)
+* DraggableGroupElement: Cleanup unreachable code (Moriel Schottlender)
+* DraggableGroupElement: Make sure it supports button widgets (Moriel Schottlender)
+* DraggableGroupElement: Unset dragged item when dropped (Moriel Schottlender)
+* Delete unused src/themes/apex/{raster,vector}.less (Bartosz Dziewoński)
+* DropdownInputWidget: Fix undefined variable in PHP (Bartosz Dziewoński)
+* DropdownWidget, ComboBoxWidget: Make keyboard-accessible (Bartosz Dziewoński)
+* Fix initialisation of window visible (Ed Sanders)
+* Fix text input auto-height calculation (Ed Sanders)
+* ListToolGroup: Remove hack for jQuery's .show()/.hide() (Bartosz Dziewoński)
+* MenuSelectWidget: Codify current behavior of Tab closing the menu (Bartosz Dziewoński)
+* MenuSelectWidget: Don't clobber other events when unbinding (Bartosz Dziewoński)
+* MenuSelectWidget: Remove dead code (Bartosz Dziewoński)
+* OptionWidgets: Make better use of `scrollIntoViewOnSelect` (Bartosz Dziewoński)
+* PopupElement: Correct documentation (Bartosz Dziewoński)
+* RadioOptionWidget: Make it a `<label />` (Bartosz Dziewoński)
+* Refactor clickability of buttons (Bartosz Dziewoński)
+* Remove usage of `this.$` and `config.$` (Trevor Parscal)
+* Stop treating ApexTheme class unfairly and make it proper (Bartosz Dziewoński)
+* TextInputMenuSelectWidget: Correct documentation (Bartosz Dziewoński)
+* build: Bump various devDependencies (James D. Forrester)
+* demo: Add button style showcase from PHP demo (Bartosz Dziewoński)
+* demo: Reorder widgets into somewhat logical groupings (Bartosz Dziewoński)
+* demo: Stop inline consoles from generating white space (Bartosz Dziewoński)
+* demo: Use properties instead of attributes for `<link>` (Timo Tijhof)
+* PHP demo: Add Vector/Raster and MediaWiki/Apex controls (Bartosz Dziewoński)
+* PHP demo: Just echo the autoload error message, don't trigger_error() (Bartosz Dziewoński)
+* PHP demo: Resynchronize with JS demo (Bartosz Dziewoński)
+* History: Fix date typos (James D. Forrester)
+* tests: Just echo the autoload error message, don't trigger_error() (Bartosz Dziewoński)
+* tools.less: Use distribution's image type and path for background (Prateek Saxena)
+
+## v0.6.6 / 2015-02-04
+### Features
+* BookletLayout#toggleOutline: Fix to use MenuLayout method (Ed Sanders)
+* Remove disabled elements from keyboard navigation flow (Derk-Jan Hartman)
+* TextInputWidget: Mostly revert "Don't try adjusting size when detached" (Bartosz Dziewoński)
+* Use CSS overriding trick to support RTL in menu layouts (Ed Sanders)
+
+### Styles
+* Use standard border colours for progress bars (Ed Sanders)
+
+### Code
+* Use css class instead of jQuery .show()/hide()/toggle() (Moriel Schottlender)
+* build: Use karma to v0.12.31 (Timo Tijhof)
+
+## v0.6.5 / 2015-02-01
+### Code
+* ButtonElement: Unbreak 'pressed' state (Bartosz Dziewoński)
+* Make BookletLayout inherit from MenuLayout instead of embedding a GridLayout (Ed Sanders)
+
+## v0.6.4 / 2015-01-30
+### Features
+* Add inline labels to text widgets (Ed Sanders)
+* BookletLayout: Make sure there is a page before focusing (Moriel Schottlender)
+* DropdownInputWidget: Introduce (Bartosz Dziewoński)
+* InputWidget: Resynchronize our internal .value with DOM .value in #getValue (eranroz)
+* Seriously work around the Chromium scrollbar bug for good this time (Bartosz Dziewoński)
+* TabIndexedElement: Introduce and use (Bartosz Dziewoński)
+* TextInputWidget: Accept `maxLength` configuration option (Bartosz Dziewoński)
+* MenuLayout: Introduce (Ed Sanders)
+* Window#updateSize: Add simpler API (Ed Sanders)
+
+### Styles
+* ActionFieldLayout: Add `nowrap` to the button (Moriel Schottlender)
+* FieldsetLayout: Add help icon (Moriel Schottlender)
+* Fix opening/closing animation on windows (Roan Kattouw)
+* OptionWidget: Unbreak 'pressed' state (Bartosz Dziewoński)
+* Provide default margins for buttons and other widgets (Bartosz Dziewoński)
+* MenuSelectWidget and OptionWidget: Remove the 'flash' feature (Bartosz Dziewoński)
+* MediaWiki theme: Adjust ButtonSelectWidget, ButtonGroupWidget highlights (Prateek Saxena)
+* MediaWiki theme: Adjust MenuOptionWidget selected state (Bartosz Dziewoński)
+* MediaWiki theme: Fix background issues with disabled buttons (Roan Kattouw)
+* MediaWiki theme: Reduce size of checkboxes and radio buttons by 20% (Ed Sanders)
+* MediaWiki theme: Remove SearchWidget's border now dialogs have outline (Ed Sanders)
+* MediaWiki theme: Tweak some more border-radii (Bartosz Dziewoński)
+* MediaWiki theme: Unbreak disabled buttons (Bartosz Dziewoński)
+
+### Code
+* ButtonOptionWidget: Add the TabIndexedElement mixin (Derk-Jan Hartman)
+* InputWidget: Clarify documentation of #getInputElement (Bartosz Dziewoński)
+* PopupButtonWidget: Set aria-haspopup to true (Prateek Saxena)
+* Remove labelPosition check (Ed Sanders)
+* Set input direction in html prop rather than css rule (Moriel Schottlender)
+* TextInputWidget: Don't try adjusting size when detached (Bartosz Dziewoński)
+* TextInputWidget: Remove superfluous role=textbox (Derk-Jan Hartman)
+* ToggleButtonWidget: Set aria-pressed when changing value (Derk-Jan Hartman)
+* ToggleWidget: Use aria-checked (Prateek Saxena)
+* Twiddle things (Ed Sanders)
+* Update OOjs to v1.1.4 and switch to the jQuery-optimised version (James D. Forrester)
+* Widget: Set aria-disabled too in #setDisabled (Derk-Jan Hartman)
+* AUTHORS: Update for the last six months' work (James D. Forrester)
+* build: Bump devDependencies and fix up (James D. Forrester)
+* demo: Have multiline text in multiline widgets (Bartosz Dziewoński)
+* demo: Remove nonexistent 'align' config option for a DropdownWidget (Bartosz Dziewoński)
+
+## v0.6.3 / 2015-01-14
+### Deprecations
+* [DEPRECATING CHANGE] LookupInputWidget should no longer be used, instead use LookupElement
+
+### Features
+* Add an ActionFieldLayout (Moriel Schottlender)
+* Replace old&busted LookupInputWidget with new&hot LookupElement (Bartosz Dziewoński)
+
+### Styles
+* dialog: Provide a 'larger' size for things for which 'large' isn't enough (James D. Forrester)
+* Synchronize ComboBoxWidget and DropdownWidget styles (Bartosz Dziewoński)
+* MediaWiki theme: Adjust toolbar popups' border and shadows (Bartosz Dziewoński)
+* MediaWiki theme: Don't use 'box-shadow' to produce thin grey lines in dialogs (Bartosz Dziewoński)
+
+### Code
+* Toolbar: Update #initialize docs (Bartosz Dziewoński)
+* demo: Switch the default theme from 'Apex' to 'MediaWiki' (Ricordisamoa)
+
+## v0.6.2 / 2015-01-09
+### Features
+* Clear windows when destroying window manager (Ed Sanders)
+* Element: Add support for 'id' config option (Bartosz Dziewoński)
+* TextInputWidget: Add support for 'autofocus' config option (Bartosz Dziewoński)
+
+### Styles
+* Add 'lock' icon (Trevor Parscal)
+* Make `@anchor-size` a LESS variable and calculate borders from it (Ed Sanders)
+* MediaWiki theme: Slightly reduce size of indicator arrows (Ed Sanders)
+* MediaWiki theme: Remove text-shadow on button (Prateek Saxena)
+* MediaWiki theme: Fix focus state for buttons (Prateek Saxena)
+* MediaWiki theme: Add state change transition to checkbox (Prateek Saxena)
+* MediaWiki theme: Fix disabled state of buttons (Prateek Saxena)
+* MediaWiki theme: Fix overlap between hover and active states (Prateek Saxena)
+
+### Code
+* Don't test abstract classes (Bartosz Dziewoński)
+* PHP LabelElement: Actually allow non-plaintext labels (Bartosz Dziewoński)
+* Synchronize `@abstract` class annotations between PHP and JS (Bartosz Dziewoński)
+* WindowManager#removeWindows: Documentation fix (Ed Sanders)
+* tests: Don't overwrite 'id' attribute (Bartosz Dziewoński)
+* testsuitegenerator.rb: Handle inheritance chains (Bartosz Dziewoński)
+
+## v0.6.1 / 2015-01-05
+### Styles
+* FieldsetLayout: Shrink size of label and bump the weight to compensate (James D. Forrester)
+
+### Code
+* Remove use of `Math.round()` for offset and position pixel values (Bartosz Dziewoński)
+* ButtonElement: Inherit all 'font' styles, not only 'font-family' (Bartosz Dziewoński)
+* IndicatorElement: Fix 'indicatorTitle' config option (Bartosz Dziewoński)
+* Error: Unmark as `@abstract` (Bartosz Dziewoński)
+* JSPHP-suite.json: Update (Bartosz Dziewoński)
+* build: Update various devDependencies (James D. Forrester)
+* readme: Update badges (Timo Tijhof)
+* readme: No need to put the same heading in twice (James D. Forrester)
+
+## v0.6.0 / 2014-12-16
+### Breaking changes
+* [BREAKING CHANGE] PopupToolGroup and friends: Pay off technical debt (Bartosz Dziewoński)
+
+### Features
+* Prevent parent window scroll in modal mode using overflow hidden (Ed Sanders)
+* ClippableElement: Handle clipping with left edge (Bartosz Dziewoński)
+
+### Styles
+* ButtonGroupWidget: Remove weird margin-bottom: -1px; from theme styles (Bartosz Dziewoński)
+* MediaWiki theme: RadioInputWidget tweaks (Bartosz Dziewoński)
+
+### Code
+* Sprinkle some child selectors around in BookletLayout styles (Roan Kattouw)
+
+## v0.5.0 / 2014-12-12
+### Breaking changes
+* [BREAKING CHANGE] FieldLayout: Handle 'inline' alignment better (Bartosz Dziewoński)
+* [BREAKING CHANGE] Split primary flag into primary and progressive (Trevor Parscal)
+* [BREAKING CHANGE] CheckboxInputWidget: Allow setting HTML 'value' attribute (Bartosz Dziewoński)
+
+### Features
+* Element.getClosestScrollableContainer: Use 'body' or 'documentElement' based on browser (Prateek Saxena)
+* Give non-isolated windows a tabIndex for selection holding (Ed Sanders)
+* Call .off() correctly in setButtonElement() (Roan Kattouw)
+
+### Styles
+* FieldLayout: In styles, don't assume that label is given (Bartosz Dziewoński)
+* PopupWidget: Remove box-shadow rule that generates invisible shadow (Bartosz Dziewoński)
+* TextInputWidget: Set vertical-align: middle, like buttons (Bartosz Dziewoński)
+* MediaWiki theme: Add hover state to listToolGroup (Trevor Parscal)
+* MediaWiki theme: Add radio buttons (Prateek Saxena)
+* MediaWiki theme: Add state transition to radio buttons (Prateek Saxena)
+* MediaWiki theme: Add thematic border to the bottom of toolbars (Bartosz Dziewoński)
+* MediaWiki theme: Copy .theme-oo-ui-outline{Controls,Option}Widget from Apex (Bartosz Dziewoński)
+* MediaWiki theme: Extract @active-color variable (Bartosz Dziewoński)
+* MediaWiki theme: Improve search widget styling (Trevor Parscal)
+* MediaWiki theme: Make button sizes match Apex (Trevor Parscal)
+* MediaWiki theme: Use gray instead of blue for select and highlight (Trevor Parscal)
+* MediaWiki theme: checkbox: Fix states according to spec (Prateek Saxena)
+
+### Code
+* Account for `<html>` rather than `<body>` being the scrollable root in Chrome (Bartosz Dziewoński)
+* ClippableElement: 7 is a better number than 10 (Bartosz Dziewoński)
+* Don't set line-height of unset button labels (Bartosz Dziewoński)
+* FieldLayout: Synchronise PHP with JS (Bartosz Dziewoński)
+* FieldLayout: Use `<label>` for this.$body, not this.$element (Bartosz Dziewoński)
+* Fix primary button description text (Niklas Laxström)
+* GridLayout: Don't round to 1% (Bartosz Dziewoński)
+* Kill the escape keydown event after handling a window close (Ed Sanders)
+* RadioInputWidget: Remove documentation lies (Bartosz Dziewoński)
+* Temporarily remove position:absolute on body when resizing (Ed Sanders)
+* build: Use String#slice instead of discouraged String#substr (Timo Tijhof)
+* testsuitegenerator: Actually filter out non-unique combinations (Bartosz Dziewoński)
+* README.md: Drop localisation update auto-commits from release notes (James D. Forrester)
+* README.md: Point to Phabricator, not Bugzilla (James D. Forrester)
+
+## v0.4.0 / 2014-12-05
+### Breaking changes
+* [BREAKING CHANGE] Remove deprecated Element#onDOMEvent and #offDOMEvent (Bartosz Dziewoński)
+* [BREAKING CHANGE] Make a number of Element getters static (Bartosz Dziewoński)
+* [BREAKING CHANGE] Rename BookletLayout#getPageName → #getCurrentPageName (Bartosz Dziewoński)
+
+### Features
+* IconElement: Add missing #getIconTitle (Bartosz Dziewoński)
+
+### Styles
+* Follow-up I859ff276e: Add cursor files to repo (Trevor Parscal)
+
+### Code
+* SelectWidget: Rewrite #getRelativeSelectableItem (Bartosz Dziewoński)
+* demo: Don't put buttons in a FieldsetLayout without FieldLayouts around them (Bartosz Dziewoński)
+
+## v0.3.0 / 2014-12-04
+### Breaking changes
+* [BREAKING CHANGE] ButtonWidget: Don't default 'target' to 'blank' (Bartosz Dziewoński)
+
+### Features
+* InputWidget: Update DOM value before firing 'change' event (Bartosz Dziewoński)
+
+### Styles
+* MediaWiki theme: Reduce indentation in theme-oo-ui-checkboxInputWidget (Prateek Saxena)
+
+### Code
+* Adding DraggableGroupElement and DraggableElement mixins (Moriel Schottlender)
+* Remove window even if closing promise rejects (Ed Sanders)
+* TextInputWidget: Reuse a single clone instead of appending and removing new ones (Prateek Saxena)
+* Fix lies in documentation (Trevor Parscal)
+* build: Have grunt watch run 'quick-build' instead of 'build' (Prateek Saxena)
+
+## v0.2.4 / 2014-12-02
+### Features
+* MessageDialog: Fit actions again when the dialog is resized (Bartosz Dziewoński)
+* Window: Avoid height flickering when resizing dialogs (Bartosz Dziewoński)
+
+### Code
+* TextInputWidget: Use .css( propertyName, value ) instead of .css( properties) for single property (Prateek Saxena)
+* TextInputWidget: Stop adjustSize if the value of the textarea is the same (Prateek Saxena)
+
+## v0.2.3 / 2014-11-26
+### Features
+* BookletLayout: Make #focus not crash when there are zero pages or when there is no outline (Roan Kattouw)
+* Dialog: Only handle escape events when open (Alex Monk)
+* Pass original event with TextInputWidget#enter (Ed Sanders)
+* MessageDialog: Add Firefox hack for scrollbars when sizing dialogs (Bartosz Dziewoński)
+* MessageDialog: Actually correctly calculate and set height (Bartosz Dziewoński)
+* Window: Disable transitions when changing window height to calculate content height (Bartosz Dziewoński)
+
+### Code
+* Add missing documentation to ToolFactory (Ed Sanders)
+* Fix RadioOptionWidget demos (Trevor Parscal)
+* RadioOptionWidget: Remove lies from documentation (Trevor Parscal)
+* RadioOptionWidget: Increase rule specificity to match OptionWidget (Bartosz Dziewoński)
+
+## v0.2.2 / 2014-11-25
+### Features
+* MessageDialog: Fit actions after updating window size, not before (Bartosz Dziewoński)
+* ProcessDialog, MessageDialog: Support iconed actions (Bartosz Dziewoński)
+
+### Styles
+* Remove padding from undecorated option widgets (Ed Sanders)
+
+### Code
+* LabelWidget: Add missing documentation for input configuration option (Ed Sanders)
+* MessageDialog: Use the right superclass (Bartosz Dziewoński)
+* build: Add .npmignore (Timo Tijhof)
+
+## v0.2.1 / 2014-11-24
+
+### Features
+* Add focus method to BookletLayout (Roan Kattouw)
+* Start the window opening transition before ready, not after (Roan Kattouw)
+
+### Code
+* LabelElement: Kill inline styles (Bartosz Dziewoński)
+* Add missing History.md file now we're a proper repo (James D. Forrester)
+* readme: Update introduction, badges, advice (James D. Forrester)
+* composer: Rename package to 'oojs-ui' and require php 5.3.3 (Timo Tijhof)
+
+## v0.2.0 / 2014-11-17
+* First versioned release
+
+## v0.1.0 / 2013-11-13
+* Initial export of repo
diff --git a/www/wiki/vendor/oojs/oojs-ui/LICENSE-MIT b/www/wiki/vendor/oojs/oojs-ui/LICENSE-MIT
new file mode 100644
index 00000000..8f0984c5
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/LICENSE-MIT
@@ -0,0 +1,20 @@
+Copyright 2011-2018 OOUI Team and other contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/www/wiki/vendor/oojs/oojs-ui/README.md b/www/wiki/vendor/oojs/oojs-ui/README.md
new file mode 100644
index 00000000..6e98d423
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/README.md
@@ -0,0 +1,152 @@
+[![npm](https://img.shields.io/npm/v/oojs-ui.svg?style=flat)](https://www.npmjs.com/package/oojs-ui) [![Packagist](https://img.shields.io/packagist/v/oojs/oojs-ui.svg?style=flat)](https://packagist.org/packages/oojs/oojs-ui) [![David](https://img.shields.io/david/dev/wikimedia/oojs-ui.svg?style=flat)](https://david-dm.org/wikimedia/oojs-ui#info=devDependencies)
+
+OOUI
+=================
+
+OOUI is a component-based JavaScript UI library. Key features:
+
+* Common widgets, layouts, and dialogs
+* Classes, elements, and mixins to create custom interfaces
+* Internationalization and localization, like right-to-left (RTL) languages support
+* Theme-ability
+* Built-in icons
+* Accessibility features
+
+It is the standard library for Web products at the Wikimedia Foundation, having been originally created for use by [VisualEditor](https://www.mediawiki.org/wiki/VisualEditor).
+
+
+Quick start
+----------
+
+The library is available on [npm](https://www.npmjs.com/package/oojs-ui). To install:
+
+<pre lang="bash">
+$ npm install oojs-ui
+</pre>
+
+Once installed, include the following scripts and styles to get started:
+
+<pre lang="html">
+<script src="node_modules/jquery/dist/jquery.min.js"></script>
+<script src="node_modules/oojs/dist/oojs.min.js"></script>
+
+<script src="node_modules/oojs-ui/dist/oojs-ui.min.js"></script>
+<script src="node_modules/oojs-ui/dist/oojs-ui-wikimediaui.min.js"></script>
+<link rel="stylesheet" href="node_modules/oojs-ui/dist/oojs-ui-wikimediaui.min.css">
+</pre>
+
+
+Loading the library
+-------------------
+
+While the distribution directory is chock-full of files, you will normally load only the following three:
+
+* `oojs-ui.js`, containing the full library;
+* One of `oojs-ui-wikimediaui.css` or `oojs-ui-apex.css`, containing theme-specific styles; and
+* One of `oojs-ui-wikimediaui.js` or `oojs-ui-apex.js`, containing theme-specific code
+
+You can load additional icon packs from files named `oojs-ui-wikimediaui-icons-*.css` or `oojs-ui-apex-icons-*.css`.
+
+The remaining files make it possible to load only parts of the whole library.
+
+Furthermore, every CSS file has a right-to-left (RTL) version available, to be used on pages using right-to-left languages if your environment doesn't automatically flip them as needed.
+
+
+Issue tracker
+-------------
+
+Found a bug or missing feature? Please report it in our [issue tracker Phabricator](https://phabricator.wikimedia.org/maniphest/task/edit/form/1/?projects=PHID-PROJ-dgmoevjqeqlerleqzzx5)!
+
+
+Contributing
+------------
+
+We are always delighted when people contribute patches. To setup your development environment:
+
+
+1. Clone the repo: `$ git clone https://phabricator.wikimedia.org/diffusion/GOJU/oojs-ui.git oojs-ui`
+
+2. Move into the library directory:<br>`$ cd oojs-ui`
+
+3. Install [composer](https://getcomposer.org/download/) and make sure running `composer` will execute it (*e.g.* add it to `$PATH` in POSIX environments).
+
+4. Install dev dependencies:<br>`$ npm install`
+
+5. Build the library (you can alternatively use `grunt quick-build` if you don't need to rebuild the PNGs):<br>`$ grunt build`
+
+6. You can see a suite of demos in `/demos` by executing:<br>`$ npm run-script demos`
+
+7. You can also copy the distribution files from the dist directory into your project.
+
+
+We use [Gerrit](https://gerrit.wikimedia.org/) for code review, and [Phabricator](https://phabricator.wikimedia.org) to track issues. To contribute patches or join discussions all you need is a [developer account](https://wikitech.wikimedia.org/w/index.php?title=Special:CreateAccount&returnto=Help%3AGetting+Started).
+
+* If you've found a bug, or wish to request a feature [raise a ticket on Phabricator](https://phabricator.wikimedia.org/maniphest/task/edit/form/1/?projects=PHID-PROJ-dgmoevjqeqlerleqzzx5).
+* To submit your patch, follow [the "getting started" quick-guide](https://www.mediawiki.org/wiki/Gerrit/Getting_started). We try to review patches within a week.
+* We automatically lint and style-check changes to JavaScript, PHP, LESS/CSS, Ruby and JSON files. You can test these yourself with `npm test` and `composer test` locally before pushing changes. SVG files should be squashed in advance of committing with [SVGO](https://github.com/svg/svgo) using `svgo --pretty --disable=removeXMLProcInst --disable=cleanupIDs <filename>`.
+
+A new version of the library is released most weeks on Tuesdays.
+
+Community
+---------
+
+Get updates, ask questions and join the discussion with maintainers and contributors:
+
+* Join the Wikimedia Developers mailing list, [wikitech-l](https://lists.wikimedia.org/mailman/listinfo/wikitech-l).
+* Chat with the maintainers on `#wikimedia-dev` on `irc.freenode.net`.
+* Ask questions on [StackOverflow](https://stackoverflow.com/tags/oojs-ui/info).
+* Watchlist the [documentation](https://www.mediawiki.org/wiki/OOUI) on MediaWiki to stay updated.
+
+
+Versioning
+----------
+
+We use the [Semantic Versioning guidelines](http://semver.org/).
+
+Releases will be numbered in the following format:
+
+`<major>.<minor>.<patch>`
+
+
+Release
+----------
+
+Release process:
+<pre lang="bash">
+
+ $ cd path/to/oojs-ui/
+ $ git remote update
+ $ git checkout -B release -t origin/master
+
+ # Ensure tests pass
+ $ npm install && composer update && npm test && composer test
+
+ # Avoid using "npm version patch" because that creates
+ # both a commit and a tag, and we shouldn't tag until after
+ # the commit is merged.
+
+ # Update release notes
+ # Copy the resulting list into a new section at the top of History.md and edit
+ # into five sub-sections, in order:
+ # * Breaking changes
+ # * Deprecations
+ # * Features
+ # * Styles
+ # * Code
+ $ git log --format='* %s (%aN)' --no-merges --reverse v$(node -e 'console.log(require("./package.json").version);')...HEAD | grep -v "Localisation updates from" | sort
+ $ edit History.md
+
+ # Update the version number
+ $ edit package.json
+
+ $ git add -p
+ $ git commit -m "Tag vX.X.X"
+ $ git review
+
+ # After merging:
+ $ git remote update
+ $ git checkout origin/master
+ $ git tag "vX.X.X"
+ $ npm run publish-build && git push --tags && npm publish
+
+</pre>
diff --git a/www/wiki/vendor/oojs/oojs-ui/Rakefile b/www/wiki/vendor/oojs/oojs-ui/Rakefile
new file mode 100644
index 00000000..6eef1216
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/Rakefile
@@ -0,0 +1,14 @@
+require 'bundler/setup'
+
+require 'rubocop/rake_task'
+RuboCop::RakeTask.new(:rubocop) do |task|
+ # if you use mediawiki-vagrant, rubocop will by default use it's .rubocop.yml
+ # the next line makes it explicit that you want .rubocop.yml from the directory
+ # where `bundle exec rake` is executed
+ task.options = ['-c', '.rubocop.yml']
+end
+
+task default: [:test]
+
+desc 'Run all build/tests commands (CI entry point)'
+task test: [:rubocop]
diff --git a/www/wiki/vendor/oojs/oojs-ui/bin/dependencytree.rb b/www/wiki/vendor/oojs/oojs-ui/bin/dependencytree.rb
new file mode 100644
index 00000000..26629632
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/bin/dependencytree.rb
@@ -0,0 +1,42 @@
+require 'pp'
+require_relative 'docparser'
+
+$classes = parse_any_path 'src'
+
+def prefix lines
+ if lines.empty?
+ ''
+ else
+ lines.gsub(/^/, '- ')
+ end
+end
+
+def find_class klass_name
+ $classes.find{|c| c[:name] == klass_name }
+end
+
+def describe klass_name
+ out = []
+ out << klass_name
+ klass = find_class klass_name
+ if klass
+ if klass[:parent]
+ out.push prefix describe klass[:parent]
+ end
+ if klass[:mixins]
+ klass[:mixins].each do |mixin|
+ out.push prefix describe mixin
+ end
+ end
+ end
+ out.select{|a| !a.empty? }.join "\n"
+end
+
+$classes.sort_by!{|klass|
+ # sort by "type" first (widget/layout/element/etc.), then by name
+ klass[:name].split(/(?=Layout|Widget|Element|Dialog|Tool|Theme)/).reverse
+}
+
+$classes.each{|klass|
+ puts describe klass[:name]
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/bin/doccomparer.rb b/www/wiki/vendor/oojs/oojs-ui/bin/doccomparer.rb
new file mode 100644
index 00000000..0dcb66a8
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/bin/doccomparer.rb
@@ -0,0 +1,158 @@
+require 'pp'
+require_relative 'docparser'
+
+# convert [ {name: 'foo'}, … ] to { foo: {name: 'foo'}, … }
+def reindex arg
+ if arg.is_a?(Array) && arg.all?{|v| v.is_a? Hash }
+ Hash[ arg.map{|v| [ v[:name], reindex(v) ] } ]
+ elsif arg.is_a? Hash
+ arg.each_pair{|k, v| arg[k] = reindex(v) }
+ else
+ arg
+ end
+end
+
+def indent text, tabs
+ text == '' ? text : text.gsub(/^/, ' ' * tabs)
+end
+
+# whitespace-insensitive strings
+def canonicalize value
+ if value.is_a? String
+ value.strip.gsub(/\s+/, ' ')
+ elsif value.is_a? Array
+ value.map{|v| canonicalize v }
+ elsif value.is_a? Hash
+ value.each_pair{|k, v| value[k] = canonicalize v }
+ else
+ value
+ end
+end
+
+def sanitize_description text
+ cleanup_class_name(text)
+ .gsub('null and undefined', 'null')
+ .gsub('undefined and null', 'null')
+ .gsub('jQuery|string|Function', 'string')
+ .gsub('jQuery', 'Tag')
+ .gsub('string|Function', 'string')
+ .gsub('object', 'array')
+ .gsub(/#(\w+)/, '\1()')
+ .gsub(/Object\.<.+?>/, 'array')
+end
+
+def smart_compare_process val, type
+ val[:description] = sanitize_description val[:description]
+
+ case type
+ when :class
+ val = val.dup
+ val[:mixins].delete 'OO.EventEmitter' # JS only
+ val[:mixins].delete 'PendingElement' # JS only
+ val.delete :methods
+ val.delete :properties
+ val.delete :events
+
+ when :method
+ if val[:name] == '#constructor'
+ val[:params].delete 'element' # PHP only
+ end
+ val[:config].each_pair{|_k, v|
+ v[:description] = sanitize_description v[:description]
+ v[:type] = sanitize_description v[:type]
+ }
+ val[:params].each_pair{|_k, v|
+ v[:description] = sanitize_description v[:description]
+ v[:type] = sanitize_description v[:type]
+ }
+ if val[:return]
+ val[:return][:description] = sanitize_description val[:return][:description]
+ val[:return][:type] = sanitize_description val[:return][:type]
+ end
+
+ when :property
+ val[:description] = sanitize_description val[:description]
+ val[:type] = sanitize_description val[:type]
+
+ end
+ val
+end
+
+def smart_compare a, b, a_name, b_name, type
+ a = smart_compare_process a, type
+ b = smart_compare_process b, type
+ compare_hash a, b, a_name, b_name
+end
+
+def smart_compare_methods a, b, a_name, b_name
+ smart_compare a, b, a_name, b_name, :method
+end
+
+def smart_compare_properties a, b, a_name, b_name
+ smart_compare a, b, a_name, b_name, :property
+end
+
+def compare_hash a, b, a_name, b_name, nested=:compare_hash
+ keys = (a ? a.keys : []) + (b ? b.keys : [])
+ out = keys.to_a.sort.uniq.map do |key|
+ a_val = a ? canonicalize(a[key]) : nil
+ b_val = b ? canonicalize(b[key]) : nil
+
+ if [a_val, b_val] == [{}, []] || [a_val, b_val] == [[], {}]
+ a_val = {}
+ b_val = {}
+ end
+
+ if a_val.is_a?(Hash) && b_val.is_a?(Hash)
+ comparison_result = indent method(nested).call(a_val, b_val, a_name, b_name), 2
+ if comparison_result.strip == ''
+ "#{key}: match" if $VERBOSE
+ else
+ "#{key}: MISMATCH\n#{comparison_result}"
+ end
+ elsif a_val == b_val
+ "#{key}: match" if $VERBOSE
+ elsif a_val.nil?
+ "#{key}: #{a_name} missing"
+ elsif b_val.nil?
+ "#{key}: #{b_name} missing"
+ else
+ "#{key}: MISMATCH\n #{a_name}: #{a_val.inspect}\n #{b_name}: #{b_val.inspect}"
+ end
+ end
+ out.compact.join "\n"
+end
+
+if ARGV.empty? || ARGV == ['-h'] || ARGV == ['--help']
+ $stderr.puts "usage: ruby [-v] #{$PROGRAM_NAME} <dirA> <dirB> <nameA> <nameB>"
+ $stderr.puts " ruby #{$PROGRAM_NAME} src php JS PHP > compare.txt"
+else
+ dir_a, dir_b, name_a, name_b = ARGV
+
+ js = parse_any_path dir_a
+ php = parse_any_path dir_b
+
+ js = reindex js
+ php = reindex php
+
+ (js.keys + php.keys).sort.uniq.each do |class_name|
+ where = [js.key?(class_name) ? name_a : nil, php.key?(class_name) ? name_b : nil].compact
+ puts "\n#{class_name}: #{where.join '/'}" if $VERBOSE || where.length == 2
+
+ if where.length == 2
+ data = {
+ 'Basic:' =>
+ smart_compare(js[class_name], php[class_name], name_a, name_b, :class),
+ 'Methods:' =>
+ compare_hash(js[class_name][:methods], php[class_name][:methods], name_a, name_b, :smart_compare_methods),
+ 'Properties:' =>
+ compare_hash(js[class_name][:properties], php[class_name][:properties], name_a, name_b, :smart_compare_properties),
+ }
+ data = data
+ .select{|_k, v| v != ''}
+ .map{|k, v| "#{k}\n#{indent v, 2}" }
+ .join("\n")
+ puts indent data, 2
+ end
+ end
+end
diff --git a/www/wiki/vendor/oojs/oojs-ui/bin/docparser.rb b/www/wiki/vendor/oojs/oojs-ui/bin/docparser.rb
new file mode 100644
index 00000000..e995ec86
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/bin/docparser.rb
@@ -0,0 +1,295 @@
+require 'pp'
+require 'json'
+
+$bad_input = false
+def bad_input file, text
+ $bad_input = true
+ $stderr.puts "#{file}: unrecognized input: #{text}"
+end
+
+def parse_dir dirname
+ Dir.entries(dirname).map{|filename|
+ if filename == '.' || filename == '..'
+ nil
+ else
+ parse_any_path "#{dirname}/#{filename}"
+ end
+ }.compact.inject(:+)
+end
+
+def cleanup_class_name class_name
+ class_name.sub(/OO\.ui\./, '').sub(/mixin\./, '')
+end
+
+def extract_default_from_description item
+ m = item[:description].match(/\(default: (.+?)\)\s*?$/i)
+ return if !m
+ # modify `item` in-place
+ item[:default] = m[1]
+ item[:description] = m.pre_match
+end
+
+def parse_file filename
+ if filename !~ /\.(php|js)$/
+ return nil
+ end
+ filetype = filename[/\.(php|js)$/, 1].to_sym
+
+ text = File.read filename, encoding: 'utf-8'
+
+ # ewwww
+ # some docblocks are missing and we really need them
+ text = text.sub(/(?<!\*\/\n)^(class|trait)/, "/**\n*/\n\\1")
+
+ # find all documentation blocks, together with the following line (unless it contains another docblock)
+ docblocks = text.scan(/\/\*\*[\s\S]+?\*\/\n[ \t]*(?:(?=\/\*\*)|.*)/)
+
+ current_class = nil
+ output = []
+ previous_item = {} # dummy
+
+ docblocks.each{|d|
+ kind = nil
+ previous_item = data = {
+ name: nil,
+ description: '',
+ parent: nil,
+ mixins: [],
+ methods: [],
+ properties: [],
+ events: [],
+ params: [],
+ config: [],
+ visibility: :public,
+ type: nil,
+ }
+ valid_for_all = %w[name description].map(&:to_sym)
+ valid_per_kind = {
+ class: valid_for_all + %w[parent mixins methods properties events abstract mixin].map(&:to_sym),
+ method: valid_for_all + %w[params config return visibility static].map(&:to_sym),
+ property: valid_for_all + %w[type static].map(&:to_sym),
+ event: valid_for_all + %w[params].map(&:to_sym),
+ }
+
+ js_class_constructor = false
+ js_class_constructor_desc = ''
+ php_trait_constructor = false
+ ignore = false
+
+ comment, code_line = d.split '*/'
+ comment.split("\n").each{|comment_line|
+ next if comment_line.strip == '/**'
+ comment_line.sub!(/^[ \t]*\*[ \t]?/, '') # strip leading '*' and whitespace
+
+ m = comment_line.match(/^@(\w+)[ \t]*(.*)/)
+ if !m
+ # this is a continuation of previous item's description
+ previous_item[:description] << comment_line + "\n"
+ if filetype == :php
+ extract_default_from_description(previous_item)
+ end
+ next
+ end
+
+ keyword, content = m.captures
+
+ # handle JS class/constructor conundrum
+ if keyword == 'class' || keyword == 'constructor'
+ js_class_constructor = true
+ end
+
+ case keyword
+ when 'constructor'
+ # handle JS class/constructor conundrum
+ js_class_constructor_desc = data[:description]
+ data[:description] = ''
+ kind = :method
+ when 'class'
+ kind = :class
+ data[:name] = cleanup_class_name(content.strip) if content && !content.strip.empty?
+ when 'method'
+ kind = :method
+ when 'property', 'var'
+ kind = :property
+ m = content.match(/^\{?(.+?)\}?( .+)?$/)
+ if !m
+ bad_input filename, comment_line
+ next
+ end
+ type, description = m.captures
+ data[:type] = type
+ data[:description] = description if description
+ when 'event'
+ kind = :event
+ data[:name] = content.strip
+ when 'extends'
+ data[:parent] = cleanup_class_name(content.strip)
+ when 'mixins'
+ data[:mixins] << cleanup_class_name(content.strip)
+ when 'param'
+ case filetype
+ when :js
+ type, name, default, description = content.match(/^\{(.+?)\} \[?([\w.$]+?)(?:=(.+?))?\]?( .+)?$/).captures
+ next if type == 'Object' && name == 'config'
+ data[:params] << {name: name, type: cleanup_class_name(type), description: description || '', default: default}
+ previous_item = data[:params][-1]
+ when :php
+ type, name, config, description = content.match(/^(\S+) \&?\$(\w+)(?:\['(\w+)'\])?( .+)?$/).captures
+ next if type == 'array' && name == 'config' && !config
+ if config && name == 'config'
+ data[:config] << {name: config, type: cleanup_class_name(type), description: description || ''}
+ previous_item = data[:config][-1]
+ else
+ data[:params] << {name: name, type: cleanup_class_name(type), description: description || ''}
+ previous_item = data[:params][-1]
+ end
+ if filetype == :php
+ extract_default_from_description(previous_item)
+ end
+ end
+ when 'cfg' # JS only
+ m = content.match(/^\{(.+?)\} \[?([\w.$]+?)(?:=(.+?))?\]?( .+)?$/)
+ if !m
+ bad_input filename, comment_line
+ next
+ end
+ type, name, default, description = m.captures
+ data[:config] << {name: name, type: cleanup_class_name(type), description: description || '', default: default}
+ previous_item = data[:config][-1]
+ when 'return'
+ case filetype
+ when :js
+ m = content.match(/^\{(.+?)\}( .+)?$/)
+ when :php
+ m = content.match(/^(\S+)( .+)?$/)
+ end
+ if !m
+ bad_input filename, comment_line
+ next
+ end
+ type, description = m.captures
+ data[:return] = {type: cleanup_class_name(type), description: description || ''}
+ previous_item = data[:return]
+ when 'private'
+ data[:visibility] = :private
+ when 'protected'
+ data[:visibility] = :protected
+ when 'static'
+ data[:static] = true
+ when 'abstract'
+ data[:abstract] = true
+ when 'ignore', 'inheritdoc'
+ ignore = true
+ when 'inheritable', 'deprecated', 'singleton', 'throws',
+ 'chainable', 'fires', 'localdoc', 'member',
+ 'see', 'uses'
+ # skip
+ else
+ bad_input filename, comment_line
+ next
+ end
+ }
+
+ next if ignore
+
+ if code_line && code_line.strip != ''
+ case filetype
+ when :js
+ m = code_line.match(/(?:(static|prototype|mixin)\.)?(\w+) =/)
+ if !m
+ bad_input filename, code_line.strip
+ next
+ end
+ kind_, name = m.captures
+ data[:static] = true if kind_ == 'static'
+ kind = {'static' => :property, 'prototype' => :method}[ kind_.strip ] if kind_ && !kind
+ data[:mixin] = true if kind_ == 'mixin'
+ data[:name] ||= cleanup_class_name(name)
+ when :php
+ m = code_line.match(/
+ \s*
+ (?:(public|protected|private)\s)?
+ (?:(static)\s)?(function\s|class\s|trait\s|\$)
+ (\w+)
+ (?:\sextends\s(\w+))?
+ /x)
+ if !m
+ bad_input filename, code_line.strip
+ next
+ end
+ visibility, static, kind_, name, parent = m.captures
+ kind = {'$' => :property, 'function' => :method, 'class' => :class, 'trait' => :class}[ kind_.strip ]
+ data[:visibility] = {'private' => :private, 'protected' => :protected, 'public' => :public}[ visibility ] || :public
+ data[:mixin] = true if kind_.strip == 'trait'
+ data[:static] = true if static
+ data[:parent] = cleanup_class_name(parent) if parent
+ data[:name] ||= cleanup_class_name(name)
+ php_trait_constructor = true if kind == :method && data[:name] == 'initialize' + current_class[:name]
+ end
+ end
+
+ # handle JS class/constructor conundrum
+ if kind == :class || js_class_constructor
+ if current_class
+ output << current_class
+ end
+ current_class = data.select{|k, _v| valid_per_kind[:class].include? k }
+ current_class[:description] = js_class_constructor_desc if js_class_constructor_desc != ''
+ previous_item = current_class
+ end
+
+ # standardize
+ # (also handle fake constructors for traits)
+ if data[:name] == '__construct' || js_class_constructor || php_trait_constructor
+ data[:name] = '#constructor'
+ end
+
+ # put into the current class
+ if kind && kind != :class
+ keys = {
+ method: :methods,
+ property: :properties,
+ event: :events,
+ }
+ if current_class
+ current_class[keys[kind]] << data.select{|k, _v| valid_per_kind[kind].include? k }
+ previous_item = current_class[keys[kind]]
+ end
+ end
+ }
+
+ # this is evil, assumes we only have one class in a file, but we'd need a proper parser to do it better
+ if current_class
+ current_class[:mixins] +=
+ text.scan(/^[ \t]*use (\w+)(?: ?\{|;)/).flatten.map(&method(:cleanup_class_name))
+ end
+
+ output << current_class if current_class
+ output
+end
+
+def parse_any_path path
+ if File.directory? path
+ result = parse_dir path
+ else
+ result = parse_file path
+ end
+ if $bad_input
+ $stderr.puts 'Unrecognized inputs encountered, stopping.'
+ exit 1
+ end
+ result
+end
+
+if __FILE__ == $PROGRAM_NAME
+ if ARGV.empty? || ARGV == ['-h'] || ARGV == ['--help']
+ $stderr.puts "usage: ruby #{$PROGRAM_NAME} <files...>"
+ $stderr.puts " ruby #{$PROGRAM_NAME} src > docs-js.json"
+ $stderr.puts " ruby #{$PROGRAM_NAME} php > docs-php.json"
+ else
+ out = JSON.pretty_generate ARGV.map{|a| parse_any_path a }.inject(:+)
+ # ew
+ out = out.gsub(/\{\s+\}/, '{}').gsub(/\[\s+\]/, '[]')
+ puts out
+ end
+end
diff --git a/www/wiki/vendor/oojs/oojs-ui/bin/generate-JSPHP-for-karma.php b/www/wiki/vendor/oojs/oojs-ui/bin/generate-JSPHP-for-karma.php
new file mode 100644
index 00000000..c58e1d2d
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/bin/generate-JSPHP-for-karma.php
@@ -0,0 +1,51 @@
+<?php
+
+require_once __DIR__ . '/../vendor/autoload.php';
+
+$testSuiteJSON = file_get_contents( __DIR__ . '/../tests/JSPHP-suite.json' );
+$testSuite = json_decode( $testSuiteJSON, true );
+$testSuiteOutput = [];
+
+// @codingStandardsIgnoreStart
+function new_OOUI( $class, $config = [] ) {
+ // @codingStandardsIgnoreEnd
+ $class = "OOUI\\" . $class;
+ return new $class( $config );
+}
+// @codingStandardsIgnoreStart
+function unstub( &$value ) {
+ // @codingStandardsIgnoreEnd
+ if ( is_string( $value ) && substr( $value, 0, 13 ) === '_placeholder_' ) {
+ $value = json_decode( substr( $value, 13 ), true );
+ if ( isset( $value['config'] ) && is_array( $value['config'] ) ) {
+ array_walk_recursive( $value['config'], 'unstub' );
+ }
+ $value = new_OOUI( $value['class'], $value['config'] );
+ }
+}
+// Keep synchronized with tests/index.php
+$themes = [ 'ApexTheme', 'WikimediaUITheme' ];
+foreach ( $themes as $theme ) {
+ OOUI\Theme::setSingleton( new_OOUI( $theme ) );
+ foreach ( $testSuite as $className => $tests ) {
+ foreach ( $tests['tests'] as $test ) {
+ // Unstub placeholders
+ $config = $test['config'];
+ array_walk_recursive( $config, 'unstub' );
+ $config['infusable'] = true;
+ $instance = new_OOUI( $test['class'], $config );
+ $output = "$instance";
+ // HACK: OO.ui.infuse() expects to find this element somewhere on the page
+ if ( $instance instanceof OOUI\LabelWidget && isset( $config['input'] ) ) {
+ $output .= $config['input'];
+ }
+ $testSuiteOutput[$theme][$className][] = $output;
+ }
+ }
+}
+
+$testSuiteOutputJSON = json_encode( $testSuiteOutput, JSON_PRETTY_PRINT );
+
+echo "var testSuiteConfigs = $testSuiteJSON;\n\n";
+echo "var testSuitePHPOutput = $testSuiteOutputJSON;\n\n";
+echo file_get_contents( __DIR__ . '/../tests/JSPHP.test.karma.js' );
diff --git a/www/wiki/vendor/oojs/oojs-ui/bin/testsuitegenerator.rb b/www/wiki/vendor/oojs/oojs-ui/bin/testsuitegenerator.rb
new file mode 100644
index 00000000..db2d841b
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/bin/testsuitegenerator.rb
@@ -0,0 +1,191 @@
+require 'pp'
+require_relative 'docparser'
+
+if ARGV.empty? || ARGV == ['-h'] || ARGV == ['--help']
+ $stderr.puts "usage: ruby #{$PROGRAM_NAME} <dirA> <dirB>"
+ $stderr.puts " ruby #{$PROGRAM_NAME} src php > tests/JSPHP-suite.json"
+else
+ dir_a, dir_b = ARGV
+ js = parse_any_path dir_a
+ php = parse_any_path dir_b
+
+ class_names = (js + php).map{|c| c[:name] }.sort.uniq
+
+ tests = {}
+ classes = php.select{|c| class_names.include? c[:name] }
+
+ # classes with different PHP and JS implementations.
+ # we can still compare the PHP-infuse result to JS result, though.
+ infuse_only_classes = %w[ComboBoxInputWidget
+ RadioSelectInputWidget CheckboxMultiselectInputWidget]
+ testable_classes = classes
+ .reject{|c| c[:abstract] } # can't test abstract classes
+ .reject{|c| !c[:parent] || c[:trait] || c[:parent] == 'Theme' } # can't test abstract
+ .reject{|c| %w[Element Widget Layout Theme].include? c[:name] } # no toplevel
+
+ make_class_instance_placeholder = lambda do |klass, config|
+ '_placeholder_' + {
+ class: klass,
+ config: config
+ }.to_json
+ end
+
+ make_htmlsnippet_placeholder = make_class_instance_placeholder.curry['HtmlSnippet']
+
+ # values to test for each type
+ expandos = {
+ 'null' => [nil],
+ 'int' => [0, -1, 300], # PHP code
+ 'number' => [0, -1, 300], # JS code
+ 'bool' => [true, false], # PHP code
+ 'boolean' => [true, false], # JS code
+ 'string' => ['Foo bar', '<b>HTML?</b>', '', ' '],
+ 'HtmlSnippet' => ['Foo bar', '<b>HTML?</b>', ''].map(&make_htmlsnippet_placeholder),
+ }
+
+ # Values to test for specific config options, when not all values of given type are valid.
+ # Empty array will result in no tests for this config option being generated.
+ sensible_values = {
+ 'align' => %w[top inline left],
+ 'href' => ['http://example.com/'],
+ ['TextInputWidget', 'type'] => %w[text number password foo],
+ ['ButtonInputWidget', 'type'] => %w[button submit foo],
+ ['FieldLayout', 'errors'] => expandos['string'].map{|v| [v] }, # treat as string[]
+ ['FieldLayout', 'notices'] => expandos['string'].map{|v| [v] }, # treat as string[]
+ 'type' => %w[text button],
+ 'method' => %w[GET POST],
+ 'target' => ['_blank'],
+ 'accessKey' => ['k'],
+ 'tabIndex' => [-1, 0, 100, '42'],
+ 'maxLength' => [100],
+ 'icon' => ['image'],
+ 'indicator' => ['down'],
+ 'flags' => %w[progressive primary],
+ 'progress' => [0, 50, 100, false],
+ 'options' => [
+ [],
+ [ { 'data' => 'a', 'label' => 'A' } ],
+ [ { 'data' => 'a' }, { 'data' => 'b' } ],
+ [ { 'data' => 'a', 'label' => 'A' }, { 'data' => 'b', 'label' => 'B' } ],
+ ],
+ 'value' => ['', 'a', 'b', '<b>HTML?</b>'],
+ # deprecated, makes test logs spammy
+ 'multiline' => [],
+ # usually makes no sense in JS
+ 'autofocus' => [],
+ # too simple to test?
+ 'action' => [],
+ 'enctype' => [],
+ 'name' => [],
+ # different PHP and JS implementations
+ ['FieldLayout', 'help'] => [],
+ ['ActionFieldLayout', 'help'] => [],
+ ['FieldsetLayout', 'help'] => [],
+ # the dynamic 'clear' indicator in JS messes everything up
+ ['SearchInputWidget', 'value'] => [],
+ ['SearchInputWidget', 'indicator'] => [],
+ ['SearchInputWidget', 'required'] => [],
+ ['SearchInputWidget', 'disabled'] => [],
+ # these are defined by Element and would bloat the tests
+ 'classes' => [],
+ 'id' => [],
+ 'content' => [],
+ 'text' => [],
+ }
+
+ find_class = lambda do |klass|
+ return classes.find{|c| c[:name] == klass }
+ end
+
+ expand_types_to_values = lambda do |types|
+ # For abstract classes (not "testable"), test a few different subclasses instead
+ if types.delete 'Widget'
+ types.push 'ButtonWidget', 'TextInputWidget'
+ end
+ if types.delete 'InputWidget'
+ types.push 'CheckboxInputWidget', 'TextInputWidget'
+ end
+
+ return types.map{|t|
+ as_array = true if t.sub! '[]', ''
+ if expandos[t]
+ # Primitive. Run tests with the provided values.
+ vals = expandos[t]
+ elsif testable_classes.find{|c| c[:name] == t }
+ # OOUI object. Test suite will instantiate one and run the test with it.
+ constructor = find_class.call(t)[:methods].find{|m| m[:name] == '#constructor' }
+ params = constructor ? (constructor[:params] || []) : []
+ config = params.map{|config_option|
+ types = config_option[:type].split '|'
+ values = expand_types_to_values.call(types)
+ { config_option[:name] => values[0] }
+ }
+ vals = [
+ make_class_instance_placeholder.call( t, config.inject({}, :merge) )
+ ]
+ else
+ # We don't know how to test this. The empty value will result in no
+ # tests being generated for this combination of config values.
+ vals = []
+ end
+ as_array ? vals.map{|v| [v] } : vals
+ }.inject(:+)
+ end
+
+ find_config_sources = lambda do |klass_name|
+ return [] unless klass_name
+ klass_names = [klass_name]
+ while klass_name
+ klass = find_class.call(klass_name)
+ break unless klass
+ klass_names +=
+ find_config_sources.call(klass[:parent]) +
+ klass[:mixins].map(&find_config_sources).flatten
+ klass_name = klass[:parent]
+ end
+ return klass_names.uniq
+ end
+
+ testable_classes.each do |klass|
+ class_name = klass[:name]
+ tests[class_name] = {
+ infuseonly: !infuse_only_classes.index(class_name).nil?,
+ tests: [],
+ }
+
+ config_sources = find_config_sources.call(class_name)
+ .map{|c| find_class.call(c)[:methods].find{|m| m[:name] == '#constructor' } }
+ config = config_sources.compact.map{|c| c[:config] }.compact.inject([], :+)
+ constructor = klass[:methods].find{|m| m[:name] == '#constructor' }
+ required_config = constructor ? (constructor[:params] || []) : []
+
+ # generate every possible configuration of configuration option sets
+ maxlength = [config.length, 2].min
+ config_combinations = (0..maxlength).map{|l| config.combination(l).to_a }.inject(:+)
+ # for each set, generate all possible values to use based on option's type
+ config_combinations = config_combinations.map{|config_comb|
+ config_comb += required_config
+ expanded = config_comb.map{|config_option|
+ types = config_option[:type].split '|'
+ values =
+ sensible_values[ [ class_name, config_option[:name] ] ] ||
+ sensible_values[ config_option[:name] ] ||
+ expand_types_to_values.call(types)
+ values.map{|v| config_option.dup.merge(value: v) }
+ }
+ expanded.empty? ? [ [] ] : expanded[0].product(*expanded[1..-1])
+ }.inject(:concat).uniq
+
+ config_combinations.each do |config_comb|
+ tests[class_name][:tests] << {
+ class: class_name,
+ config: Hash[ config_comb.map{|c| [ c[:name], c[:value] ] } ]
+ }
+ end
+ end
+
+ $stderr.puts "Generated #{tests.values.map{|a| a[:tests].length}.inject(:+)} test cases."
+
+ $stderr.puts tests.map{|class_name, class_tests| "* #{class_name}: #{class_tests[:tests].length}" }
+ puts JSON.pretty_generate tests
+end
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/BookletDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/BookletDialog.js
new file mode 100644
index 00000000..24365715
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/BookletDialog.js
@@ -0,0 +1,70 @@
+Demo.BookletDialog = function DemoBookletDialog( config ) {
+ Demo.BookletDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.BookletDialog, OO.ui.ProcessDialog );
+Demo.BookletDialog.static.title = 'Booklet dialog';
+Demo.BookletDialog.static.actions = [
+ { action: 'save', label: 'Done', flags: [ 'primary', 'progressive' ] },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] }
+];
+Demo.BookletDialog.prototype.getBodyHeight = function () {
+ return 250;
+};
+Demo.BookletDialog.prototype.initialize = function () {
+ var dialog;
+ Demo.BookletDialog.parent.prototype.initialize.apply( this, arguments );
+
+ dialog = this;
+
+ function changePage( direction ) {
+ var pageIndex = dialog.pages.indexOf( dialog.bookletLayout.getCurrentPage() );
+ pageIndex = ( dialog.pages.length + pageIndex + direction ) % dialog.pages.length;
+ dialog.bookletLayout.setPage( dialog.pages[ pageIndex ].getName() );
+ }
+
+ this.navigationField = new OO.ui.FieldLayout(
+ new OO.ui.ButtonGroupWidget( {
+ items: [
+ new OO.ui.ButtonWidget( {
+ data: 'previous',
+ icon: 'previous'
+ } ).on( 'click', function () {
+ changePage( -1 );
+ } ),
+ new OO.ui.ButtonWidget( {
+ data: 'next',
+ icon: 'next'
+ } ).on( 'click', function () {
+ changePage( 1 );
+ } )
+ ]
+ } ),
+ {
+ label: 'Change page',
+ align: 'top'
+ }
+ );
+
+ this.bookletLayout = new OO.ui.BookletLayout();
+ this.pages = [
+ new Demo.SamplePage( 'page-1', { label: 'Page 1', icon: 'window' } ),
+ new Demo.SamplePage( 'page-2', { label: 'Page 2', icon: 'window' } ),
+ new Demo.SamplePage( 'page-3', { label: 'Page 3', icon: 'window' } )
+ ];
+ this.bookletLayout.addPages( this.pages );
+ this.bookletLayout.connect( this, { set: 'onBookletLayoutSet' } );
+ this.bookletLayout.setPage( 'page-1' );
+
+ this.$body.append( this.bookletLayout.$element );
+};
+Demo.BookletDialog.prototype.getActionProcess = function ( action ) {
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ this.close( { action: action } );
+ }, this );
+ }
+ return Demo.BookletDialog.parent.prototype.getActionProcess.call( this, action );
+};
+Demo.BookletDialog.prototype.onBookletLayoutSet = function ( page ) {
+ page.$element.append( this.navigationField.$element );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/BrokenDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/BrokenDialog.js
new file mode 100644
index 00000000..40739a84
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/BrokenDialog.js
@@ -0,0 +1,61 @@
+Demo.BrokenDialog = function DemoBrokenDialog( config ) {
+ Demo.BrokenDialog.parent.call( this, config );
+ this.broken = false;
+};
+OO.inheritClass( Demo.BrokenDialog, OO.ui.ProcessDialog );
+Demo.BrokenDialog.static.title = 'Broken dialog';
+Demo.BrokenDialog.static.actions = [
+ { action: 'save', label: 'Save', flags: [ 'primary', 'progressive' ] },
+ { action: 'delete', label: 'Delete', flags: 'destructive' },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] }
+];
+Demo.BrokenDialog.prototype.getBodyHeight = function () {
+ return 250;
+};
+Demo.BrokenDialog.prototype.initialize = function () {
+ Demo.BrokenDialog.parent.prototype.initialize.apply( this, arguments );
+ this.content = new OO.ui.PanelLayout( { padded: true } );
+ this.fieldset = new OO.ui.FieldsetLayout( {
+ label: 'Dialog with error handling',
+ icon: 'alert'
+ } );
+ this.description = new OO.ui.LabelWidget( {
+ label: 'Deleting will fail and will not be recoverable. ' +
+ 'Saving will fail the first time, but succeed the second time.'
+ } );
+ this.fieldset.addItems( [ this.description ] );
+ this.content.$element.append( this.fieldset.$element );
+ this.$body.append( this.content.$element );
+};
+Demo.BrokenDialog.prototype.getSetupProcess = function ( data ) {
+ return Demo.BrokenDialog.parent.prototype.getSetupProcess.call( this, data )
+ .next( function () {
+ this.broken = true;
+ }, this );
+};
+Demo.BrokenDialog.prototype.getActionProcess = function ( action ) {
+ return Demo.BrokenDialog.parent.prototype.getActionProcess.call( this, action )
+ .next( function () {
+ return 1000;
+ }, this )
+ .next( function () {
+ var state;
+
+ if ( action === 'save' ) {
+ if ( this.broken ) {
+ this.broken = false;
+ return new OO.ui.Error( 'Server did not respond' );
+ }
+ } else if ( action === 'delete' ) {
+ return new OO.ui.Error( 'Permission denied', { recoverable: false } );
+ }
+
+ state = this.close( { action: action } );
+ if ( action === 'save' ) {
+ // Return a promise that is resolved when the dialog is closed,
+ // so that it remains in "pending" state while closing
+ return state.closed;
+ }
+ return Demo.BrokenDialog.parent.prototype.getActionProcess.call( this, action );
+ }, this );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.css b/www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.css
new file mode 100644
index 00000000..29f09da4
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.css
@@ -0,0 +1,3 @@
+.demo-buttonStyleShowcaseWidget .oo-ui-buttonWidget {
+ margin-bottom: 0.5em;
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.js
new file mode 100644
index 00000000..9f9573e3
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.js
@@ -0,0 +1,74 @@
+Demo.ButtonStyleShowcaseWidget = function DemoButtonStyleShowcaseWidget( config ) {
+ var widget = this;
+
+ Demo.ButtonStyleShowcaseWidget.parent.call( this, config );
+
+ this.$element.addClass( 'demo-buttonStyleShowcaseWidget' );
+
+ $.each( this.constructor.static.styles, function ( i, style ) {
+ var $buttonRow = $( '<div>' );
+ $.each( widget.constructor.static.states, function ( j, state ) {
+ $buttonRow.append(
+ new OO.ui.ButtonWidget( $.extend( {}, style, state ) ).$element
+ );
+ } );
+ widget.$element.append( $buttonRow );
+ } );
+};
+
+OO.inheritClass( Demo.ButtonStyleShowcaseWidget, OO.ui.Widget );
+
+Demo.ButtonStyleShowcaseWidget.static.styles = [
+ {},
+ {
+ flags: [ 'progressive' ]
+ },
+ {
+ flags: [ 'destructive' ]
+ },
+ {
+ flags: [ 'primary', 'progressive' ]
+ },
+ {
+ flags: [ 'primary', 'destructive' ]
+ }
+];
+
+Demo.ButtonStyleShowcaseWidget.static.states = [
+ {
+ label: 'Button'
+ },
+ {
+ label: 'Button',
+ icon: 'tag'
+ },
+ {
+ label: 'Button',
+ icon: 'tag',
+ indicator: 'down'
+ },
+ {
+ icon: 'tag',
+ title: 'Title text'
+ },
+ {
+ indicator: 'down'
+ },
+ {
+ icon: 'tag',
+ indicator: 'down'
+ },
+ {
+ label: 'Button',
+ disabled: true
+ },
+ {
+ icon: 'tag',
+ title: 'Title text',
+ disabled: true
+ },
+ {
+ indicator: 'down',
+ disabled: true
+ }
+];
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.php b/www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.php
new file mode 100644
index 00000000..7d2f45e4
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/ButtonStyleShowcaseWidget.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace Demo;
+
+use OOUI;
+
+class ButtonStyleShowcaseWidget extends OOUI\Widget {
+
+ protected static $styles = [
+ [],
+ [
+ 'flags' => [ 'progressive' ],
+ ],
+ [
+ 'flags' => [ 'destructive' ],
+ ],
+ [
+ 'flags' => [ 'primary', 'progressive' ],
+ ],
+ [
+ 'flags' => [ 'primary', 'destructive' ],
+ ],
+ ];
+ protected static $states = [
+ [
+ 'label' => 'Button',
+ ],
+ [
+ 'label' => 'Button',
+ 'icon' => 'tag',
+ ],
+ [
+ 'label' => 'Button',
+ 'icon' => 'tag',
+ 'indicator' => 'down',
+ ],
+ [
+ 'icon' => 'tag',
+ 'title' => "Title text",
+ ],
+ [
+ 'indicator' => 'down',
+ ],
+ [
+ 'icon' => 'tag',
+ 'indicator' => 'down',
+ ],
+ [
+ 'label' => 'Button',
+ 'disabled' => true,
+ ],
+ [
+ 'icon' => 'tag',
+ 'title' => "Title text",
+ 'disabled' => true,
+ ],
+ [
+ 'indicator' => 'down',
+ 'disabled' => true,
+ ],
+ ];
+
+ public function __construct( array $config = [] ) {
+ parent::__construct( $config );
+
+ $this->addClasses( [ 'demo-buttonStyleShowcaseWidget' ] );
+
+ foreach ( self::$styles as $style ) {
+ $buttonRow = new OOUI\Tag( 'div' );
+ foreach ( self::$states as $state ) {
+ $buttonRow->appendContent(
+ new OOUI\ButtonWidget( array_merge( $style, $state ) )
+ );
+ }
+ $this->appendContent( $buttonRow );
+ }
+ }
+
+ protected function getJavaScriptClassName() {
+ return 'Demo.ButtonStyleShowcaseWidget';
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/CapsuleNumberPopupMultiselectWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/CapsuleNumberPopupMultiselectWidget.js
new file mode 100644
index 00000000..5cf38266
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/CapsuleNumberPopupMultiselectWidget.js
@@ -0,0 +1,27 @@
+Demo.CapsuleNumberPopupMultiselectWidget = function DemoCapsuleNumberPopupMultiselectWidget( config ) {
+ // Properties
+ this.capsulePopupWidget = new OO.ui.NumberInputWidget( {
+ isInteger: true
+ } );
+
+ // Parent constructor
+ Demo.CapsuleNumberPopupMultiselectWidget.parent.call( this, $.extend( {}, config, {
+ allowArbitrary: true,
+ popup: {}
+ } ) );
+
+ // Events
+ this.capsulePopupWidget.connect( this, { enter: 'onPopupEnter' } );
+
+ // Initialization
+ this.popup.$body.append( this.capsulePopupWidget.$element );
+};
+
+OO.inheritClass( Demo.CapsuleNumberPopupMultiselectWidget, OO.ui.CapsuleMultiselectWidget );
+
+Demo.CapsuleNumberPopupMultiselectWidget.prototype.onPopupEnter = function () {
+ if ( !isNaN( this.capsulePopupWidget.getNumericValue() ) ) {
+ this.addItemsFromData( [ this.capsulePopupWidget.getNumericValue() ] );
+ this.capsulePopupWidget.setValue( '' );
+ }
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/ContinuousOutlinedBookletDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/ContinuousOutlinedBookletDialog.js
new file mode 100644
index 00000000..d37412e6
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/ContinuousOutlinedBookletDialog.js
@@ -0,0 +1,58 @@
+Demo.ContinuousOutlinedBookletDialog = function DemoContinuousOutlinedBookletDialog( config ) {
+ Demo.ContinuousOutlinedBookletDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.ContinuousOutlinedBookletDialog, OO.ui.ProcessDialog );
+Demo.ContinuousOutlinedBookletDialog.static.title = 'Continuous outlined booklet dialog';
+Demo.ContinuousOutlinedBookletDialog.static.actions = [
+ { action: 'save', label: 'Done', flags: [ 'primary', 'progressive' ] },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] }
+];
+Demo.ContinuousOutlinedBookletDialog.prototype.getBodyHeight = function () {
+ return 250;
+};
+Demo.ContinuousOutlinedBookletDialog.prototype.initialize = function () {
+ var lipsum;
+ Demo.ContinuousOutlinedBookletDialog.parent.prototype.initialize.apply( this, arguments );
+ this.bookletLayout = new OO.ui.BookletLayout( {
+ outlined: true,
+ continuous: true
+ } );
+ lipsum = [
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eleifend justo nec erat tempus, quis aliquet augue aliquam. Sed rutrum odio in tellus pharetra, ut mollis est fermentum. ' +
+ 'Sed egestas dolor libero, a aliquet sem finibus eu. Morbi dolor nisl, pulvinar vitae maximus sed, lacinia eu ipsum. Fusce rutrum placerat massa, vel vehicula nisi viverra nec. ' +
+ 'Nam at turpis vel nisi efficitur tempor. Interdum et malesuada fames ac ante ipsum primis in faucibus. Morbi aliquam pulvinar fermentum. Maecenas rutrum accumsan lorem ac sagittis. ' +
+ 'Praesent id nunc gravida, iaculis odio eu, maximus ligula. Praesent ut tellus mollis, pharetra orci vitae, interdum lacus. Nulla sodales lacus eget libero pellentesque tempor.',
+ 'Ut a metus elementum, eleifend velit et, malesuada enim.',
+ 'Aenean sem eros, rutrum vitae pulvinar at, vulputate id quam. Quisque tincidunt, ligula pulvinar consequat tempor, tellus erat lobortis nisl, non euismod diam nisl ut libero. Etiam mollis, ' +
+ 'risus a tincidunt efficitur, ipsum justo ullamcorper sem, id gravida dui lacus quis turpis. In consectetur tincidunt elit in mollis. Sed nec ultricies turpis, at dictum risus. Curabitur ipsum diam, ' +
+ 'aliquet sit amet ante eu, congue cursus magna. Donec at lectus in nulla ornare faucibus. Vestibulum mattis massa eu convallis convallis. Sed tristique ut quam non eleifend. Nunc aliquam, nisi non ' +
+ 'posuere dictum, est nunc mollis nisl.',
+ 'Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce laoreet mi mi, nec tempor erat posuere malesuada. Nam dignissim at nisl ac aliquet. In fermentum ' +
+ 'mauris et tellus fermentum rutrum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam hendrerit diam mauris, id rutrum justo malesuada nec. Duis ',
+ 'Ut fringilla enim nec augue rutrum, nec vestibulum orci sollicitudin. Donec eget ex tincidunt augue ullamcorper efficitur at sed odio. Praesent ac interdum elit. Suspendisse blandit feugiat pulvinar. '
+ ];
+ this.pages = [
+ new Demo.SamplePage( 'page1', { label: 'Level 0', icon: 'window', level: 0, content: [ $( '<h3>' ).text( 'Page 1' ), lipsum[ 0 ] ] } ),
+ new Demo.SamplePage( 'page2', { label: 'Level 1', icon: 'window', level: 1, content: [ $( '<h3>' ).text( 'Page 2' ), lipsum[ 1 ] ] } ),
+ new Demo.SamplePage( 'page3', { label: 'Level 2', icon: 'window', level: 2, content: [ $( '<h3>' ).text( 'Page 3' ), lipsum[ 2 ] ] } ),
+ new Demo.SamplePage( 'page4', { label: 'Level 1', icon: 'window', level: 1, content: [ $( '<h3>' ).text( 'Page 4' ), lipsum[ 3 ] ] } ),
+ new Demo.SamplePage( 'page5', { label: 'Level 2', icon: 'window', level: 2, content: [ $( '<h3>' ).text( 'Page 5' ), lipsum[ 4 ] ] } )
+ ];
+
+ this.bookletLayout.addPages( this.pages );
+ this.$body.append( this.bookletLayout.$element );
+};
+Demo.ContinuousOutlinedBookletDialog.prototype.getActionProcess = function ( action ) {
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ this.close( { action: action } );
+ }, this );
+ }
+ return Demo.ContinuousOutlinedBookletDialog.parent.prototype.getActionProcess.call( this, action );
+};
+Demo.ContinuousOutlinedBookletDialog.prototype.getSetupProcess = function ( data ) {
+ return Demo.ContinuousOutlinedBookletDialog.parent.prototype.getSetupProcess.call( this, data )
+ .next( function () {
+ this.bookletLayout.setPage( 'page1' );
+ }, this );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/DelayedReadyProcessDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DelayedReadyProcessDialog.js
new file mode 100644
index 00000000..c7d185c3
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DelayedReadyProcessDialog.js
@@ -0,0 +1,13 @@
+Demo.DelayedReadyProcessDialog = function DemoDelayedReadyProcessDialog( config ) {
+ Demo.DelayedReadyProcessDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.DelayedReadyProcessDialog, Demo.SimpleDialog );
+Demo.DelayedReadyProcessDialog.prototype.getReadyProcess = function () {
+ return Demo.DelayedReadyProcessDialog.parent.prototype.getReadyProcess.call( this ).next( function () {
+ var deferred = $.Deferred();
+ setTimeout( function () {
+ deferred.resolve();
+ }, 2000 );
+ return deferred.promise();
+ } );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/DialogWithDropdowns.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DialogWithDropdowns.js
new file mode 100644
index 00000000..1566af2d
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DialogWithDropdowns.js
@@ -0,0 +1,218 @@
+Demo.DialogWithDropdowns = function DemoDialogWithDropdowns( config ) {
+ Demo.DialogWithDropdowns.parent.call( this, config );
+};
+OO.inheritClass( Demo.DialogWithDropdowns, OO.ui.ProcessDialog );
+Demo.DialogWithDropdowns.static.title = 'Dialog with dropdowns ($overlay test)';
+Demo.DialogWithDropdowns.static.actions = [
+ { action: 'save', label: 'Done', flags: [ 'primary', 'progressive' ] },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] }
+];
+Demo.DialogWithDropdowns.prototype.getBodyHeight = function () {
+ return 300;
+};
+Demo.DialogWithDropdowns.prototype.initialize = function () {
+ var
+ loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, ' +
+ 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\u200E',
+ $spacer = $( '<div>' ).height( 350 );
+ Demo.DialogWithDropdowns.parent.prototype.initialize.apply( this, arguments );
+ this.bookletLayout = new OO.ui.BookletLayout( {
+ outlined: true
+ } );
+ this.pages = [
+ new Demo.SamplePage( 'info', {
+ label: 'Information',
+ icon: 'info',
+ content: [
+ 'This is a test of various kinds of dropdown menus and their $overlay config option. ',
+ 'Entries without any icon use a correctly set $overlay and their menus should be able to extend outside of this small dialog. ',
+ 'Entries with the ', new OO.ui.IconWidget( { icon: 'alert' } ), ' icon do not, and their menus should be clipped to the dialog\'s boundaries. ',
+ 'All dropdown menus should stick to the widget proper, even when scrolling while the menu is open.'
+ ]
+ } ),
+ new Demo.SamplePage( 'dropdown', {
+ label: 'DropdownWidget',
+ content: [ $spacer.clone(), new OO.ui.DropdownWidget( {
+ $overlay: this.$overlay,
+ menu: {
+ items: this.makeItems()
+ }
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'dropdown2', {
+ label: 'DropdownWidget',
+ icon: 'alert',
+ content: [ $spacer.clone(), new OO.ui.DropdownWidget( {
+ menu: {
+ items: this.makeItems()
+ }
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'combobox', {
+ label: 'ComboBoxInputWidget',
+ content: [ $spacer.clone(), new OO.ui.ComboBoxInputWidget( {
+ $overlay: this.$overlay,
+ menu: {
+ items: this.makeItems()
+ }
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'combobox2', {
+ label: 'ComboBoxInputWidget',
+ icon: 'alert',
+ content: [ $spacer.clone(), new OO.ui.ComboBoxInputWidget( {
+ menu: {
+ items: this.makeItems()
+ }
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'lookup', {
+ label: 'LookupElement',
+ content: [ $spacer.clone(), new Demo.NumberLookupTextInputWidget( {
+ $overlay: this.$overlay
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'lookup2', {
+ label: 'LookupElement',
+ icon: 'alert',
+ content: [ $spacer.clone(), new Demo.NumberLookupTextInputWidget(), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'fieldsetandfield', {
+ label: 'FieldsetLayout and FieldLayout',
+ content: [ $spacer.clone(), new OO.ui.FieldsetLayout( {
+ $overlay: this.$overlay,
+ label: 'Fieldset',
+ help: loremIpsum,
+ items: [
+ new OO.ui.FieldLayout( new OO.ui.CheckboxInputWidget(), {
+ $overlay: this.$overlay,
+ align: 'inline',
+ label: 'Field',
+ help: loremIpsum
+ } )
+ ]
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'fieldsetandfield2', {
+ label: 'FieldsetLayout and FieldLayout',
+ icon: 'alert',
+ content: [ $spacer.clone(), new OO.ui.FieldsetLayout( {
+ label: 'Fieldset',
+ help: loremIpsum,
+ items: [
+ new OO.ui.FieldLayout( new OO.ui.CheckboxInputWidget(), {
+ align: 'inline',
+ label: 'Field',
+ help: loremIpsum
+ } )
+ ]
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'popupbutton', {
+ label: 'PopupButtonWidget',
+ content: [ $spacer.clone(), new OO.ui.PopupButtonWidget( {
+ $overlay: this.$overlay,
+ label: 'Popup button',
+ popup: {
+ padded: true,
+ $content: this.makeContents()
+ }
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'popupbutton2', {
+ label: 'PopupButtonWidget',
+ icon: 'alert',
+ content: [ $spacer.clone(), new OO.ui.PopupButtonWidget( {
+ label: 'Popup button',
+ popup: {
+ padded: true,
+ $content: this.makeContents()
+ }
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'popupbuttonhoriz', {
+ label: 'PopupButtonWidget (horizontal)',
+ content: [ $spacer.clone(), new OO.ui.PopupButtonWidget( {
+ $overlay: this.$overlay,
+ label: 'Popup button',
+ popup: {
+ position: 'after',
+ height: 200,
+ width: 200,
+ padded: true,
+ $content: this.makeContents()
+ }
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'popupbuttonhoriz2', {
+ label: 'PopupButtonWidget (horizontal)',
+ icon: 'alert',
+ content: [ $spacer.clone(), new OO.ui.PopupButtonWidget( {
+ label: 'Popup button',
+ popup: {
+ position: 'after',
+ height: 200,
+ width: 200,
+ padded: true,
+ $content: this.makeContents()
+ }
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'capsulemenu', {
+ label: 'CapsuleMultiselectWidget (menu)',
+ content: [ $spacer.clone(), new OO.ui.CapsuleMultiselectWidget( {
+ $overlay: this.$overlay,
+ menu: {
+ items: this.makeItems()
+ }
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'capsulemenu2', {
+ label: 'CapsuleMultiselectWidget (menu)',
+ icon: 'alert',
+ content: [ $spacer.clone(), new OO.ui.CapsuleMultiselectWidget( {
+ menu: {
+ items: this.makeItems()
+ }
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'capsulepopup', {
+ label: 'CapsuleMultiselectWidget (popup)',
+ content: [ $spacer.clone(), new Demo.CapsuleNumberPopupMultiselectWidget( {
+ $overlay: this.$overlay
+ } ), $spacer.clone() ]
+ } ),
+ new Demo.SamplePage( 'capsulepopup2', {
+ label: 'CapsuleMultiselectWidget (popup)',
+ icon: 'alert',
+ content: [ $spacer.clone(), new Demo.CapsuleNumberPopupMultiselectWidget(), $spacer.clone() ]
+ } )
+ ];
+ this.bookletLayout.on( 'set', function ( page ) {
+ page.$element[ 0 ].scrollTop = 325;
+ } );
+ this.bookletLayout.addPages( this.pages );
+ this.$body.append( this.bookletLayout.$element );
+};
+Demo.DialogWithDropdowns.prototype.makeItems = function () {
+ return [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ].map( function ( val ) {
+ return new OO.ui.MenuOptionWidget( {
+ data: val,
+ label: String( val )
+ } );
+ } );
+};
+Demo.DialogWithDropdowns.prototype.makeContents = function () {
+ var loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, ' +
+ 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\u200E';
+ return $( '<p>' ).text( loremIpsum );
+};
+
+Demo.DialogWithDropdowns.prototype.getActionProcess = function ( action ) {
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ this.close( { action: action } );
+ }, this );
+ }
+ return Demo.DialogWithDropdowns.parent.prototype.getActionProcess.call( this, action );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/DialogWithPopupAndDropdown.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DialogWithPopupAndDropdown.js
new file mode 100644
index 00000000..edd30ef2
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DialogWithPopupAndDropdown.js
@@ -0,0 +1,70 @@
+Demo.DialogWithPopupAndDropdown = function DemoDialogWithPopupAndDropdown( config ) {
+ Demo.DialogWithPopupAndDropdown.parent.call( this, config );
+};
+OO.inheritClass( Demo.DialogWithPopupAndDropdown, OO.ui.ProcessDialog );
+Demo.DialogWithPopupAndDropdown.static.title = 'Dialog with popup and dropdown (ClippableElement test)';
+Demo.DialogWithPopupAndDropdown.static.actions = [
+ { action: 'save', label: 'Done', flags: [ 'primary', 'progressive' ] },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] }
+];
+Demo.DialogWithPopupAndDropdown.prototype.getBodyHeight = function () {
+ return 300;
+};
+Demo.DialogWithPopupAndDropdown.prototype.initialize = function () {
+ var $spacer = $( '<div>' ).height( 240 );
+ Demo.DialogWithPopupAndDropdown.parent.prototype.initialize.apply( this, arguments );
+ this.bookletLayout = new OO.ui.BookletLayout( {
+ outlined: true
+ } );
+ this.pages = [
+ new Demo.SamplePage( 'info', {
+ label: 'Information',
+ icon: 'info',
+ content: [
+ 'Widgets that don\'t use $overlay get clipped at the bottom of their container. ',
+ 'This is a test of two such cases'
+ ]
+ } ),
+ new Demo.SamplePage( 'dropdownbottom', {
+ label: 'DropdownWidget at bottom',
+ content: [ $spacer.clone(), new OO.ui.DropdownWidget( {
+ menu: {
+ items: this.makeItems()
+ }
+ } ) ]
+ } ),
+ new Demo.SamplePage( 'popupbottom', {
+ label: 'Popup at bottom',
+ content: [ $spacer.clone(), new OO.ui.PopupButtonWidget( {
+ icon: 'info',
+ label: 'Popup here',
+ framed: false,
+ popup: {
+ head: true,
+ label: 'More information',
+ $content: $( '<p>Extra information here.</p>' ),
+ padded: true
+ }
+ } ) ]
+ } )
+ ];
+ this.bookletLayout.addPages( this.pages );
+ this.$body.append( this.bookletLayout.$element );
+};
+Demo.DialogWithPopupAndDropdown.prototype.makeItems = function () {
+ return [ 0, 1, 2, 3, 4 ].map( function ( val ) {
+ return new OO.ui.MenuOptionWidget( {
+ data: val,
+ label: String( val )
+ } );
+ } );
+};
+
+Demo.DialogWithPopupAndDropdown.prototype.getActionProcess = function ( action ) {
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ this.close( { action: action } );
+ }, this );
+ }
+ return Demo.DialogWithPopupAndDropdown.parent.prototype.getActionProcess.call( this, action );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableGroupWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableGroupWidget.js
new file mode 100644
index 00000000..aa13875c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableGroupWidget.js
@@ -0,0 +1,19 @@
+/**
+ * Draggable group widget containing drag/drop items
+ *
+ * @param {Object} [config] Configuration options
+ */
+Demo.DraggableGroupWidget = function DemoDraggableGroupWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ Demo.DraggableGroupWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.DraggableGroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );
+};
+
+/* Setup */
+OO.inheritClass( Demo.DraggableGroupWidget, OO.ui.Widget );
+OO.mixinClass( Demo.DraggableGroupWidget, OO.ui.mixin.DraggableGroupElement );
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableHandledItemWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableHandledItemWidget.js
new file mode 100644
index 00000000..9ded7b50
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableHandledItemWidget.js
@@ -0,0 +1,19 @@
+/**
+ * Drag/drop items with custom handle
+ *
+ * @param {Object} [config] Configuration options
+ */
+Demo.DraggableHandledItemWidget = function DemoDraggableHandledItemWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ Demo.DraggableHandledItemWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.DraggableElement.call( this, $.extend( { $handle: this.$icon }, config ) );
+};
+
+/* Setup */
+OO.inheritClass( Demo.DraggableHandledItemWidget, Demo.SimpleWidget );
+OO.mixinClass( Demo.DraggableHandledItemWidget, OO.ui.mixin.DraggableElement );
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableItemWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableItemWidget.js
new file mode 100644
index 00000000..ef5488a3
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DraggableItemWidget.js
@@ -0,0 +1,19 @@
+/**
+ * Drag/drop items
+ *
+ * @param {Object} [config] Configuration options
+ */
+Demo.DraggableItemWidget = function DemoDraggableItemWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ Demo.DraggableItemWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.DraggableElement.call( this, config );
+};
+
+/* Setup */
+OO.inheritClass( Demo.DraggableItemWidget, Demo.SimpleWidget );
+OO.mixinClass( Demo.DraggableItemWidget, OO.ui.mixin.DraggableElement );
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/DynamicLabelTextInputWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DynamicLabelTextInputWidget.js
new file mode 100644
index 00000000..be649fda
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/DynamicLabelTextInputWidget.js
@@ -0,0 +1,17 @@
+Demo.DynamicLabelTextInputWidget = function DemoDynamicLabelTextInputWidget( config ) {
+ // Configuration initialization
+ config = $.extend( { getLabelText: $.noop }, config );
+ // Parent constructor
+ Demo.DynamicLabelTextInputWidget.parent.call( this, config );
+ // Properties
+ this.getLabelText = config.getLabelText;
+ // Events
+ this.connect( this, { change: 'onChange' } );
+ // Initialization
+ this.setLabel( this.getLabelText( this.getValue() ) );
+};
+OO.inheritClass( Demo.DynamicLabelTextInputWidget, OO.ui.TextInputWidget );
+
+Demo.DynamicLabelTextInputWidget.prototype.onChange = function ( value ) {
+ this.setLabel( this.getLabelText( value ) );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/FailedReadyProcessDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/FailedReadyProcessDialog.js
new file mode 100644
index 00000000..67d718ff
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/FailedReadyProcessDialog.js
@@ -0,0 +1,9 @@
+Demo.FailedReadyProcessDialog = function DemoFailedReadyProcessDialog( config ) {
+ Demo.FailedReadyProcessDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.FailedReadyProcessDialog, Demo.SimpleDialog );
+Demo.FailedReadyProcessDialog.prototype.getReadyProcess = function () {
+ return Demo.FailedReadyProcessDialog.parent.prototype.getReadyProcess.call( this ).next( function () {
+ return $.Deferred().reject().promise();
+ } );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/FailedSetupProcessDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/FailedSetupProcessDialog.js
new file mode 100644
index 00000000..7cba2d48
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/FailedSetupProcessDialog.js
@@ -0,0 +1,9 @@
+Demo.FailedSetupProcessDialog = function DemoFailedSetupProcessDialog( config ) {
+ Demo.FailedSetupProcessDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.FailedSetupProcessDialog, Demo.SimpleDialog );
+Demo.FailedSetupProcessDialog.prototype.getSetupProcess = function () {
+ return Demo.FailedSetupProcessDialog.parent.prototype.getSetupProcess.call( this ).next( function () {
+ return $.Deferred().reject().promise();
+ } );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableTest.css b/www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableTest.css
new file mode 100644
index 00000000..d5c0c84c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableTest.css
@@ -0,0 +1,22 @@
+.demo-floatableTest-floatable,
+.demo-floatableTest-container {
+ border: 1px solid #000;
+}
+
+.demo-floatableTest-floatable {
+ border: 1px solid #d33;
+ width: 200px;
+ height: 200px;
+ position: absolute;
+ pointer-events: none;
+}
+
+.demo-floatableTest-container {
+ position: absolute;
+ text-align: center;
+}
+
+.demo-floatableTest-container .oo-ui-fieldsetLayout {
+ margin-top: 20%;
+ display: inline-block;
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableTest.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableTest.js
new file mode 100644
index 00000000..43cb9779
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableTest.js
@@ -0,0 +1,125 @@
+Demo.FloatableTest = function DemoFloatableTest( config ) {
+ // Parent constructor
+ Demo.FloatableTest.parent.call( this, config );
+ // Properties
+ // Must be equal to dialog width and height
+ this.viewportSize = 500;
+ // Width and height of scrollable area
+ this.outerSize = 1000;
+ // Width and height of scrollable container
+ this.innerSize = 400;
+};
+OO.inheritClass( Demo.FloatableTest, OO.ui.ProcessDialog );
+Demo.FloatableTest.static.title = 'FloatableElement test';
+Demo.FloatableTest.static.actions = [
+ { action: '', label: 'Cancel', flags: [ 'safe', 'back' ] },
+ { action: 'center', label: 'Center view' }
+];
+Demo.FloatableTest.prototype.getBodyHeight = function () {
+ return this.viewportSize;
+};
+Demo.FloatableTest.prototype.initialize = function () {
+ Demo.FloatableTest.parent.prototype.initialize.apply( this, arguments );
+
+ this.$container = $( '<div>' ).css( { width: this.outerSize, height: this.outerSize } );
+ this.selectWidget = new Demo.PositionSelectWidget();
+ this.toggleOverlayWidget = new OO.ui.ToggleSwitchWidget( { value: true } );
+ this.toggleClippingWidget = new OO.ui.ToggleSwitchWidget( { value: false } );
+
+ this.$floatableContainer = $( '<div>' ).css( { width: this.innerSize, height: this.innerSize } );
+ this.floatable = new Demo.FloatableWidget( { $floatableContainer: this.$floatableContainer } );
+ this.floatable.toggle( false );
+
+ this.floatable.$element.addClass( 'demo-floatableTest-floatable' );
+ this.$floatableContainer.addClass( 'demo-floatableTest-container' );
+
+ this.selectWidget.connect( this, { select: 'onSelectPosition' } );
+ this.toggleOverlayWidget.connect( this, { change: 'onToggleOverlay' } );
+ this.toggleClippingWidget.connect( this, { change: 'onToggleClipping' } );
+
+ this.fieldset = new OO.ui.FieldsetLayout( {
+ items: [
+ new OO.ui.FieldLayout( this.selectWidget, {
+ align: 'top',
+ label: 'Floatable position'
+ } ),
+ new OO.ui.FieldLayout( this.toggleClippingWidget, {
+ align: 'inline',
+ label: 'Enable clipping'
+ } ),
+ new OO.ui.FieldLayout( this.toggleOverlayWidget, {
+ align: 'inline',
+ label: 'Use overlay'
+ } )
+ ]
+ } );
+
+ this.$body.append(
+ this.$container.append(
+ this.$floatableContainer.append( this.fieldset.$element )
+ )
+ );
+ this.$overlay.append( this.floatable.$element );
+};
+Demo.FloatableTest.prototype.onSelectPosition = function ( option ) {
+ this.floatable.setHorizontalPosition( option.getData().horizontalPosition );
+ this.floatable.setVerticalPosition( option.getData().verticalPosition );
+};
+Demo.FloatableTest.prototype.onToggleOverlay = function ( useOverlay ) {
+ this.floatable.togglePositioning( false );
+ this.floatable.toggleClipping( false );
+ ( useOverlay ? this.$overlay : this.$container ).append( this.floatable.$element );
+ this.floatable.togglePositioning( true );
+ this.floatable.toggleClipping( this.toggleClippingWidget.getValue() );
+};
+Demo.FloatableTest.prototype.onToggleClipping = function ( useClipping ) {
+ this.floatable.toggleClipping( useClipping );
+};
+Demo.FloatableTest.prototype.centerView = function () {
+ var offset = ( this.outerSize - this.viewportSize ) / 2;
+ this.$body[ 0 ].scrollTop = offset;
+ // Different browsers count scrollLeft in RTL differently,
+ // see <https://github.com/othree/jquery.rtl-scroll-type>.
+ // This isn't correct for arbitrary offsets, but works for centering.
+ this.$body[ 0 ].scrollLeft = offset;
+ if ( this.$body[ 0 ].scrollLeft === 0 ) {
+ this.$body[ 0 ].scrollLeft = -offset;
+ }
+};
+Demo.FloatableTest.prototype.getReadyProcess = function () {
+ return new OO.ui.Process( function () {
+ var offset, side;
+ offset = ( this.outerSize - this.innerSize ) / 2;
+ side = this.getDir() === 'rtl' ? 'right' : 'left';
+ this.$floatableContainer.css( 'top', offset );
+ this.$floatableContainer.css( side, offset );
+
+ this.centerView();
+ this.selectWidget.selectItemByData( {
+ horizontalPosition: 'start',
+ verticalPosition: 'below'
+ } );
+
+ // Wait until the opening animation is over
+ setTimeout( function () {
+ this.floatable.toggle( true );
+ this.floatable.togglePositioning( true );
+ this.floatable.toggleClipping( this.toggleClippingWidget.getValue() );
+ }.bind( this ), OO.ui.theme.getDialogTransitionDuration() );
+ }, this );
+};
+Demo.FloatableTest.prototype.getHoldProcess = function () {
+ return new OO.ui.Process( function () {
+ this.floatable.toggleClipping( false );
+ this.floatable.togglePositioning( false );
+ this.floatable.toggle( false );
+ }, this );
+};
+Demo.FloatableTest.prototype.getActionProcess = function ( action ) {
+ if ( action === 'center' ) {
+ return new OO.ui.Process( function () {
+ this.centerView();
+ }, this );
+ }
+ return Demo.FloatableTest.parent.prototype.getActionProcess.call( this, action );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableWidget.js
new file mode 100644
index 00000000..ef5f2bf7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/FloatableWidget.js
@@ -0,0 +1,10 @@
+Demo.FloatableWidget = function DemoFloatableWidget( config ) {
+ // Parent constructor
+ Demo.FloatableWidget.parent.call( this, config );
+ // Mixin constructors
+ OO.ui.mixin.FloatableElement.call( this, config );
+ OO.ui.mixin.ClippableElement.call( this, config );
+};
+OO.inheritClass( Demo.FloatableWidget, OO.ui.Widget );
+OO.mixinClass( Demo.FloatableWidget, OO.ui.mixin.FloatableElement );
+OO.mixinClass( Demo.FloatableWidget, OO.ui.mixin.ClippableElement );
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/IndexedDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/IndexedDialog.js
new file mode 100644
index 00000000..ac932245
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/IndexedDialog.js
@@ -0,0 +1,45 @@
+Demo.IndexedDialog = function DemoIndexedDialog( config ) {
+ Demo.IndexedDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.IndexedDialog, OO.ui.ProcessDialog );
+Demo.IndexedDialog.static.title = 'Indexed dialog';
+Demo.IndexedDialog.static.actions = [
+ { action: 'save', label: 'Done', flags: [ 'primary', 'progressive' ] },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] }
+];
+Demo.IndexedDialog.prototype.getBodyHeight = function () {
+ return 250;
+};
+Demo.IndexedDialog.prototype.initialize = function () {
+ var loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, ' +
+ 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\u200E';
+ Demo.IndexedDialog.parent.prototype.initialize.apply( this, arguments );
+ this.indexLayout = new OO.ui.IndexLayout();
+ this.tabPanels = [
+ new Demo.SampleTabPanel( 'first', { label: 'One tab' } ),
+ new Demo.SampleTabPanel( 'second', { label: 'Two tab' } ),
+ new Demo.SampleTabPanel( 'third', { label: 'Three tab' } ),
+ new Demo.SampleTabPanel( 'fourth', { label: 'Four tab' } ),
+ new Demo.SampleTabPanel( 'long', {
+ label: 'Long tab',
+ content: [
+ $( '<p>' ).text( loremIpsum ),
+ $( '<p>' ).text( loremIpsum ),
+ $( '<p>' ).text( loremIpsum )
+ ]
+ } )
+ ];
+
+ this.indexLayout.addTabPanels( this.tabPanels );
+ this.$body.append( this.indexLayout.$element );
+
+ this.indexLayout.getTabs().findItemFromData( 'fourth' ).setDisabled( true );
+};
+Demo.IndexedDialog.prototype.getActionProcess = function ( action ) {
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ this.close( { action: action } );
+ }, this );
+ }
+ return Demo.IndexedDialog.parent.prototype.getActionProcess.call( this, action );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/LongProcessDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/LongProcessDialog.js
new file mode 100644
index 00000000..d21b2dcb
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/LongProcessDialog.js
@@ -0,0 +1,32 @@
+Demo.LongProcessDialog = function DemoLongProcessDialog( config ) {
+ Demo.LongProcessDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.LongProcessDialog, OO.ui.ProcessDialog );
+Demo.LongProcessDialog.static.title = 'Process dialog';
+Demo.LongProcessDialog.static.actions = [
+ { action: 'save', label: 'Done', flags: [ 'primary', 'progressive' ] },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] },
+ { action: 'other', label: 'Other', flags: 'other' }
+];
+Demo.LongProcessDialog.prototype.initialize = function () {
+ var i;
+
+ Demo.LongProcessDialog.parent.prototype.initialize.apply( this, arguments );
+ this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
+ for ( i = 0; i < 100; i++ ) {
+ this.content.$element.append( '<p>Dialog content</p>' );
+ }
+ this.$body.append( this.content.$element );
+};
+Demo.LongProcessDialog.prototype.getActionProcess = function ( action ) {
+ var dialog = this;
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ dialog.close( { action: action } );
+ } );
+ }
+ return Demo.LongProcessDialog.parent.prototype.getActionProcess.call( this, action );
+};
+Demo.LongProcessDialog.prototype.getBodyHeight = function () {
+ return this.content.$element.outerHeight( true );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/MenuDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/MenuDialog.js
new file mode 100644
index 00000000..34e55806
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/MenuDialog.js
@@ -0,0 +1,90 @@
+Demo.MenuDialog = function DemoMenuDialog( config ) {
+ Demo.MenuDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.MenuDialog, OO.ui.ProcessDialog );
+Demo.MenuDialog.static.title = 'Menu dialog';
+Demo.MenuDialog.static.actions = [
+ { action: 'save', label: 'Done', flags: [ 'primary', 'progressive' ] },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] }
+];
+Demo.MenuDialog.prototype.getBodyHeight = function () {
+ return 350;
+};
+Demo.MenuDialog.prototype.initialize = function () {
+ var menuLayout, positionField, showField, expandField, menuPanel, contentPanel;
+ Demo.MenuDialog.parent.prototype.initialize.apply( this, arguments );
+
+ menuLayout = new OO.ui.MenuLayout();
+ positionField = new OO.ui.FieldLayout(
+ new OO.ui.ButtonSelectWidget( {
+ items: [
+ new OO.ui.ButtonOptionWidget( {
+ data: 'before',
+ label: 'Before'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'after',
+ label: 'After'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'top',
+ label: 'Top'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'bottom',
+ label: 'Bottom'
+ } )
+ ]
+ } ).on( 'select', function ( item ) {
+ menuLayout.setMenuPosition( item.getData() );
+ } ),
+ {
+ label: 'Menu position',
+ align: 'top'
+ }
+ );
+ showField = new OO.ui.FieldLayout(
+ new OO.ui.ToggleSwitchWidget( { value: true } ).on( 'change', function ( value ) {
+ menuLayout.toggleMenu( value );
+ } ),
+ {
+ label: 'Show menu',
+ align: 'top'
+ }
+ );
+ expandField = new OO.ui.FieldLayout(
+ new OO.ui.ToggleSwitchWidget( { value: true } ).on( 'change', function ( value ) {
+ menuLayout.$element.toggleClass( 'oo-ui-menuLayout-expanded', value );
+ menuLayout.$element.toggleClass( 'oo-ui-menuLayout-static', !value );
+ menuPanel.$element.toggleClass( 'oo-ui-panelLayout-expanded', value );
+ contentPanel.$element.toggleClass( 'oo-ui-panelLayout-expanded', value );
+ } ),
+ {
+ label: 'Expand layout',
+ align: 'top'
+ }
+ );
+ menuPanel = new OO.ui.PanelLayout( { padded: true, expanded: true, scrollable: true } );
+ contentPanel = new OO.ui.PanelLayout( { padded: true, expanded: true, scrollable: true } );
+
+ menuLayout.$menu.append(
+ menuPanel.$element.append( 'Menu panel' )
+ );
+ menuLayout.$content.append(
+ contentPanel.$element.append(
+ positionField.$element,
+ expandField.$element,
+ showField.$element
+ )
+ );
+
+ this.$body.append( menuLayout.$element );
+};
+Demo.MenuDialog.prototype.getActionProcess = function ( action ) {
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ this.close( { action: action } );
+ }, this );
+ }
+ return Demo.MenuDialog.parent.prototype.getActionProcess.call( this, action );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/NumberLookupTextInputWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/NumberLookupTextInputWidget.js
new file mode 100644
index 00000000..7ad5d16b
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/NumberLookupTextInputWidget.js
@@ -0,0 +1,68 @@
+/**
+ * Demo for LookupElement.
+ *
+ * @class
+ * @extends OO.ui.TextInputWidget
+ * @mixins OO.ui.mixin.LookupElement
+ *
+ * @constructor
+ * @param {Object} config Configuration options
+ */
+Demo.NumberLookupTextInputWidget = function DemoNumberLookupTextInputWidget( config ) {
+ // Parent constructor
+ OO.ui.TextInputWidget.call( this, $.extend( { validate: 'integer' }, config ) );
+ // Mixin constructors
+ OO.ui.mixin.LookupElement.call( this, config );
+};
+OO.inheritClass( Demo.NumberLookupTextInputWidget, OO.ui.TextInputWidget );
+OO.mixinClass( Demo.NumberLookupTextInputWidget, OO.ui.mixin.LookupElement );
+
+/**
+ * @inheritdoc
+ */
+Demo.NumberLookupTextInputWidget.prototype.getLookupRequest = function () {
+ var
+ value = this.getValue(),
+ deferred = $.Deferred(),
+ delay = 500 + Math.floor( Math.random() * 500 );
+
+ this.getValidity().then( function () {
+ // Resolve with results after a faked delay
+ setTimeout( function () {
+ deferred.resolve( [
+ value * 1, value * 2, value * 3, value * 4, value * 5,
+ value * 6, value * 7, value * 8, value * 9, value * 10
+ ] );
+ }, delay );
+ }, function () {
+ // No results when the input contains invalid content
+ deferred.resolve( [] );
+ } );
+
+ return deferred.promise( { abort: function () {} } );
+};
+
+/**
+ * @inheritdoc
+ */
+Demo.NumberLookupTextInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
+ return response || [];
+};
+
+/**
+ * @inheritdoc
+ */
+Demo.NumberLookupTextInputWidget.prototype.getLookupMenuOptionsFromData = function ( data ) {
+ var
+ items = [],
+ i, number;
+ for ( i = 0; i < data.length; i++ ) {
+ number = String( data[ i ] );
+ items.push( new OO.ui.MenuOptionWidget( {
+ data: number,
+ label: number
+ } ) );
+ }
+
+ return items;
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/OutlinedBookletDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/OutlinedBookletDialog.js
new file mode 100644
index 00000000..c58a6fdc
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/OutlinedBookletDialog.js
@@ -0,0 +1,46 @@
+Demo.OutlinedBookletDialog = function DemoOutlinedBookletDialog( config ) {
+ Demo.OutlinedBookletDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.OutlinedBookletDialog, OO.ui.ProcessDialog );
+Demo.OutlinedBookletDialog.static.title = 'Outlined booklet dialog';
+Demo.OutlinedBookletDialog.static.actions = [
+ { action: 'save', label: 'Done', flags: [ 'primary', 'progressive' ] },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] }
+];
+Demo.OutlinedBookletDialog.prototype.getBodyHeight = function () {
+ return 250;
+};
+Demo.OutlinedBookletDialog.prototype.initialize = function () {
+ Demo.OutlinedBookletDialog.parent.prototype.initialize.apply( this, arguments );
+ this.bookletLayout = new OO.ui.BookletLayout( {
+ outlined: true
+ } );
+ this.pages = [
+ new Demo.SamplePage( 'small', { label: 'Small', icon: 'window' } ),
+ new Demo.SamplePage( 'medium', { label: 'Medium', icon: 'window' } ),
+ new Demo.SamplePage( 'large', { label: 'Large', icon: 'window' } ),
+ new Demo.SamplePage( 'larger', { label: 'Larger', icon: 'window' } ),
+ new Demo.SamplePage( 'full', { label: 'Full', icon: 'window' } )
+ ];
+
+ this.bookletLayout.addPages( this.pages );
+ this.bookletLayout.connect( this, { set: 'onBookletLayoutSet' } );
+ this.$body.append( this.bookletLayout.$element );
+};
+Demo.OutlinedBookletDialog.prototype.getActionProcess = function ( action ) {
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ this.close( { action: action } );
+ }, this );
+ }
+ return Demo.OutlinedBookletDialog.parent.prototype.getActionProcess.call( this, action );
+};
+Demo.OutlinedBookletDialog.prototype.onBookletLayoutSet = function ( page ) {
+ this.setSize( page.getName() );
+};
+Demo.OutlinedBookletDialog.prototype.getSetupProcess = function ( data ) {
+ return Demo.OutlinedBookletDialog.parent.prototype.getSetupProcess.call( this, data )
+ .next( function () {
+ this.bookletLayout.setPage( this.getSize() );
+ }, this );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/PopupButtonWidgetTest.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/PopupButtonWidgetTest.js
new file mode 100644
index 00000000..2c817f79
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/PopupButtonWidgetTest.js
@@ -0,0 +1,123 @@
+Demo.PopupButtonWidgetTest = function DemoPopupButtonWidgetTest( config ) {
+ Demo.PopupButtonWidgetTest.parent.call( this, config );
+};
+OO.inheritClass( Demo.PopupButtonWidgetTest, OO.ui.ProcessDialog );
+Demo.PopupButtonWidgetTest.static.title = 'PopupButtonWidget test';
+Demo.PopupButtonWidgetTest.static.actions = [
+ { action: 'save', label: 'Done', flags: [ 'primary', 'progressive' ] },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] }
+];
+Demo.PopupButtonWidgetTest.prototype.initialize = function () {
+ Demo.PopupButtonWidgetTest.parent.prototype.initialize.apply( this, arguments );
+
+ this.panel = new OO.ui.PanelLayout( {
+ expanded: false,
+ padded: true
+ } );
+
+ this.$center = $( '<td>' ).attr( { colspan: 3, rowspan: 3 } );
+
+ this.toggleOverlayWidget = new OO.ui.ToggleSwitchWidget( { value: true } );
+ this.toggleAnchorWidget = new OO.ui.ToggleSwitchWidget( { value: true } );
+ this.showAllWidget = new OO.ui.ButtonWidget( { label: 'Toggle all' } );
+
+ this.toggleOverlayWidget.connect( this, { change: 'makeTable' } );
+ this.toggleAnchorWidget.connect( this, { change: 'makeTable' } );
+ this.showAllWidget.connect( this, { click: 'toggleAll' } );
+
+ this.fieldset = new OO.ui.FieldsetLayout( {
+ items: [
+ new OO.ui.FieldLayout( this.toggleAnchorWidget, {
+ align: 'inline',
+ label: 'Enable anchors'
+ } ),
+ new OO.ui.FieldLayout( this.toggleOverlayWidget, {
+ align: 'inline',
+ label: 'Use overlay'
+ } ),
+ new OO.ui.FieldLayout( this.showAllWidget, {
+ align: 'top'
+ } )
+ ]
+ } );
+
+ this.$center.append( this.fieldset.$element );
+
+ this.makeTable();
+
+ this.$body.append( this.panel.$element );
+};
+Demo.PopupButtonWidgetTest.prototype.makeContents = function () {
+ var loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, ' +
+ 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\u200E';
+ return $( [] )
+ .add( $( '<p>' ).text( loremIpsum ) )
+ .add( $( '<p>' ).text( loremIpsum ) )
+ .add( $( '<p>' ).text( loremIpsum ) );
+};
+Demo.PopupButtonWidgetTest.prototype.makeTable = function () {
+ this.buttons = [];
+ if ( this.$table ) {
+ this.$table.detach();
+ }
+
+ this.$table = $( '<table>' ).append(
+ $( '<tr>' ).append(
+ $( '<td>' ),
+ $( '<td>' ).append( this.getButton( 'above', 'backwards' ).$element ),
+ $( '<td>' ).append( this.getButton( 'above', 'center' ).$element ),
+ $( '<td>' ).append( this.getButton( 'above', 'forwards' ).$element ),
+ $( '<td>' )
+ ),
+ $( '<tr>' ).append(
+ $( '<td>' ).append( this.getButton( 'before', 'backwards' ).$element ),
+ this.$center,
+ $( '<td>' ).append( this.getButton( 'after', 'backwards' ).$element ).css( 'text-align', this.getDir() === 'rtl' ? 'left' : 'right' )
+ ),
+ $( '<tr>' ).append(
+ $( '<td>' ).append( this.getButton( 'before', 'center' ).$element ),
+ $( '<td>' ).append( this.getButton( 'after', 'center' ).$element ).css( 'text-align', this.getDir() === 'rtl' ? 'left' : 'right' )
+ ),
+ $( '<tr>' ).append(
+ $( '<td>' ).append( this.getButton( 'before', 'forwards' ).$element ),
+ $( '<td>' ).append( this.getButton( 'after', 'forwards' ).$element ).css( 'text-align', this.getDir() === 'rtl' ? 'left' : 'right' )
+ ),
+ $( '<tr>' ).append(
+ $( '<td>' ),
+ $( '<td>' ).append( this.getButton( 'below', 'backwards' ).$element ),
+ $( '<td>' ).append( this.getButton( 'below', 'center' ).$element ),
+ $( '<td>' ).append( this.getButton( 'below', 'forwards' ).$element ),
+ $( '<td>' )
+ )
+ );
+ this.panel.$element.append( this.$table );
+};
+Demo.PopupButtonWidgetTest.prototype.getButton = function ( position, align ) {
+ var button = new OO.ui.PopupButtonWidget( {
+ $overlay: ( this.toggleOverlayWidget.getValue() ? this.$overlay : null ),
+ label: $( '<span>' ).append( position + '<br>' + align ),
+ popup: {
+ position: position,
+ align: align,
+ anchor: this.toggleAnchorWidget.getValue(),
+ padded: true,
+ $content: this.makeContents()
+ }
+ } );
+
+ this.buttons.push( button );
+ return button;
+};
+Demo.PopupButtonWidgetTest.prototype.toggleAll = function () {
+ this.buttons.forEach( function ( button ) {
+ button.getPopup().toggle();
+ } );
+};
+Demo.PopupButtonWidgetTest.prototype.getActionProcess = function ( action ) {
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ this.close( { action: action } );
+ }, this );
+ }
+ return Demo.PopupButtonWidgetTest.parent.prototype.getActionProcess.call( this, action );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/PositionSelectWidget.css b/www/wiki/vendor/oojs/oojs-ui/demos/classes/PositionSelectWidget.css
new file mode 100644
index 00000000..eb60d777
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/PositionSelectWidget.css
@@ -0,0 +1,34 @@
+.demo-positionSelectWidget table {
+ border-collapse: collapse;
+}
+.demo-positionSelectWidget tr:nth-child( 2 ) td:nth-child( 2 ) {
+ border-top: 1px solid #000;
+ border-left: 1px solid #000;
+}
+.demo-positionSelectWidget tr:nth-child( 2 ) td:nth-child( 3 ) {
+ border-top: 1px solid #000;
+}
+.demo-positionSelectWidget tr:nth-child( 2 ) td:nth-child( 4 ) {
+ border-top: 1px solid #000;
+ border-right: 1px solid #000;
+}
+.demo-positionSelectWidget tr:nth-child( 3 ) td:nth-child( 2 ) {
+ border-left: 1px solid #000;
+}
+.demo-positionSelectWidget tr:nth-child( 3 ) td:nth-child( 4 ) {
+ border-right: 1px solid #000;
+}
+.demo-positionSelectWidget tr:nth-child( 4 ) td:nth-child( 2 ) {
+ border-bottom: 1px solid #000;
+ border-left: 1px solid #000;
+}
+.demo-positionSelectWidget tr:nth-child( 4 ) td:nth-child( 3 ) {
+ border-bottom: 1px solid #000;
+}
+.demo-positionSelectWidget tr:nth-child( 4 ) td:nth-child( 4 ) {
+ border-bottom: 1px solid #000;
+ border-right: 1px solid #000;
+}
+.demo-positionSelectWidget .oo-ui-radioOptionWidget.oo-ui-optionWidget-selected {
+ outline: 1px solid #d33;
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/PositionSelectWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/PositionSelectWidget.js
new file mode 100644
index 00000000..67a2bdb4
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/PositionSelectWidget.js
@@ -0,0 +1,35 @@
+Demo.PositionSelectWidget = function DemoPositionSelectWidget( config ) {
+ var verticalPositions, horizontalPositions, $table,
+ widget = this;
+
+ Demo.PositionSelectWidget.parent.call( this, config );
+
+ verticalPositions = [ 'above', 'top', 'center', 'bottom', 'below' ];
+ horizontalPositions = [ 'before', 'start', 'center', 'end', 'after' ];
+
+ $table = $( '<table>' );
+ verticalPositions.forEach( function ( v ) {
+ var $tr = $( '<tr>' );
+ horizontalPositions.forEach( function ( h ) {
+ var $td = $( '<td>' );
+ $td.append( widget.getOption( h, v ).$element );
+ $td.attr( 'title', v + '/' + h );
+ $tr.append( $td );
+ } );
+ $table.append( $tr );
+ } );
+
+ this.$element.append( $table );
+ this.$element.addClass( 'demo-positionSelectWidget' );
+};
+OO.inheritClass( Demo.PositionSelectWidget, OO.ui.RadioSelectWidget );
+Demo.PositionSelectWidget.prototype.getOption = function ( h, v ) {
+ var option = new OO.ui.RadioOptionWidget( {
+ data: {
+ horizontalPosition: h,
+ verticalPosition: v
+ }
+ } );
+ this.addItems( [ option ] );
+ return option;
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/ProcessDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/ProcessDialog.js
new file mode 100644
index 00000000..6ddc8982
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/ProcessDialog.js
@@ -0,0 +1,39 @@
+Demo.ProcessDialog = function DemoProcessDialog( config ) {
+ Demo.ProcessDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.ProcessDialog, OO.ui.ProcessDialog );
+Demo.ProcessDialog.static.title = 'Process dialog';
+Demo.ProcessDialog.static.actions = [
+ { action: 'save', label: 'Done', flags: [ 'primary', 'progressive' ] },
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] },
+ { action: 'other', label: 'Other', flags: 'other' }
+];
+Demo.ProcessDialog.prototype.initialize = function () {
+ var $content;
+ Demo.ProcessDialog.parent.prototype.initialize.apply( this, arguments );
+
+ $content = $( '<div>' ).append(
+ $( '<p>' ).text( 'Dialog content' ),
+ $( '<a>' )
+ .text( 'Be alert!' )
+ .on( 'click', function () {
+ OO.ui.alert( 'You are alert!' );
+ } )
+ );
+
+ this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
+ this.content.$element.append( $content );
+ this.$body.append( this.content.$element );
+};
+Demo.ProcessDialog.prototype.getActionProcess = function ( action ) {
+ var dialog = this;
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ dialog.close( { action: action } );
+ } );
+ }
+ return Demo.ProcessDialog.parent.prototype.getActionProcess.call( this, action );
+};
+Demo.ProcessDialog.prototype.getBodyHeight = function () {
+ return this.content.$element.outerHeight( true );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/SamplePage.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SamplePage.js
new file mode 100644
index 00000000..6572e909
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SamplePage.js
@@ -0,0 +1,20 @@
+Demo.SamplePage = function DemoSamplePage( name, config ) {
+ config = $.extend( { label: 'Sample page' }, config );
+ Demo.SamplePage.parent.apply( this, arguments );
+ this.label = config.label;
+ this.level = config.level;
+ this.icon = config.icon;
+ if ( this.$element.is( ':empty' ) ) {
+ this.$element.text( this.label );
+ }
+};
+OO.inheritClass( Demo.SamplePage, OO.ui.PageLayout );
+Demo.SamplePage.prototype.setupOutlineItem = function ( outlineItem ) {
+ Demo.SamplePage.parent.prototype.setupOutlineItem.call( this, outlineItem );
+ this.outlineItem
+ .setMovable( true )
+ .setRemovable( true )
+ .setIcon( this.icon )
+ .setLevel( this.level )
+ .setLabel( this.label );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/SampleTabPanel.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SampleTabPanel.js
new file mode 100644
index 00000000..39a7c6b6
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SampleTabPanel.js
@@ -0,0 +1,7 @@
+Demo.SampleTabPanel = function DemoSampleTabPanel( name, config ) {
+ OO.ui.TabPanelLayout.call( this, name, config );
+ if ( this.$element.is( ':empty' ) ) {
+ this.$element.text( this.label );
+ }
+};
+OO.inheritClass( Demo.SampleTabPanel, OO.ui.TabPanelLayout );
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/SearchWidgetDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SearchWidgetDialog.js
new file mode 100644
index 00000000..f8d17188
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SearchWidgetDialog.js
@@ -0,0 +1,30 @@
+Demo.SearchWidgetDialog = function DemoSearchWidgetDialog( config ) {
+ Demo.SearchWidgetDialog.parent.call( this, config );
+ this.broken = false;
+};
+OO.inheritClass( Demo.SearchWidgetDialog, OO.ui.ProcessDialog );
+Demo.SearchWidgetDialog.static.title = 'Search widget dialog';
+Demo.SearchWidgetDialog.prototype.initialize = function () {
+ var i, items, searchWidget;
+ Demo.SearchWidgetDialog.parent.prototype.initialize.apply( this, arguments );
+ items = [];
+ searchWidget = new OO.ui.SearchWidget();
+ for ( i = 1; i <= 20; i++ ) {
+ items.push( new OO.ui.OptionWidget( { data: i, label: 'Item ' + i } ) );
+ }
+ searchWidget.results.addItems( items );
+ searchWidget.onQueryChange = function () {};
+ this.$body.append( searchWidget.$element );
+};
+Demo.SearchWidgetDialog.prototype.getBodyHeight = function () {
+ return 300;
+};
+Demo.SearchWidgetDialog.static.actions = [
+ { action: 'cancel', label: 'Cancel', flags: [ 'safe', 'back' ] }
+];
+Demo.SearchWidgetDialog.prototype.getActionProcess = function ( action ) {
+ var dialog = this;
+ return new OO.ui.Process( function () {
+ dialog.close( { action: action } );
+ } );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleDialog.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleDialog.js
new file mode 100644
index 00000000..733c8c7f
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleDialog.js
@@ -0,0 +1,26 @@
+Demo.SimpleDialog = function DemoSimpleDialog( config ) {
+ Demo.SimpleDialog.parent.call( this, config );
+};
+OO.inheritClass( Demo.SimpleDialog, OO.ui.Dialog );
+Demo.SimpleDialog.static.title = 'Simple dialog';
+Demo.SimpleDialog.prototype.initialize = function () {
+ var closeButton,
+ dialog = this;
+
+ Demo.SimpleDialog.parent.prototype.initialize.apply( this, arguments );
+ this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
+ this.content.$element.append( '<p>Dialog content</p>' );
+
+ closeButton = new OO.ui.ButtonWidget( {
+ label: OO.ui.msg( 'ooui-dialog-process-dismiss' )
+ } );
+ closeButton.on( 'click', function () {
+ dialog.close();
+ } );
+
+ this.content.$element.append( closeButton.$element );
+ this.$body.append( this.content.$element );
+};
+Demo.SimpleDialog.prototype.getBodyHeight = function () {
+ return this.content.$element.outerHeight( true );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleWidget.css b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleWidget.css
new file mode 100644
index 00000000..04f0844e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleWidget.css
@@ -0,0 +1,23 @@
+.demo-simpleWidget {
+ display: block;
+ position: relative;
+ padding: 0.703125em 0.9375em 0.625em;
+ line-height: 1;
+}
+
+.demo-simpleWidget.oo-ui-labelElement {
+ line-height: 1.172em;
+}
+
+.demo-simpleWidget.oo-ui-iconElement {
+ padding-left: 2.96875em;
+}
+
+.demo-simpleWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+ position: absolute;
+ left: 0.9375em;
+}
+
+.demo-simpleWidget.oo-ui-widget-disabled .oo-ui-iconElement-icon {
+ opacity: 0.51;
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleWidget.js
new file mode 100644
index 00000000..e5ad631a
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/SimpleWidget.js
@@ -0,0 +1,31 @@
+/**
+ * Very simple custom widget.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.LabelElement
+ *
+ * @param {Object} [config] Configuration options
+ */
+Demo.SimpleWidget = function DemoSimpleWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ Demo.SimpleWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.LabelElement.call( this, config );
+
+ // Initialization
+ this.$element
+ .addClass( 'demo-simpleWidget' )
+ .append( this.$icon, this.$label );
+};
+
+/* Setup */
+OO.inheritClass( Demo.SimpleWidget, OO.ui.Widget );
+OO.mixinClass( Demo.SimpleWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( Demo.SimpleWidget, OO.ui.mixin.LabelElement );
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/classes/UnsupportedSelectFileWidget.js b/www/wiki/vendor/oojs/oojs-ui/demos/classes/UnsupportedSelectFileWidget.js
new file mode 100644
index 00000000..5da9f9b5
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/classes/UnsupportedSelectFileWidget.js
@@ -0,0 +1,8 @@
+Demo.UnsupportedSelectFileWidget = function DemoUnsupportedSelectFileWidget() {
+ // Parent constructor
+ Demo.UnsupportedSelectFileWidget.parent.apply( this, arguments );
+};
+OO.inheritClass( Demo.UnsupportedSelectFileWidget, OO.ui.SelectFileWidget );
+Demo.UnsupportedSelectFileWidget.static.isSupported = function () {
+ return false;
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/demo.js b/www/wiki/vendor/oojs/oojs-ui/demos/demo.js
new file mode 100644
index 00000000..635952e8
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/demo.js
@@ -0,0 +1,794 @@
+/* eslint-disable no-console */
+/* globals Prism, javascriptStringify */
+/**
+ * @class
+ * @extends OO.ui.Element
+ *
+ * @constructor
+ */
+window.Demo = function Demo() {
+ var demo = this;
+
+ // Parent constructor
+ Demo.parent.call( this );
+
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+
+ // Normalization
+ this.normalizeQuery();
+
+ // Properties
+ this.stylesheetLinks = this.getStylesheetLinks();
+ this.mode = this.getCurrentMode();
+ this.$menu = $( '<div>' );
+ this.pageDropdown = new OO.ui.DropdownWidget( {
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( { data: 'dialogs', label: 'Dialogs' } ),
+ new OO.ui.MenuOptionWidget( { data: 'icons', label: 'Icons' } ),
+ new OO.ui.MenuOptionWidget( { data: 'toolbars', label: 'Toolbars' } ),
+ new OO.ui.MenuOptionWidget( { data: 'widgets', label: 'Widgets' } )
+ ],
+ // Funny effect... This dropdown is considered to always be "out of viewport"
+ // due to the getViewportSpacing() override below. Don't let it disappear.
+ hideWhenOutOfView: false
+ },
+ classes: [ 'demo-pageDropdown' ]
+ } );
+ this.pageMenu = this.pageDropdown.getMenu();
+ this.themeSelect = new OO.ui.ButtonSelectWidget();
+ Object.keys( this.constructor.static.themes ).forEach( function ( theme ) {
+ demo.themeSelect.addItems( [
+ new OO.ui.ButtonOptionWidget( {
+ data: theme,
+ label: demo.constructor.static.themes[ theme ]
+ } )
+ ] );
+ } );
+ this.directionSelect = new OO.ui.ButtonSelectWidget().addItems( [
+ new OO.ui.ButtonOptionWidget( { data: 'ltr', label: 'LTR' } ),
+ new OO.ui.ButtonOptionWidget( { data: 'rtl', label: 'RTL' } )
+ ] );
+ this.jsPhpSelect = new OO.ui.ButtonGroupWidget().addItems( [
+ new OO.ui.ButtonWidget( { label: 'JS' } ).setActive( true ),
+ new OO.ui.ButtonWidget( {
+ label: 'PHP',
+ href: 'demos.php' + this.getUrlQuery( this.getCurrentFactorValues() )
+ } )
+ ] );
+ this.platformSelect = new OO.ui.ButtonSelectWidget().addItems( [
+ new OO.ui.ButtonOptionWidget( { data: 'desktop', label: 'Desktop' } ),
+ new OO.ui.ButtonOptionWidget( { data: 'mobile', label: 'Mobile' } )
+ ] );
+
+ this.documentationLink = new OO.ui.ButtonWidget( {
+ label: 'Docs',
+ classes: [ 'demo-button-docs' ],
+ icon: 'journal',
+ href: '../js/',
+ flags: [ 'progressive' ]
+ } );
+
+ // Events
+ this.pageMenu.on( 'choose', OO.ui.bind( this.onModeChange, this ) );
+ this.themeSelect.on( 'choose', OO.ui.bind( this.onModeChange, this ) );
+ this.directionSelect.on( 'choose', OO.ui.bind( this.onModeChange, this ) );
+ this.platformSelect.on( 'choose', OO.ui.bind( this.onModeChange, this ) );
+
+ // Initialization
+ this.pageMenu.selectItemByData( this.mode.page );
+ this.themeSelect.selectItemByData( this.mode.theme );
+ this.directionSelect.selectItemByData( this.mode.direction );
+ this.platformSelect.selectItemByData( this.mode.platform );
+ this.$menu
+ .addClass( 'demo-menu' )
+ .attr( 'role', 'navigation' )
+ .append(
+ this.pageDropdown.$element,
+ this.themeSelect.$element,
+ this.directionSelect.$element,
+ this.jsPhpSelect.$element,
+ this.platformSelect.$element,
+ this.documentationLink.$element
+ );
+ this.$element
+ .addClass( 'demo' )
+ .append( this.$menu );
+ $( 'html' ).attr( 'dir', this.mode.direction );
+ $( 'head' ).append( this.stylesheetLinks );
+ $( 'body' ).addClass( 'oo-ui-theme-' + this.mode.theme );
+ // eslint-disable-next-line new-cap
+ OO.ui.theme = new OO.ui[ this.constructor.static.themes[ this.mode.theme ] + 'Theme' ]();
+ OO.ui.isMobile = function () {
+ return demo.mode.platform === 'mobile';
+ };
+ OO.ui.getViewportSpacing = function () {
+ return {
+ // Contents of dialogs are shown on top of the fixed menu
+ top: demo.mode.page === 'dialogs' ? 0 : demo.$menu.outerHeight(),
+ right: 0,
+ bottom: 0,
+ left: 0
+ };
+ };
+};
+
+/* Setup */
+
+OO.inheritClass( Demo, OO.ui.Element );
+OO.mixinClass( Demo, OO.EventEmitter );
+
+/* Static Properties */
+
+/**
+ * Available pages.
+ *
+ * Populated by each of the page scripts in the `pages` directory.
+ *
+ * @static
+ * @property {Object.<string,Function>} pages List of functions that render a page, keyed by
+ * symbolic page name
+ */
+Demo.static.pages = {};
+
+/**
+ * Available themes.
+ *
+ * Map of lowercase name to proper name. Lowercase names are used for linking to the
+ * correct stylesheet file. Proper names are used to find the theme class.
+ *
+ * @static
+ * @property {Object.<string,string>}
+ */
+Demo.static.themes = {
+ wikimediaui: 'WikimediaUI', // Do not change this line or you'll break `grunt add-theme`
+ apex: 'Apex'
+};
+
+/**
+ * Additional suffixes for which each theme defines image modules.
+ *
+ * @static
+ * @property {Object.<string,string[]>
+ */
+Demo.static.additionalThemeImagesSuffixes = {
+ wikimediaui: [
+ '-icons-movement',
+ '-icons-content',
+ '-icons-alerts',
+ '-icons-interactions',
+ '-icons-moderation',
+ '-icons-editing-core',
+ '-icons-editing-styling',
+ '-icons-editing-list',
+ '-icons-editing-advanced',
+ '-icons-media',
+ '-icons-location',
+ '-icons-user',
+ '-icons-layout',
+ '-icons-accessibility',
+ '-icons-wikimedia'
+ ],
+ apex: [
+ '-icons-movement',
+ '-icons-content',
+ '-icons-alerts',
+ '-icons-interactions',
+ '-icons-moderation',
+ '-icons-editing-core',
+ '-icons-editing-styling',
+ '-icons-editing-list',
+ '-icons-editing-advanced',
+ '-icons-media',
+ '-icons-location',
+ '-icons-user',
+ '-icons-layout',
+ '-icons-accessibility',
+ '-icons-wikimedia'
+ ]
+};
+
+/**
+ * Available text directions.
+ *
+ * List of text direction descriptions, each containing a `fileSuffix` property used for linking to
+ * the correct stylesheet file.
+ *
+ * @static
+ * @property {Object.<string,Object>}
+ */
+Demo.static.directions = {
+ ltr: { fileSuffix: '' },
+ rtl: { fileSuffix: '.rtl' }
+};
+
+/**
+ * Available platforms.
+ *
+ * @static
+ * @property {string[]}
+ */
+Demo.static.platforms = [ 'desktop', 'mobile' ];
+
+/**
+ * Default page.
+ *
+ * @static
+ * @property {string}
+ */
+Demo.static.defaultPage = 'widgets';
+
+/**
+ * Default page.
+ *
+ * Set by one of the page scripts in the `pages` directory.
+ *
+ * @static
+ * @property {string}
+ */
+Demo.static.defaultTheme = 'wikimediaui';
+
+/**
+ * Default page.
+ *
+ * Set by one of the page scripts in the `pages` directory.
+ *
+ * @static
+ * @property {string}
+ */
+Demo.static.defaultDirection = 'ltr';
+
+/**
+ * Default platform.
+ *
+ * Set by one of the page scripts in the `pages` directory.
+ *
+ * @static
+ * @property {string}
+ */
+Demo.static.defaultPlatform = 'desktop';
+
+/* Static Methods */
+
+/**
+ * Scroll to current fragment identifier. We have to do this manually because of the fixed header.
+ */
+Demo.static.scrollToFragment = function () {
+ var elem = document.getElementById( location.hash.slice( 1 ) );
+ if ( elem ) {
+ // The additional '10' is just because it looks nicer.
+ $( window ).scrollTop( $( elem ).offset().top - $( '.demo-menu' ).outerHeight() - 10 );
+ }
+};
+
+/* Methods */
+
+/**
+ * Load the demo page. Must be called after $element is attached.
+ *
+ * @return {jQuery.Promise} Resolved when demo is initialized
+ */
+Demo.prototype.initialize = function () {
+ var demo = this,
+ promises = this.stylesheetLinks.map( function ( el ) {
+ return $( el ).data( 'load-promise' );
+ } );
+
+ // Helper function to get high resolution profiling data, where available.
+ function now() {
+ return ( window.performance && performance.now ) ? performance.now() :
+ Date.now ? Date.now() : new Date().getTime();
+ }
+
+ return $.when.apply( $, promises )
+ .done( function () {
+ var start, end;
+ start = now();
+ demo.constructor.static.pages[ demo.mode.page ]( demo );
+ end = now();
+ window.console.log( 'Took ' + ( end - start ) + ' ms to build demo page.' );
+ } )
+ .fail( function () {
+ demo.$element.append( $( '<p>' ).text( 'Demo styles failed to load.' ) );
+ } );
+};
+
+/**
+ * Handle mode change events.
+ *
+ * Will load a new page.
+ */
+Demo.prototype.onModeChange = function () {
+ var page = this.pageMenu.findSelectedItem().getData(),
+ theme = this.themeSelect.findSelectedItem().getData(),
+ direction = this.directionSelect.findSelectedItem().getData(),
+ platform = this.platformSelect.findSelectedItem().getData();
+
+ history.pushState( null, document.title, this.getUrlQuery( [ page, theme, direction, platform ] ) );
+ $( window ).triggerHandler( 'popstate' );
+};
+
+/**
+ * Get URL query for given factors describing the demo's mode.
+ *
+ * @param {string[]} factors Factors, as returned e.g. by #getCurrentFactorValues
+ * @return {string} URL query part, starting with '?'
+ */
+Demo.prototype.getUrlQuery = function ( factors ) {
+ return '?page=' + factors[ 0 ] +
+ '&theme=' + factors[ 1 ] +
+ '&direction=' + factors[ 2 ] +
+ '&platform=' + factors[ 3 ] +
+ // Preserve current URL 'fragment' part
+ location.hash;
+};
+
+/**
+ * Get a list of mode factors.
+ *
+ * Factors are a mapping between symbolic names used in the URL query and internal information used
+ * to act on those symbolic names.
+ *
+ * Factor lists are in URL order: page, theme, direction, platform. Page contains the symbolic
+ * page name, others contain file suffixes.
+ *
+ * @return {Object[]} List of mode factors, keyed by symbolic name
+ */
+Demo.prototype.getFactors = function () {
+ var key,
+ factors = [ {}, {}, {}, {} ];
+
+ for ( key in this.constructor.static.pages ) {
+ factors[ 0 ][ key ] = key;
+ }
+ for ( key in this.constructor.static.themes ) {
+ factors[ 1 ][ key ] = '-' + key;
+ }
+ for ( key in this.constructor.static.directions ) {
+ factors[ 2 ][ key ] = this.constructor.static.directions[ key ].fileSuffix;
+ }
+ this.constructor.static.platforms.forEach( function ( platform ) {
+ factors[ 3 ][ platform ] = '';
+ } );
+
+ return factors;
+};
+
+/**
+ * Get a list of default factors.
+ *
+ * Factor defaults are in URL order: page, theme, direction, platform. Each contains a symbolic
+ * factor name which should be used as a fallback when the URL query is missing or invalid.
+ *
+ * @return {Object[]} List of default factors
+ */
+Demo.prototype.getDefaultFactorValues = function () {
+ return [
+ this.constructor.static.defaultPage,
+ this.constructor.static.defaultTheme,
+ this.constructor.static.defaultDirection,
+ this.constructor.static.defaultPlatform
+ ];
+};
+
+/**
+ * Parse the current URL query into factor values.
+ *
+ * @return {string[]} Factor values in URL order: page, theme, direction, platform
+ */
+Demo.prototype.getCurrentFactorValues = function () {
+ var i, parts, index,
+ factors = this.getDefaultFactorValues(),
+ order = [ 'page', 'theme', 'direction', 'platform' ],
+ query = location.search.slice( 1 ).split( '&' );
+ for ( i = 0; i < query.length; i++ ) {
+ parts = query[ i ].split( '=', 2 );
+ index = order.indexOf( parts[ 0 ] );
+ if ( index !== -1 ) {
+ factors[ index ] = decodeURIComponent( parts[ 1 ] );
+ }
+ }
+ return factors;
+};
+
+/**
+ * Get the current mode.
+ *
+ * Generated from parsed URL query values.
+ *
+ * @return {Object} List of factor values keyed by factor name
+ */
+Demo.prototype.getCurrentMode = function () {
+ var factorValues = this.getCurrentFactorValues();
+
+ return {
+ page: factorValues[ 0 ],
+ theme: factorValues[ 1 ],
+ direction: factorValues[ 2 ],
+ platform: factorValues[ 3 ]
+ };
+};
+
+/**
+ * Get link elements for the current mode.
+ *
+ * @return {HTMLElement[]} List of link elements
+ */
+Demo.prototype.getStylesheetLinks = function () {
+ var i, len, links, fragments,
+ factors = this.getFactors(),
+ theme = this.getCurrentFactorValues()[ 1 ],
+ suffixes = this.constructor.static.additionalThemeImagesSuffixes[ theme ] || [],
+ urls = [];
+
+ // Translate modes to filename fragments
+ fragments = this.getCurrentFactorValues().map( function ( val, index ) {
+ return factors[ index ][ val ];
+ } );
+
+ // Theme styles
+ urls.push( 'dist/oojs-ui' + fragments.slice( 1 ).join( '' ) + '.css' );
+ for ( i = 0, len = suffixes.length; i < len; i++ ) {
+ urls.push( 'dist/oojs-ui' + fragments[ 1 ] + suffixes[ i ] + fragments[ 2 ] + '.css' );
+ }
+
+ // Demo styles
+ urls.push( 'styles/demo' + fragments[ 2 ] + '.css' );
+
+ // Add link tags
+ links = urls.map( function ( url ) {
+ var
+ link = document.createElement( 'link' ),
+ $link = $( link ),
+ deferred = $.Deferred();
+ $link.data( 'load-promise', deferred.promise() );
+ $link.on( {
+ load: deferred.resolve,
+ error: deferred.reject
+ } );
+ link.rel = 'stylesheet';
+ link.href = url;
+ return link;
+ } );
+
+ return links;
+};
+
+/**
+ * Normalize the URL query.
+ */
+Demo.prototype.normalizeQuery = function () {
+ var i, len, factorValues, match, valid, factorValue,
+ modes = [],
+ factors = this.getFactors(),
+ defaults = this.getDefaultFactorValues();
+
+ factorValues = this.getCurrentFactorValues();
+ for ( i = 0, len = factors.length; i < len; i++ ) {
+ factorValue = factorValues[ i ];
+ modes[ i ] = factors[ i ][ factorValue ] !== undefined ? factorValue : defaults[ i ];
+ }
+
+ // Backwards-compatibility with old URLs that used the 'fragment' part to link to demo sections:
+ // if a fragment is specified and it describes valid factors, turn the URL into the new style.
+ match = location.hash.match( /^#(\w+)-(\w+)-(\w+)-(\w+)$/ );
+ if ( match ) {
+ factorValues = [];
+ valid = true;
+ for ( i = 0, len = factors.length; i < len; i++ ) {
+ factorValue = match[ i + 1 ];
+ if ( factors[ i ][ factorValue ] !== undefined ) {
+ factorValues[ i ] = factorValue;
+ } else {
+ valid = false;
+ break;
+ }
+ }
+ if ( valid ) {
+ location.hash = '';
+ modes = factorValues;
+ }
+ }
+
+ // Update query
+ history.replaceState( null, document.title, this.getUrlQuery( modes ) );
+};
+
+/**
+ * Destroy demo.
+ */
+Demo.prototype.destroy = function () {
+ $( 'body' ).removeClass( 'oo-ui-ltr oo-ui-rtl' );
+ $( 'body' ).removeClass( 'oo-ui-theme-' + this.mode.theme );
+ $( this.stylesheetLinks ).remove();
+ this.$element.remove();
+ this.emit( 'destroy' );
+};
+
+/**
+ * Build a console for interacting with an element.
+ *
+ * @param {OO.ui.Layout} item
+ * @param {string} layout Variable name for layout
+ * @param {string} widget Variable name for layout's field widget
+ * @return {jQuery} Console interface element
+ */
+Demo.prototype.buildConsole = function ( item, layout, widget, showLayoutCode ) {
+ var $toggle, $log, $label, $input, $submit, $console, $form, $pre, $code,
+ console = window.console;
+
+ function exec( str ) {
+ var func, ret;
+ if ( str.indexOf( 'return' ) !== 0 ) {
+ str = 'return ' + str;
+ }
+ try {
+ // eslint-disable-next-line no-new-func
+ func = new Function( layout, widget, 'item', str );
+ ret = { value: func( item, item.fieldWidget, item.fieldWidget ) };
+ } catch ( error ) {
+ ret = {
+ value: undefined,
+ error: error
+ };
+ }
+ return ret;
+ }
+
+ function submit() {
+ var val, result, logval;
+
+ val = $input.val();
+ $input.val( '' );
+ $input[ 0 ].focus();
+ result = exec( val );
+
+ logval = String( result.value );
+ if ( logval === '' ) {
+ logval = '""';
+ }
+
+ $log.append(
+ $( '<div>' )
+ .addClass( 'demo-console-log-line demo-console-log-line-input' )
+ .text( val ),
+ $( '<div>' )
+ .addClass( 'demo-console-log-line demo-console-log-line-return' )
+ .text( logval || result.value )
+ );
+
+ if ( result.error ) {
+ $log.append( $( '<div>' ).addClass( 'demo-console-log-line demo-console-log-line-error' ).text( result.error ) );
+ }
+
+ if ( console && console.log ) {
+ console.log( '[demo]', result.value );
+ if ( result.error ) {
+ if ( console.error ) {
+ console.error( '[demo]', String( result.error ), result.error );
+ } else {
+ console.log( '[demo] Error: ', result.error );
+ }
+ }
+ }
+
+ // Scrol to end
+ $log.prop( 'scrollTop', $log.prop( 'scrollHeight' ) );
+ }
+
+ function getCode( item, toplevel ) {
+ var config, defaultConfig, url, params, out, i,
+ items = [],
+ demoLinks = [],
+ docLinks = [];
+
+ function getConstructorName( item ) {
+ var isDemoWidget = item.constructor.name.indexOf( 'Demo' ) === 0;
+ return ( isDemoWidget ? 'Demo.' : 'OO.ui.' ) + item.constructor.name.slice( 4 );
+ }
+
+ // If no item was passed we shouldn't show a code block
+ if ( item === undefined ) {
+ return false;
+ }
+
+ config = item.initialConfig;
+
+ // Prevent the default config from being part of the code
+ if ( item instanceof OO.ui.ActionFieldLayout ) {
+ defaultConfig = ( new item.constructor( new OO.ui.TextInputWidget(), new OO.ui.ButtonWidget() ) ).initialConfig;
+ } else if ( item instanceof OO.ui.FieldLayout ) {
+ defaultConfig = ( new item.constructor( new OO.ui.ButtonWidget() ) ).initialConfig;
+ } else {
+ defaultConfig = ( new item.constructor() ).initialConfig;
+ }
+ Object.keys( defaultConfig ).forEach( function ( key ) {
+ if ( config[ key ] === defaultConfig[ key ] ) {
+ delete config[ key ];
+ } else if (
+ typeof config[ key ] === 'object' && typeof defaultConfig[ key ] === 'object' &&
+ OO.compare( config[ key ], defaultConfig[ key ] )
+ ) {
+ delete config[ key ];
+ }
+ } );
+
+ config = javascriptStringify( config, function ( obj, indent, stringify ) {
+ if ( obj instanceof Function ) {
+ // Get function's source code, with extraneous indentation removed
+ return obj.toString().replace( /^\t\t\t\t\t\t/gm, '' );
+ } else if ( obj instanceof jQuery ) {
+ if ( $.contains( item.$element[ 0 ], obj[ 0 ] ) ) {
+ // If this element appears inside the generated widget,
+ // assume this was something like `$label: $( '<p>Text</p>' )`
+ return '$( ' + javascriptStringify( obj.prop( 'outerHTML' ) ) + ' )';
+ } else {
+ // Otherwise assume this was something like `$overlay: $( '#overlay' )`
+ return '$( ' + javascriptStringify( '#' + obj.attr( 'id' ) ) + ' )';
+ }
+ } else if ( obj instanceof OO.ui.HtmlSnippet ) {
+ return 'new OO.ui.HtmlSnippet( ' + javascriptStringify( obj.toString() ) + ' )';
+ } else if ( obj instanceof OO.ui.Element ) {
+ return getCode( obj );
+ } else {
+ return stringify( obj );
+ }
+ }, '\t' );
+
+ // The generated code needs to include different arguments, based on the object type
+ items.push( item );
+ if ( item instanceof OO.ui.ActionFieldLayout ) {
+ params = getCode( item.fieldWidget ) + ', ' + getCode( item.buttonWidget );
+ items.push( item.fieldWidget );
+ items.push( item.buttonWidget );
+ } else if ( item instanceof OO.ui.FieldLayout ) {
+ params = getCode( item.fieldWidget );
+ items.push( item.fieldWidget );
+ } else {
+ params = '';
+ }
+ if ( config !== '{}' ) {
+ params += ( params ? ', ' : '' ) + config;
+ }
+ out = 'new ' + getConstructorName( item ) + '(' +
+ ( params ? ' ' : '' ) + params + ( params ? ' ' : '' ) +
+ ')';
+
+ if ( toplevel ) {
+ for ( i = 0; i < items.length; i++ ) {
+ item = items[ i ];
+ // The code generated for Demo widgets cannot be copied and used
+ if ( item.constructor.name.indexOf( 'Demo' ) === 0 ) {
+ url =
+ 'https://phabricator.wikimedia.org/diffusion/GOJU/browse/master/demos/classes/' +
+ item.constructor.name.slice( 4 ) + '.js';
+ demoLinks.push( url );
+ } else {
+ url = 'https://doc.wikimedia.org/oojs-ui/master/js/#!/api/' + getConstructorName( item );
+ url = '[' + url + '](' + url + ')';
+ docLinks.push( url );
+ }
+ }
+ }
+
+ return (
+ ( docLinks.length ? '// See documentation at: \n// ' : '' ) +
+ docLinks.join( '\n// ' ) + ( docLinks.length ? '\n' : '' ) +
+ ( demoLinks.length ? '// See source code:\n// ' : '' ) +
+ demoLinks.join( '\n// ' ) + ( demoLinks.length ? '\n' : '' ) +
+ out
+ );
+ }
+
+ $toggle = $( '<span>' )
+ .addClass( 'demo-console-toggle' )
+ .attr( 'title', 'Toggle console' )
+ .on( 'click', function ( e ) {
+ var code;
+ e.preventDefault();
+ $console.toggleClass( 'demo-console-collapsed demo-console-expanded' );
+ if ( $input.is( ':visible' ) ) {
+ $input[ 0 ].focus();
+ if ( console && console.log ) {
+ window[ layout ] = item;
+ window[ widget ] = item.fieldWidget;
+ console.log( '[demo]', 'Globals ' + layout + ', ' + widget + ' have been set' );
+ console.log( '[demo]', item );
+
+ if ( showLayoutCode === true ) {
+ code = getCode( item, true );
+ } else {
+ code = getCode( item.fieldWidget, true );
+ }
+
+ if ( code ) {
+ $code.text( code );
+ Prism.highlightElement( $code[ 0 ] );
+ } else {
+ $code.remove();
+ }
+ }
+ }
+ } );
+
+ $log = $( '<div>' )
+ .addClass( 'demo-console-log' );
+
+ $label = $( '<label>' )
+ .addClass( 'demo-console-label' );
+
+ $input = $( '<input>' )
+ .addClass( 'demo-console-input' )
+ .prop( 'placeholder', '... (predefined: ' + layout + ', ' + widget + ')' );
+
+ $submit = $( '<div>' )
+ .addClass( 'demo-console-submit' )
+ .text( '↵' )
+ .on( 'click', submit );
+
+ $form = $( '<form>' ).on( 'submit', function ( e ) {
+ e.preventDefault();
+ submit();
+ } );
+
+ $code = $( '<code>' ).addClass( 'language-javascript' );
+
+ $pre = $( '<pre>' )
+ .addClass( 'demo-sample-code' )
+ .append( $code );
+
+ $console = $( '<div>' )
+ .addClass( 'demo-console demo-console-collapsed' )
+ .append(
+ $toggle,
+ $log,
+ $form.append(
+ $label.append(
+ $input
+ ),
+ $submit
+ ),
+ $pre
+ );
+
+ return $console;
+};
+
+/**
+ * Build a link to this example.
+ *
+ * @param {OO.ui.Layout} item
+ * @param {OO.ui.FieldsetLayout} parentItem
+ * @return {jQuery} Link interface element
+ */
+Demo.prototype.buildLinkExample = function ( item, parentItem ) {
+ var $linkExample, label, fragment;
+
+ if ( item.$label.text() === '' ) {
+ item = parentItem;
+ }
+ fragment = item.elementId;
+ if ( !fragment ) {
+ label = item.$label.text();
+ fragment = label.replace( /[^\w]+/g, '-' ).replace( /^-|-$/g, '' );
+ item.setElementId( fragment );
+ }
+
+ $linkExample = $( '<a>' )
+ .addClass( 'demo-link-example' )
+ .attr( 'title', 'Link to this example' )
+ .attr( 'href', '#' + fragment )
+ .on( 'click', function ( e ) {
+ // We have to handle this manually in order to call .scrollToFragment() even if it's the same
+ // fragment. Normally, the browser will scroll but not fire a 'hashchange' event in this
+ // situation, and the scroll position will be off because of our fixed header.
+ if ( e.which === OO.ui.MouseButtons.LEFT ) {
+ location.hash = $( this ).attr( 'href' );
+ Demo.static.scrollToFragment();
+ e.preventDefault();
+ }
+ } );
+
+ return $linkExample;
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/demos.php b/www/wiki/vendor/oojs/oojs-ui/demos/demos.php
new file mode 100644
index 00000000..ab8ba742
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/demos.php
@@ -0,0 +1,165 @@
+<?php
+ define( 'OOUI_DEMOS', true );
+
+ $autoload = __DIR__ . '/vendor/autoload.php';
+ if ( !file_exists( $autoload ) ) {
+ echo '<p>Did you forget to run <code>composer install</code>?</p>';
+ exit();
+ }
+ require_once $autoload;
+ require_once 'classes/ButtonStyleShowcaseWidget.php';
+
+ // @codingStandardsIgnoreStart MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment
+ $themes = [
+ 'wikimediaui' => 'WikimediaUI', // Do not change this line or you'll break `grunt add-theme`
+ 'apex' => 'Apex',
+ ];
+ // @codingStandardsIgnoreEnd MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment
+ $theme = ( isset( $_GET['theme'] ) && isset( $themes[ $_GET['theme'] ] ) )
+ ? $_GET['theme'] : 'wikimediaui';
+ $themeClass = 'OOUI\\' . $themes[ $theme ] . 'Theme';
+ OOUI\Theme::setSingleton( new $themeClass() );
+
+ $direction = ( isset( $_GET['direction'] ) && $_GET['direction'] === 'rtl' ) ? 'rtl' : 'ltr';
+ $directionSuffix = $direction === 'rtl' ? '.rtl' : '';
+ OOUI\Element::setDefaultDir( $direction );
+
+ // We will require_once a file by this name later, so this validation is important
+ $pages = [ 'widgets' ];
+ $page = ( isset( $_GET['page'] ) && in_array( $_GET['page'], $pages ) )
+ ? $_GET['page'] : 'widgets';
+
+ $query = [
+ 'page' => $page,
+ 'theme' => $theme,
+ 'direction' => $direction,
+ ];
+
+ $additionalThemeImagesSuffixes = [
+ 'wikimediaui' => [
+ '-icons-movement',
+ '-icons-content',
+ '-icons-alerts',
+ '-icons-interactions',
+ '-icons-moderation',
+ '-icons-editing-core',
+ '-icons-editing-styling',
+ '-icons-editing-list',
+ '-icons-editing-advanced',
+ '-icons-media',
+ '-icons-location',
+ '-icons-user',
+ '-icons-layout',
+ '-icons-accessibility',
+ '-icons-wikimedia'
+ ],
+ 'apex' => [
+ '-icons-movement',
+ '-icons-content',
+ '-icons-alerts',
+ '-icons-interactions',
+ '-icons-moderation',
+ '-icons-editing-core',
+ '-icons-editing-styling',
+ '-icons-editing-list',
+ '-icons-editing-advanced',
+ '-icons-media',
+ '-icons-location',
+ '-icons-user',
+ '-icons-layout',
+ '-icons-accessibility',
+ '-icons-wikimedia'
+ ]
+ ];
+ // Stylesheets to load
+ $urls = [];
+ $urls[] = "oojs-ui-core-$theme$directionSuffix.css";
+ $urls[] = "oojs-ui-images-$theme$directionSuffix.css";
+ foreach ( $additionalThemeImagesSuffixes[ $theme ] as $suffix ) {
+ $urls[] = "oojs-ui-$theme$suffix$directionSuffix.css";
+ }
+?>
+<!DOCTYPE html>
+<html lang="en" dir="<?php echo $direction; ?>">
+<head>
+ <meta charset="UTF-8">
+ <title>OOUI Widget Demo</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <?php
+ foreach ( $urls as $url ) {
+ echo '<link rel="stylesheet" href="dist/' . htmlspecialchars( $url ) . '">' . "\n";
+ }
+ ?>
+ <link rel="stylesheet" href="styles/demo<?php echo $directionSuffix; ?>.css">
+ <link rel="stylesheet" href="classes/ButtonStyleShowcaseWidget.css">
+</head>
+<body class="oo-ui-<?php echo $direction; ?> oo-ui-theme-<?php echo $theme ?>">
+ <div class="demo">
+ <div class="demo-menu" role="navigation">
+ <?php
+ echo new OOUI\ButtonGroupWidget( [
+ 'infusable' => true,
+ 'items' => array_map( function ( $theme, $themeLabel ) use ( $query ) {
+ return new OOUI\ButtonWidget( [
+ 'label' => $themeLabel,
+ 'href' => '?' . http_build_query( array_merge( $query, [ 'theme' => $theme ] ) ),
+ 'active' => $query['theme'] === $theme,
+ ] );
+ }, array_keys( $themes ), array_values( $themes ) ),
+ ] );
+ echo new OOUI\ButtonGroupWidget( [
+ 'infusable' => true,
+ 'items' => [
+ new OOUI\ButtonWidget( [
+ 'label' => 'LTR',
+ 'href' => '?' . http_build_query( array_merge( $query, [ 'direction' => 'ltr' ] ) ),
+ 'active' => $query['direction'] === 'ltr',
+ ] ),
+ new OOUI\ButtonWidget( [
+ 'label' => 'RTL',
+ 'href' => '?' . http_build_query( array_merge( $query, [ 'direction' => 'rtl' ] ) ),
+ 'active' => $query['direction'] === 'rtl',
+ ] ),
+ ]
+ ] );
+ echo new OOUI\ButtonGroupWidget( [
+ 'infusable' => true,
+ 'id' => 'demo-menu-infuse',
+ 'items' => [
+ new OOUI\ButtonWidget( [
+ 'label' => 'JS',
+ 'href' => '.?' . http_build_query( $query ),
+ 'active' => false,
+ ] ),
+ new OOUI\ButtonWidget( [
+ 'label' => 'PHP',
+ 'href' => '?' . http_build_query( $query ),
+ 'active' => true,
+ ] ),
+ ]
+ ] );
+
+ echo new OOUI\ButtonWidget( [
+ 'label' => 'Docs',
+ 'icon' => 'journal',
+ 'href' => '../php/',
+ 'flags' => [ 'progressive' ],
+ ] );
+ ?>
+ </div>
+ <?php
+ // $page is validated above
+ require_once "pages/$page.php";
+ ?>
+ </div>
+
+ <!-- Demonstrate JavaScript "infusion" of PHP widgets -->
+ <script src="node_modules/jquery/dist/jquery.js"></script>
+ <script src="node_modules/oojs/dist/oojs.jquery.js"></script>
+ <script src="dist/oojs-ui-core.js"></script>
+ <script src="dist/oojs-ui-<?php echo $theme; ?>.js"></script>
+ <script>window.Demo = {};</script>
+ <script src="classes/ButtonStyleShowcaseWidget.js"></script>
+ <script src="infusion.js"></script>
+</body>
+</html>
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/index.html b/www/wiki/vendor/oojs/oojs-ui/demos/index.html
new file mode 100644
index 00000000..b8d17e85
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/index.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
+<head>
+ <meta charset="UTF-8">
+ <title>OOUI Demos</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link rel="stylesheet" href="classes/ButtonStyleShowcaseWidget.css">
+ <link rel="stylesheet" href="classes/SimpleWidget.css">
+ <link rel="stylesheet" href="classes/FloatableTest.css">
+ <link rel="stylesheet" href="classes/PositionSelectWidget.css">
+ <link rel="stylesheet" href="node_modules/prismjs/themes/prism.css">
+</head>
+<body>
+ <script src="node_modules/jquery/dist/jquery.js"></script>
+ <script src="node_modules/oojs/dist/oojs.jquery.js"></script>
+ <script src="node_modules/prismjs/prism.js"></script>
+ <script src="node_modules/prismjs/plugins/autolinker/prism-autolinker.js"></script>
+ <script src="node_modules/javascript-stringify/javascript-stringify.js"></script>
+ <!-- Add the individual oojs-ui files for proper sourcemap support -->
+ <script src="dist/oojs-ui-core.js"></script>
+ <script src="dist/oojs-ui-toolbars.js"></script>
+ <script src="dist/oojs-ui-widgets.js"></script>
+ <script src="dist/oojs-ui-windows.js"></script>
+ <script src="dist/oojs-ui-wikimediaui.js"></script> <!-- Do not change this line or you'll break `grunt add-theme` -->
+ <script src="dist/oojs-ui-apex.js"></script>
+ <script src="demo.js"></script>
+ <script src="classes/ButtonStyleShowcaseWidget.js"></script>
+ <script src="classes/CapsuleNumberPopupMultiselectWidget.js"></script>
+ <script src="classes/SimpleWidget.js"></script>
+ <script src="classes/DraggableGroupWidget.js"></script>
+ <script src="classes/DraggableItemWidget.js"></script>
+ <script src="classes/DraggableHandledItemWidget.js"></script>
+ <script src="classes/DynamicLabelTextInputWidget.js"></script>
+ <script src="classes/NumberLookupTextInputWidget.js"></script>
+ <script src="classes/UnsupportedSelectFileWidget.js"></script>
+ <script src="classes/BookletDialog.js"></script>
+ <script src="classes/BrokenDialog.js"></script>
+ <script src="classes/ContinuousOutlinedBookletDialog.js"></script>
+ <script src="classes/DialogWithDropdowns.js"></script>
+ <script src="classes/DialogWithPopupAndDropdown.js"></script>
+ <script src="classes/FloatableTest.js"></script>
+ <script src="classes/FloatableWidget.js"></script>
+ <script src="classes/IndexedDialog.js"></script>
+ <script src="classes/LongProcessDialog.js"></script>
+ <script src="classes/MenuDialog.js"></script>
+ <script src="classes/OutlinedBookletDialog.js"></script>
+ <script src="classes/PopupButtonWidgetTest.js"></script>
+ <script src="classes/PositionSelectWidget.js"></script>
+ <script src="classes/ProcessDialog.js"></script>
+ <script src="classes/SampleTabPanel.js"></script>
+ <script src="classes/SamplePage.js"></script>
+ <script src="classes/SearchWidgetDialog.js"></script>
+ <script src="classes/SimpleDialog.js"></script>
+ <script src="classes/DelayedReadyProcessDialog.js"></script>
+ <script src="classes/FailedReadyProcessDialog.js"></script>
+ <script src="classes/FailedSetupProcessDialog.js"></script>
+ <script src="pages/dialogs.js"></script>
+ <script src="pages/icons.js"></script>
+ <script src="pages/widgets.js"></script>
+ <script src="pages/toolbars.js"></script>
+ <script>
+ $( function () {
+ var demo, lastQuery = location.search;
+
+ OO.ui.isDemo = true;
+
+ function setup() {
+ var
+ prevPage = demo ? demo.mode.page : null,
+ scrollPos = $( window ).scrollTop();
+ if ( demo ) {
+ if ( lastQuery === location.search ) {
+ return false;
+ }
+ demo.destroy();
+ }
+ lastQuery = location.search;
+ demo = new Demo();
+ $( 'body' ).append( demo.$element );
+ demo.initialize().done( function () {
+ if ( prevPage === demo.mode.page && scrollPos ) {
+ // Restore scroll position from before we destroyed the demo
+ $( window ).scrollTop( scrollPos );
+ } else {
+ Demo.static.scrollToFragment();
+ }
+ } );
+ }
+
+ setup();
+
+ $( window ).on( 'popstate', setup );
+ $( window ).on( 'hashchange', Demo.static.scrollToFragment );
+ } )
+ </script>
+</body>
+</html>
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/infusion.js b/www/wiki/vendor/oojs/oojs-ui/demos/infusion.js
new file mode 100644
index 00000000..1374b9a2
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/infusion.js
@@ -0,0 +1,44 @@
+// Demonstrate JavaScript 'infusion' of PHP-generated widgets.
+// Used by widgets.php.
+
+var infuseButton, $demoMenu;
+
+// Helper function to get high resolution profiling data, where available.
+function now() {
+ return ( window.performance && performance.now ) ? performance.now() :
+ Date.now ? Date.now() : new Date().getTime();
+}
+
+// Add a button to infuse everything!
+// (You wouldn't typically do this: you'd only infuse those objects which you needed to attach
+// client-side behaviors to, or where the JS implementation provides additional features over PHP,
+// like DropdownInputWidget. We do it here because it's a good overall test.)
+function infuseAll() {
+ var start, end;
+ start = now();
+ $( '*[data-ooui]' ).map( function ( _, e ) {
+ return OO.ui.infuse( e.id );
+ } );
+ end = now();
+ window.console.log( 'Took ' + ( end - start ) + ' ms to infuse demo page.' );
+ infuseButton.setDisabled( true );
+}
+
+$demoMenu = $( '.demo-menu' );
+
+OO.ui.getViewportSpacing = function () {
+ return {
+ top: $demoMenu.outerHeight(),
+ right: 0,
+ bottom: 0,
+ left: 0
+ };
+};
+
+// More typical usage: we take the existing server-side
+// button group and do things to it, here adding a new button.
+infuseButton = new OO.ui.ButtonWidget( { label: 'Infuse' } )
+ .on( 'click', infuseAll );
+
+OO.ui.ButtonGroupWidget.static.infuse( 'demo-menu-infuse' )
+ .addItems( [ infuseButton ] );
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/pages/dialogs.js b/www/wiki/vendor/oojs/oojs-ui/demos/pages/dialogs.js
new file mode 100644
index 00000000..e55e4e70
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/pages/dialogs.js
@@ -0,0 +1,333 @@
+Demo.static.pages.dialogs = function ( demo ) {
+ var i, j, name, openButton, fieldset, examples, DialogClass, config,
+ $demo = demo.$element,
+ $fieldsets = $( [] ),
+ windows = {},
+ windowManager = new OO.ui.WindowManager();
+
+ config = [
+ {
+ name: 'Convenience functions',
+ examples: [
+ {
+ name: 'Quick alert',
+ method: 'alert',
+ param: 'Alert message.'
+ },
+ {
+ name: 'Larger alert',
+ method: 'alert',
+ param: 'Alert message.',
+ data: { size: 'larger' }
+ },
+ {
+ name: 'Quick confirm',
+ method: 'confirm',
+ param: 'Confirmation message?'
+ },
+ {
+ name: 'Quick prompt',
+ method: 'prompt',
+ param: 'Text prompt:'
+ }
+ ]
+ },
+ {
+ name: 'Dialog interface',
+ examples: [
+ {
+ name: 'Simple dialog (small)',
+ config: {
+ size: 'small'
+ }
+ },
+ {
+ name: 'Simple dialog (medium)',
+ config: {
+ size: 'medium'
+ }
+ },
+ {
+ name: 'Simple dialog (large)',
+ config: {
+ size: 'large'
+ }
+ },
+ {
+ name: 'Simple dialog (larger)',
+ config: {
+ size: 'larger'
+ }
+ },
+ {
+ name: 'Simple dialog (full)',
+ config: {
+ size: 'full'
+ }
+ },
+ {
+ name: 'Simple dialog (delayed ready process)',
+ dialogClass: Demo.DelayedReadyProcessDialog,
+ config: {
+ size: 'large'
+ }
+ },
+ {
+ name: 'Simple dialog (failed ready process)',
+ dialogClass: Demo.FailedReadyProcessDialog,
+ config: {
+ size: 'large'
+ }
+ },
+ {
+ name: 'Simple dialog (failed setup process)',
+ dialogClass: Demo.FailedSetupProcessDialog,
+ config: {
+ size: 'large'
+ }
+ },
+ {
+ name: 'Process dialog (medium)',
+ dialogClass: Demo.ProcessDialog,
+ config: {
+ size: 'medium'
+ }
+ },
+ {
+ name: 'Process dialog (medium, long title)',
+ dialogClass: Demo.ProcessDialog,
+ config: {
+ size: 'medium'
+ },
+ data: {
+ title: 'Sample dialog with very long title that does not remotely fit into the space available and thus demonstrates what happens in that use case'
+ }
+ },
+ {
+ name: 'Process dialog (medium, long)',
+ dialogClass: Demo.LongProcessDialog,
+ config: {
+ size: 'medium'
+ }
+ },
+ {
+ name: 'Process dialog (full)',
+ dialogClass: Demo.ProcessDialog,
+ config: {
+ size: 'full'
+ }
+ },
+ {
+ name: 'Broken dialog (error handling)',
+ dialogClass: Demo.BrokenDialog,
+ config: {
+ size: 'medium'
+ }
+ },
+ {
+ name: 'Message dialog (generic)',
+ dialogClass: OO.ui.MessageDialog,
+ data: {
+ title: 'Continue?',
+ message: 'It may be risky'
+ }
+ },
+ {
+ name: 'Message dialog (lengthy)',
+ dialogClass: OO.ui.MessageDialog,
+ data: {
+ title: 'Continue?',
+ message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque quis laoreet elit. Nam eu velit ullamcorper, volutpat elit sed, viverra massa. Aenean congue aliquam lorem, et laoreet risus condimentum vel. Praesent nec imperdiet mauris. Nunc eros magna, iaculis sit amet ante id, dapibus tristique lorem. Praesent in feugiat lorem, sit amet porttitor eros. Donec sapien turpis, pretium eget ligula id, scelerisque tincidunt diam. Pellentesque a venenatis tortor, at luctus nisl. Quisque vel urna a enim mattis rutrum. Morbi eget consequat nisl. Nam tristique molestie diam ac consequat. Nam varius adipiscing mattis. Praesent sodales volutpat nulla lobortis iaculis. Quisque vel odio eget diam posuere imperdiet. Fusce et iaculis odio. Donec in nibh ut dui accumsan vehicula quis et massa.'
+ }
+ },
+ {
+ name: 'Message dialog (1 action)',
+ dialogClass: OO.ui.MessageDialog,
+ data: {
+ title: 'Storage limit reached',
+ message: 'You are out of disk space',
+ actions: [
+ {
+ action: 'accept',
+ label: 'Dismiss',
+ flags: 'primary'
+ }
+ ]
+ }
+ },
+ {
+ name: 'Message dialog (2 actions)',
+ dialogClass: OO.ui.MessageDialog,
+ data: {
+ title: 'Cannot save data',
+ message: 'The server is not responding',
+ actions: [
+ {
+ action: 'reject',
+ label: 'Cancel',
+ flags: [ 'safe', 'back' ]
+ },
+ {
+ action: 'repeat',
+ label: 'Try again',
+ flags: [ 'primary', 'progressive' ]
+ }
+ ]
+ }
+ },
+ {
+ name: 'Message dialog (3 actions)',
+ dialogClass: OO.ui.MessageDialog,
+ data: {
+ title: 'Delete file?',
+ message: 'The file will be irreversably obliterated. Proceed with caution.',
+ actions: [
+ { action: 'reject', label: 'Cancel', flags: [ 'safe', 'back' ] },
+ { action: 'reject', label: 'Move file to trash' },
+ {
+ action: 'accept',
+ label: 'Obliterate',
+ flags: [ 'primary', 'destructive' ]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ name: 'Elements best used inside dialogs',
+ examples: [
+ {
+ name: 'Search widget dialog (medium)',
+ dialogClass: Demo.SearchWidgetDialog,
+ config: {
+ size: 'medium'
+ }
+ },
+ {
+ name: 'Booklet dialog',
+ dialogClass: Demo.BookletDialog,
+ config: {
+ size: 'medium'
+ }
+ },
+ {
+ name: 'Outlined booklet dialog (aside navigation)',
+ dialogClass: Demo.OutlinedBookletDialog,
+ config: {
+ size: 'medium'
+ }
+ },
+ {
+ name: 'Continuous outlined booklet dialog (aside navigation)',
+ dialogClass: Demo.ContinuousOutlinedBookletDialog,
+ config: {
+ size: 'medium'
+ }
+ },
+ {
+ name: 'Indexed dialog (tab navigation)',
+ dialogClass: Demo.IndexedDialog,
+ config: {
+ size: 'medium'
+ }
+ },
+ {
+ name: 'Menu dialog',
+ dialogClass: Demo.MenuDialog,
+ config: {
+ size: 'medium'
+ }
+ }
+ ]
+ },
+ {
+ name: 'Low-level test cases',
+ examples: [
+ {
+ name: 'FloatableElement test',
+ dialogClass: Demo.FloatableTest,
+ config: {
+ size: 'medium'
+ }
+ },
+ {
+ name: 'Dialog with dropdowns ($overlay test)',
+ dialogClass: Demo.DialogWithDropdowns,
+ config: {
+ size: 'large'
+ }
+ },
+ {
+ name: 'PopupButtonWidget test',
+ dialogClass: Demo.PopupButtonWidgetTest,
+ config: {
+ size: 'large'
+ }
+ },
+ {
+ name: 'Dialog with popup and dropdown (ClippableElement test)',
+ dialogClass: Demo.DialogWithPopupAndDropdown,
+ config: {
+ size: 'large'
+ }
+ }
+ ]
+ }
+ ];
+
+ function openDialog( name, data ) {
+ windowManager.openWindow( name, data );
+ }
+
+ for ( j = 0; j < config.length; j++ ) {
+ fieldset = new OO.ui.FieldsetLayout( { label: config[ j ].name } );
+ examples = config[ j ].examples;
+ $fieldsets = $fieldsets.add( fieldset.$element );
+
+ for ( i = 0; i < examples.length; i++ ) {
+ openButton = new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'window',
+ label: $( '<span dir="ltr"></span>' ).text( examples[ i ].name )
+ } );
+
+ if ( examples[ i ].method ) {
+ openButton.on(
+ 'click', OO.ui.bind(
+ OO.ui,
+ examples[ i ].method,
+ examples[ i ].param,
+ examples[ i ].data
+ )
+ );
+ } else {
+ name = 'window_' + j + '_' + i;
+ DialogClass = examples[ i ].dialogClass || Demo.SimpleDialog;
+ windows[ name ] = new DialogClass( examples[ i ].config );
+ openButton.on(
+ 'click', OO.ui.bind( openDialog, this, name, examples[ i ].data )
+ );
+ }
+
+ fieldset.addItems( [ new OO.ui.FieldLayout( openButton, { align: 'inline' } ) ] );
+ }
+ }
+ windowManager.addWindows( windows );
+
+ $demo.append(
+ new OO.ui.PanelLayout( {
+ expanded: false,
+ framed: true
+ } ).$element
+ .addClass( 'demo-container' )
+ .attr( 'role', 'main' )
+ .append( $fieldsets ),
+ windowManager.$element
+ );
+
+ demo.once( 'destroy', function () {
+ windowManager.destroy();
+ OO.ui.getWindowManager().closeWindow( OO.ui.getWindowManager().getCurrentWindow() );
+ } );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/pages/icons.js b/www/wiki/vendor/oojs/oojs-ui/demos/pages/icons.js
new file mode 100644
index 00000000..cea76145
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/pages/icons.js
@@ -0,0 +1,302 @@
+Demo.static.pages.icons = function ( demo ) {
+ var i, len, iconSet, iconsFieldset, iconWidget, selector,
+ icons = {
+ movement: [
+ 'arrowPrevious',
+ 'arrowNext',
+ 'downTriangle',
+ 'upTriangle',
+ 'first',
+ 'previous',
+ 'next',
+ 'last',
+ 'expand',
+ 'collapse',
+ 'move',
+ 'draggable'
+ ],
+ content: [
+ 'article',
+ 'articles',
+ 'articleCheck',
+ 'articleSearch',
+ 'articleRedirect',
+ 'citeArticle',
+ 'book',
+ 'history',
+ 'info',
+ 'journal',
+ 'newspaper',
+ 'folderPlaceholder',
+ 'die',
+ 'download',
+ 'tag',
+ 'upload',
+ 'window'
+ ],
+ alerts: [
+ 'alert',
+ 'bell',
+ 'comment',
+ 'message',
+ 'notice',
+ 'speechBubble',
+ 'speechBubbleAdd',
+ 'speechBubbles',
+ 'tray'
+ ],
+ interactions: [
+ 'add',
+ 'advanced',
+ 'browser',
+ 'cancel',
+ 'check',
+ 'checkAll',
+ 'clear',
+ 'clock',
+ 'close',
+ 'ellipsis',
+ 'feedback',
+ 'funnel',
+ 'heart',
+ 'help',
+ 'key',
+ 'keyboard',
+ 'lightbulb',
+ 'logOut',
+ 'newWindow',
+ 'printer',
+ 'reload',
+ 'search',
+ 'settings',
+ 'subtract'
+ ],
+ moderation: [
+ 'bookmarkOutline',
+ 'bookmark',
+ 'block',
+ 'unBlock',
+ 'flag',
+ 'unFlag',
+ 'lock',
+ 'unLock',
+ 'star',
+ 'halfStar',
+ 'unStar',
+ 'trash',
+ 'unTrash',
+ 'pushPin',
+ 'ongoingConversation'
+ ],
+ 'editing-core': [
+ 'edit',
+ 'editLock',
+ 'editUndo',
+ 'link',
+ 'linkExternal',
+ 'linkSecure',
+ 'redo',
+ 'undo'
+ ],
+ 'editing-styling': [
+ 'bigger',
+ 'smaller',
+ 'subscript',
+ 'superscript',
+ 'bold',
+ 'highlight',
+ 'italic',
+ 'strikethrough',
+ 'underline',
+ 'textDirLTR',
+ 'textDirRTL',
+ 'textStyle'
+ ],
+ 'editing-list': [
+ 'indent',
+ 'listBullet',
+ 'listNumbered',
+ 'outdent'
+ ],
+ 'editing-advanced': [
+ 'alignCenter',
+ 'alignLeft',
+ 'alignRight',
+ 'attachment',
+ 'calendar',
+ 'code',
+ 'find',
+ 'language',
+ 'layout',
+ 'markup',
+ 'newline',
+ 'noWikiText',
+ 'outline',
+ 'puzzle',
+ 'quotes',
+ 'searchCaseSensitive',
+ 'searchDiacritics',
+ 'searchRegularExpression',
+ 'signature',
+ 'specialCharacter',
+ 'table',
+ 'tableAddColumnAfter',
+ 'tableAddColumnBefore',
+ 'tableAddRowAfter',
+ 'tableAddRowBefore',
+ 'tableCaption',
+ 'tableMergeCells',
+ 'tableMoveColumnAfter',
+ 'tableMoveColumnBefore',
+ 'tableMoveRowAfter',
+ 'tableMoveRowBefore',
+ 'templateAdd',
+ 'wikiText'
+ ],
+ media: [
+ 'fullScreen',
+ 'exitFullscreen',
+ 'image',
+ 'imageAdd',
+ 'imageLock',
+ 'imageGallery',
+ 'imageBroken',
+ 'play',
+ 'pause',
+ 'stop'
+ ],
+ location: [
+ 'map',
+ 'mapPin',
+ 'mapPinAdd',
+ 'mapTrail'
+ ],
+ user: [
+ 'userAnonymous',
+ 'userAvatar',
+ 'userTalk'
+ ],
+ layout: [
+ 'menu',
+ 'stripeFlow',
+ 'stripeSummary',
+ 'stripeToC',
+ 'viewCompact',
+ 'viewDetails'
+ ],
+ accessibility: [
+ 'bright',
+ 'halfBright',
+ 'notBright',
+ 'eye',
+ 'eyeClosed',
+ 'moon',
+ 'largerText',
+ 'smallerText',
+ 'visionSimulator'
+ ],
+ wikimedia: [
+ 'logoCC',
+ 'logoWikimediaCommons',
+ 'logoWikimediaDiscovery',
+ 'logoWikipedia'
+ ]
+ },
+ indicators = [
+ 'clear',
+ 'down',
+ 'required',
+ 'search',
+ 'up'
+ ],
+ iconsFieldsets = [],
+ iconsWidgets = [],
+ indicatorsFieldset = new OO.ui.FieldsetLayout( { label: 'Indicators' } );
+
+ for ( i = 0, len = indicators.length; i < len; i++ ) {
+ indicatorsFieldset.addItems( [
+ new OO.ui.FieldLayout(
+ new OO.ui.IndicatorWidget( {
+ indicator: indicators[ i ],
+ title: indicators[ i ]
+ } ),
+ {
+ align: 'inline',
+ label: indicators[ i ]
+ }
+ )
+ ] );
+ }
+ for ( iconSet in icons ) {
+ iconsFieldset = new OO.ui.FieldsetLayout( { label: 'Icons – ' + iconSet } );
+ iconsFieldsets.push( iconsFieldset );
+
+ for ( i = 0, len = icons[ iconSet ].length; i < len; i++ ) {
+ iconWidget = new OO.ui.IconWidget( {
+ icon: icons[ iconSet ][ i ],
+ title: icons[ iconSet ][ i ]
+ } );
+ iconsWidgets.push( iconWidget );
+ iconsFieldset.addItems( [
+ new OO.ui.FieldLayout( iconWidget, {
+ label: icons[ iconSet ][ i ],
+ align: 'inline'
+ } )
+ ] );
+ }
+ }
+
+ selector = new OO.ui.ButtonSelectWidget( {
+ items: [
+ new OO.ui.ButtonOptionWidget( {
+ label: 'None',
+ flags: [],
+ data: {
+ progressive: false,
+ destructive: false
+ }
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ label: 'Progressive',
+ flags: [ 'progressive' ],
+ data: {
+ progressive: true,
+ destructive: false
+ }
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ label: 'Destructive',
+ flags: [ 'destructive' ],
+ data: {
+ progressive: false,
+ destructive: true
+ }
+ } )
+ ]
+ } );
+
+ selector
+ .on( 'select', function ( selected ) {
+ iconsWidgets.forEach( function ( iconWidget ) {
+ iconWidget.setFlags( selected.getData() );
+ } );
+ } )
+ .selectItemByData( {
+ progressive: false,
+ destructive: false
+ } );
+
+ demo.$element.append(
+ new OO.ui.PanelLayout( {
+ expanded: false,
+ framed: true
+ } ).$element
+ .addClass( 'demo-container demo-icons' )
+ .attr( 'role', 'main' )
+ .append(
+ selector.$element,
+ indicatorsFieldset.$element,
+ iconsFieldsets.map( function ( item ) { return item.$element[ 0 ]; } )
+ )
+ );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/pages/toolbars.js b/www/wiki/vendor/oojs/oojs-ui/demos/pages/toolbars.js
new file mode 100644
index 00000000..c7061182
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/pages/toolbars.js
@@ -0,0 +1,588 @@
+Demo.static.pages.toolbars = function ( demo ) {
+ var i, toolGroups, actionButton, actionButtonDelete, actionButtonDisabled, actionGroup, publishButton, AlertTool, PopupTool, ToolGroupTool,
+ setDisabled = function () { this.setDisabled( true ); },
+ $demo = demo.$element,
+ $containers = $(),
+ toolFactories = [],
+ toolGroupFactories = [],
+ toolbars = [],
+ configs = [
+ {},
+ { actions: true },
+ {},
+ { actions: true },
+ { position: 'bottom' },
+ { actions: true, position: 'bottom' },
+ {},
+ { actions: true }
+ ];
+
+ // Show some random accelerator keys that don't actually work
+ function getToolAccelerator( name ) {
+ return {
+ listTool1: 'Ctrl+Shift+1',
+ listTool2: 'Ctrl+Alt+2',
+ listTool3: 'Cmd+Enter',
+ listTool5: 'Shift+Down',
+ menuTool: 'Ctrl+M'
+ }[ name ];
+ }
+
+ for ( i = 0; i <= 7; i++ ) {
+ toolFactories.push( new OO.ui.ToolFactory() );
+ toolGroupFactories.push( new OO.ui.ToolGroupFactory() );
+ toolbars.push( new OO.ui.Toolbar( toolFactories[ i ], toolGroupFactories[ i ], configs[ i ] ) );
+ toolbars[ i ].getToolAccelerator = getToolAccelerator;
+ }
+
+ function createTool( toolbar, group, name, icon, title, init, onSelect, displayBothIconAndLabel ) {
+ var Tool = function () {
+ Tool.parent.apply( this, arguments );
+ this.toggled = false;
+ if ( init ) {
+ init.call( this );
+ }
+ };
+
+ OO.inheritClass( Tool, OO.ui.Tool );
+
+ Tool.prototype.onSelect = function () {
+ if ( onSelect ) {
+ onSelect.call( this );
+ } else {
+ this.toggled = !this.toggled;
+ this.setActive( this.toggled );
+ }
+ toolbars[ toolbar ].emit( 'updateState' );
+ };
+ Tool.prototype.onUpdateState = function () {};
+
+ Tool.static.name = name;
+ Tool.static.group = group;
+ Tool.static.icon = icon;
+ Tool.static.title = title;
+ Tool.static.displayBothIconAndLabel = !!displayBothIconAndLabel;
+ return Tool;
+ }
+
+ function createToolGroup( toolbar, group ) {
+ $.each( toolGroups[ group ], function ( i, tool ) {
+ var args = tool.slice();
+ args.splice( 0, 0, toolbar, group );
+ toolFactories[ toolbar ].register( createTool.apply( null, args ) );
+ } );
+ }
+
+ function createDisabledToolGroup( parent, name ) {
+ var DisabledToolGroup = function () {
+ DisabledToolGroup.parent.apply( this, arguments );
+ this.setDisabled( true );
+ };
+
+ OO.inheritClass( DisabledToolGroup, parent );
+
+ DisabledToolGroup.static.name = name;
+
+ DisabledToolGroup.prototype.onUpdateState = function () {
+ this.setLabel( 'Disabled' );
+ };
+
+ return DisabledToolGroup;
+ }
+
+ toolGroupFactories[ 0 ].register( createDisabledToolGroup( OO.ui.BarToolGroup, 'disabledBar' ) );
+ toolGroupFactories[ 0 ].register( createDisabledToolGroup( OO.ui.ListToolGroup, 'disabledList' ) );
+ toolGroupFactories[ 1 ].register( createDisabledToolGroup( OO.ui.MenuToolGroup, 'disabledMenu' ) );
+
+ AlertTool = function ( toolGroup, config ) {
+ // Parent constructor
+ OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {
+ padded: true,
+ label: 'Alert head',
+ head: true
+ } }, config ) );
+
+ this.popup.$body.append( '<p>Alert contents</p>' );
+ };
+
+ OO.inheritClass( AlertTool, OO.ui.PopupTool );
+
+ AlertTool.static.name = 'alertTool';
+ AlertTool.static.group = 'popupTools';
+ AlertTool.static.icon = 'alert';
+
+ toolFactories[ 2 ].register( AlertTool );
+ toolFactories[ 4 ].register( AlertTool );
+
+ PopupTool = function ( toolGroup, config ) {
+ // Parent constructor
+ OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {
+ padded: true,
+ label: 'Popup head',
+ head: true
+ } }, config ) );
+
+ this.popup.$body.append( '<p>Popup contents</p>' );
+ };
+
+ OO.inheritClass( PopupTool, OO.ui.PopupTool );
+
+ PopupTool.static.name = 'popupTool';
+ PopupTool.static.group = 'popupTools';
+ PopupTool.static.icon = 'help';
+
+ toolFactories[ 2 ].register( PopupTool );
+ toolFactories[ 4 ].register( PopupTool );
+
+ ToolGroupTool = function ( toolGroup, config ) {
+ // Parent constructor
+ OO.ui.ToolGroupTool.call( this, toolGroup, config );
+ };
+
+ OO.inheritClass( ToolGroupTool, OO.ui.ToolGroupTool );
+
+ ToolGroupTool.static.name = 'toolGroupTool';
+ ToolGroupTool.static.group = 'barTools';
+ ToolGroupTool.static.groupConfig = {
+ label: 'More',
+ include: [ { group: 'moreListTools' } ]
+ };
+
+ toolFactories[ 0 ].register( ToolGroupTool );
+ toolFactories[ 3 ].register( ToolGroupTool );
+ toolFactories[ 5 ].register( ToolGroupTool );
+
+ // Toolbars setup, in order of toolbar items appearance
+ // Toolbar
+ toolbars[ 0 ].setup( [
+ {
+ type: 'bar',
+ include: [ { group: 'barTools' } ],
+ demote: [ 'toolGroupTool' ]
+ },
+ {
+ type: 'disabledBar',
+ include: [ { group: 'disabledBarTools' } ]
+ },
+ {
+ type: 'list',
+ label: 'List',
+ icon: 'image',
+ include: [ { group: 'listTools' } ],
+ allowCollapse: [ 'listTool1', 'listTool6' ]
+ },
+ {
+ type: 'disabledList',
+ label: 'List',
+ icon: 'image',
+ include: [ { group: 'disabledListTools' } ]
+ },
+ {
+ type: 'list',
+ label: 'Auto-disabling list',
+ icon: 'image',
+ include: [ { group: 'autoDisableListTools' } ]
+ },
+ {
+ label: 'Catch-all',
+ include: '*'
+ }
+ ] );
+ // Toolbar with action buttons
+ toolbars[ 1 ].setup( [
+ {
+ type: 'menu',
+ header: 'Popup-/MenuToolGroup header',
+ icon: 'image',
+ include: [ { group: 'menuTools' } ]
+ },
+ {
+ type: 'disabledMenu',
+ icon: 'image',
+ include: [ { group: 'disabledMenuTools' } ]
+ },
+ {
+ type: 'bar',
+ include: [ { group: 'cite' } ]
+ },
+ {
+ type: 'bar',
+ include: [ { group: 'citeDisabled' } ]
+ }
+ ] );
+ // Action toolbar for toolbars[ 3 ] below
+ toolbars[ 2 ].setup( [
+ {
+ include: [ { group: 'popupTools' } ]
+ },
+ {
+ type: 'list',
+ icon: 'menu',
+ indicator: '',
+ include: [ { group: 'overflowTools' } ]
+ },
+ {
+ type: 'list',
+ icon: 'edit',
+ include: [ { group: 'editorSwitchTools' } ]
+ }
+ ] );
+ // Word processor toolbar
+ toolbars[ 3 ].setup( [
+ {
+ type: 'bar',
+ include: [ { group: 'history' } ]
+ },
+ {
+ type: 'menu',
+ include: [ { group: 'formatTools' } ]
+ },
+ {
+ type: 'list',
+ icon: 'textStyle',
+ include: [ { group: 'styleTools' } ]
+ },
+ {
+ type: 'bar',
+ include: [ { group: 'link' } ]
+ },
+ {
+ type: 'bar',
+ include: [ { group: 'cite' } ]
+ },
+ {
+ type: 'bar',
+ include: [ { group: 'citeDisabled' } ]
+ },
+ {
+ type: 'list',
+ icon: 'listBullet',
+ include: [ { group: 'structureTools' } ]
+ },
+ {
+ type: 'list',
+ label: 'Insert',
+ include: [ { group: 'insertTools' }, { group: 'autoDisableListTools' }, { group: 'unusedStuff' } ],
+ allowCollapse: [ 'comment', 'hieroglyphs', 'score', 'signature', 'gallery', 'chem', 'math', 'syntaxHighlightDialog', 'graph', 'referencesList' ]
+ },
+ {
+ type: 'bar',
+ include: [ { group: 'specialCharacters' } ]
+ }
+ ] );
+ // Action toolbar for toolbars[ 5 ] below
+ toolbars[ 4 ].setup( [
+ {
+ include: [ { group: 'popupTools' } ]
+ },
+ {
+ include: [ { group: 'alertTools' } ]
+ },
+ {
+ type: 'list',
+ icon: 'menu',
+ indicator: '',
+ include: [ { group: 'overflowTools' } ]
+ },
+ {
+ type: 'list',
+ icon: 'edit',
+ include: [ { group: 'editorSwitchTools' } ]
+ }
+ ] );
+ // Word processor toolbar set to `position: 'bottom'`
+ toolbars[ 5 ].setup( [
+ {
+ type: 'bar',
+ include: [ { group: 'history' } ]
+ },
+ {
+ type: 'menu',
+ include: [ { group: 'formatTools' } ]
+ },
+ {
+ type: 'list',
+ icon: 'textStyle',
+ include: [ { group: 'styleTools' } ]
+ },
+ {
+ type: 'bar',
+ include: [ { group: 'link' } ]
+ },
+ {
+ type: 'bar',
+ include: [ { group: 'cite' } ]
+ },
+ {
+ type: 'bar',
+ include: [ { group: 'citeDisabled' } ]
+ },
+ {
+ type: 'list',
+ icon: 'listBullet',
+ include: [ { group: 'structureTools' } ]
+ },
+ {
+ type: 'list',
+ label: 'Insert',
+ include: [ { group: 'insertTools' }, { group: 'autoDisableListTools' }, { group: 'unusedStuff' } ]
+ },
+ {
+ type: 'bar',
+ include: [ { group: 'specialCharacters' } ]
+ }
+ ] );
+ // Action toolbar for toolbars[7]
+ toolbars[ 6 ].setup( [
+ {
+ type: 'list',
+ indicator: 'down',
+ flags: [ 'primary', 'progressive' ],
+ include: [ { group: 'listTools' } ]
+ }
+ ] );
+ // Toolbar with action buttons, in a ButtonGroup
+ toolbars[ 7 ].setup( [
+ {
+ type: 'menu',
+ icon: 'image',
+ include: [ { group: 'menuTools' } ]
+ },
+ {
+ type: 'disabledMenu',
+ icon: 'image',
+ include: [ { group: 'disabledMenuTools' } ]
+ }
+ ] );
+
+ actionButton = new OO.ui.ButtonWidget( { label: 'Action' } );
+ actionButtonDisabled = new OO.ui.ButtonWidget( { label: 'Disabled', disabled: true } );
+ toolbars[ 1 ].$actions.append( actionButton.$element, actionButtonDisabled.$element );
+
+ for ( i = 3; i <= 5; i += 2 ) {
+ publishButton = new OO.ui.ButtonWidget( { label: 'Publish changes', flags: [ 'progressive', 'primary' ] } );
+ toolbars[ i ].$actions.append( toolbars[ i - 1 ].$element, publishButton.$element );
+ }
+
+ actionButtonDelete = new OO.ui.ButtonWidget( { label: 'Delete', flags: [ 'destructive' ] } );
+ publishButton = new OO.ui.ButtonWidget( { label: 'Publish changes', flags: [ 'progressive', 'primary' ] } );
+ actionGroup = new OO.ui.ButtonGroupWidget( {
+ items: [ actionButtonDelete, publishButton, toolbars[ 6 ].items[ 0 ] ]
+ } );
+ toolbars[ 7 ].$actions.append( actionGroup.$element );
+
+ for ( i = 0; i < toolbars.length; i++ ) {
+ toolbars[ i ].emit( 'updateState' );
+ }
+
+ // ToolGroups definition, in alphabetical/disabledAlphabetical order
+ toolGroups = {
+ barTools: [
+ [ 'barTool', 'image', 'Basic tool in bar' ],
+ [ 'disabledBarTool', 'image', 'Basic tool in bar disabled', setDisabled ]
+ ],
+
+ disabledBarTools: [
+ [ 'barToolInDisabled', 'image', 'Basic tool in disabled bar' ]
+ ],
+
+ cite: [
+ [ 'citeTool', 'quotes', 'Cite', null, null, true ]
+ ],
+
+ citeDisabled: [
+ [ 'citeToolDisabled', 'quotes', 'Cite', setDisabled, null, true ]
+ ],
+
+ editorSwitchTools: [
+ [ 'visualEditor', 'eye', 'Visual editing' ],
+ [ 'wikitextEditor', 'wikiText', 'Source editing' ]
+ ],
+
+ formatTools: [
+ [ 'paragraph', null, 'Paragraph' ],
+ [ 'heading2', null, 'Heading 2' ],
+ [ 'heading3', null, 'Sub-heading 1' ],
+ [ 'heading4', null, 'Sub-heading 2' ],
+ [ 'heading5', null, 'Sub-heading 3' ],
+ [ 'heading6', null, 'Sub-heading 4' ],
+ [ 'preformatted', null, 'Preformatted' ],
+ [ 'blockquote', null, 'Blockquote' ]
+ ],
+
+ history: [
+ [ 'undoTool', 'undo', 'Undo' ],
+ [ 'redoTool', 'redo', 'Redo' ]
+ ],
+
+ insertTools: [
+ [ 'media', 'image', 'First basic tool in list' ],
+ [ 'template', 'puzzle', 'Template' ],
+ [ 'table', 'table', 'Table' ],
+ [ 'comment', 'comment', 'Comment' ],
+ [ 'hieroglyphs', 'specialCharacter', 'Hieroglyphs' ],
+ [ 'score', 'specialCharacter', 'Musical notation' ],
+ [ 'signature', 'signature', 'Your signature' ],
+ [ 'gallery', 'imageGallery', 'Gallery' ],
+ [ 'chem', 'specialCharacter', 'Chemical formula' ],
+ [ 'math', 'specialCharacter', 'Math formula' ],
+ [ 'syntaxHighlightDialog', 'markup', 'Code block' ],
+ [ 'graph', 'specialCharacter', 'Graph' ],
+ [ 'referencesList', 'specialCharacter', 'References list' ]
+ ],
+
+ link: [
+ [ 'linkTool', 'link', 'Link' ]
+ ],
+
+ listTools: [
+ [ 'listTool', 'image', 'First basic tool in list' ],
+ [ 'listTool1', 'image', 'Basic tool in list' ],
+ [ 'listTool3', 'image', 'Basic disabled tool in list', setDisabled ],
+ [ 'listTool6', 'image', 'A final tool' ]
+ ],
+
+ moreListTools: [
+ [ 'listTool2', 'code', 'Another basic tool' ],
+ [ 'listTool4', 'image', 'More basic tools' ],
+ [ 'listTool5', 'ellipsis', 'And even more' ]
+ ],
+
+ disabledListTools: [
+ [ 'listToolInDisabled', 'image', 'Basic tool in disabled list' ]
+ ],
+
+ autoDisableListTools: [
+ [ 'autoDisableListTool', 'image', 'Click to disable this tool', null, setDisabled ]
+ ],
+
+ menuTools: [
+ [ 'menuTool', 'image', 'Basic tool' ],
+ [ 'iconlessMenuTool', null, 'Tool without an icon' ],
+ [ 'disabledMenuTool', 'image', 'Basic tool disabled', setDisabled ]
+ ],
+
+ disabledMenuTools: [
+ [ 'menuToolInDisabled', 'image', 'Basic tool' ]
+ ],
+
+ overflowTools: [
+ [ 'meta', 'window', 'Options' ],
+ [ 'categories', 'image', 'Categories' ],
+ [ 'settings', 'settings', 'Page settings' ],
+ [ 'advanced', 'advanced', 'Advanced settings' ],
+ [ 'textLanguage', 'language', 'Languages' ],
+ [ 'templatesUsed', 'puzzle', 'Templates used' ],
+ [ 'codeMirror', 'highlight', 'Syntax highlighting', setDisabled ],
+ [ 'changeDirectionality', 'textDirRTL', 'View as right-to-left' ],
+ [ 'find', 'articleSearch', 'Find and replace' ]
+ ],
+
+ specialCharacters: [
+ [ 'specialCharacter', 'specialCharacter', 'Special character' ]
+ ],
+
+ popupTools: [
+ [ 'popupTool', 'alertTool' ]
+ ],
+
+ structureTools: [
+ [ 'bullet', 'listBullet', 'Bullet list' ],
+ [ 'number', 'listNumbered', 'Numbered list' ],
+ [ 'outdent', 'outdent', 'Decrease indentation' ],
+ [ 'indent', 'indent', 'Increase indentation' ]
+ ],
+
+ styleTools: [
+ [ 'bold', 'bold', 'Bold' ],
+ [ 'italic', 'italic', 'Italic' ],
+ [ 'italic', 'italic', 'Italic' ],
+ [ 'superscript', 'superscript', 'Superscript' ],
+ [ 'subscript', 'subscript', 'Subscript' ],
+ [ 'strikethrough', 'strikethrough', 'Strikethrough' ],
+ [ 'code', 'code', 'Computer Code' ],
+ [ 'underline', 'underline', 'Underline' ],
+ [ 'language', 'language', 'Language' ],
+ [ 'big', 'bigger', 'Big' ],
+ [ 'small', 'smaller', 'Small' ],
+ [ 'clear', 'cancel', 'Clear Styling', setDisabled ]
+ ],
+
+ unusedStuff: [
+ [ 'unusedTool', 'help', 'This tool is not explicitly used anywhere' ],
+ [ 'unusedTool1', 'help', 'And neither is this one' ]
+ ]
+ };
+
+ // ToolGroup creation, in Toolbar numeric and ToolGroup alphabetical order
+ createToolGroup( 0, 'barTools' );
+ createToolGroup( 0, 'disabledBarTools' );
+ createToolGroup( 0, 'listTools' );
+ createToolGroup( 0, 'moreListTools' );
+ createToolGroup( 0, 'disabledListTools' );
+ createToolGroup( 0, 'autoDisableListTools' );
+ createToolGroup( 0, 'unusedStuff' );
+
+ createToolGroup( 1, 'cite' );
+ createToolGroup( 1, 'citeDisabled' );
+ createToolGroup( 1, 'menuTools' );
+ createToolGroup( 1, 'disabledMenuTools' );
+
+ createToolGroup( 6, 'listTools' );
+
+ createToolGroup( 7, 'menuTools' );
+ createToolGroup( 7, 'disabledMenuTools' );
+
+ for ( i = 3; i <= 5; i += 2 ) {
+ createToolGroup( i - 1, 'overflowTools' );
+ createToolGroup( i - 1, 'editorSwitchTools' );
+ createToolGroup( i, 'cite' );
+ createToolGroup( i, 'formatTools' );
+ createToolGroup( i, 'insertTools' );
+ createToolGroup( i, 'history' );
+ createToolGroup( i, 'link' );
+ createToolGroup( i, 'listTools' );
+ createToolGroup( i, 'moreListTools' );
+ createToolGroup( i, 'autoDisableListTools' );
+ createToolGroup( i, 'menuTools' );
+ createToolGroup( i, 'specialCharacters' );
+ createToolGroup( i, 'structureTools' );
+ createToolGroup( i, 'styleTools' );
+ createToolGroup( i, 'unusedStuff' );
+ }
+
+ for ( i = 0; i < toolbars.length; i++ ) {
+ if ( i === 2 || i === 4 || i === 6 ) {
+ // Action toolbars
+ continue;
+ }
+ $containers = $containers.add(
+ new OO.ui.PanelLayout( {
+ expanded: false,
+ framed: true
+ } ).$element
+ .addClass( 'demo-toolbar' )
+ );
+
+ $containers.last().append( toolbars[ i ].$element );
+ }
+ $containers.append( '' );
+ $demo.append(
+ new OO.ui.PanelLayout( {
+ expanded: false,
+ framed: false
+ } ).$element
+ .addClass( 'demo-container demo-toolbars' )
+ .attr( 'role', 'main' )
+ .append(
+ $containers.eq( 0 ).append( '<div class="demo-toolbars-contents">Toolbar</div>' ),
+ $containers.eq( 1 ).append( '<div class="demo-toolbars-contents">Toolbar with action buttons</div>' ),
+ $containers.eq( 2 ).append( '<div class="demo-toolbars-contents">Word processor toolbar</div>' ),
+ $containers.eq( 3 ).prepend( '<div class="demo-toolbars-contents">Word processor toolbar set to <code>position: &#39;bottom&#39;</code></div>' ),
+ $containers.eq( 4 ).append( '<div class="demo-toolbars-contents">Toolbar with action buttons in a group</div>' )
+ )
+ );
+ for ( i = 0; i < toolbars.length; i++ ) {
+ toolbars[ i ].initialize();
+ }
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/pages/widgets.js b/www/wiki/vendor/oojs/oojs-ui/demos/pages/widgets.js
new file mode 100644
index 00000000..d41270db
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/pages/widgets.js
@@ -0,0 +1,3014 @@
+Demo.static.pages.widgets = function ( demo ) {
+ var i, fieldsets,
+ loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, ' +
+ 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\u200E',
+ textInputForLabel, labelForTextInput, radioSelectInputForLabel, labelForRadioSelectInput,
+ inputForValidation, fieldLayoutForValidation,
+ horizontalDragItems = [],
+ verticalDragItems = [],
+ verticalHandledDragItems = [],
+ $overlay = $( '<div>' ).addClass( 'demo-overlay' ).attr( 'id', 'demo-overlay' ),
+ $demo = demo.$element,
+ disabledItemsTagMultiselectWidget = new OO.ui.TagMultiselectWidget( {
+ placeholder: 'Add tags',
+ allowArbitrary: true
+ } );
+
+ disabledItemsTagMultiselectWidget.addTag( 'item1', 'Item 1 (optional)' );
+ disabledItemsTagMultiselectWidget.addTag( 'item2', 'Item 2 (mandatory)' );
+ disabledItemsTagMultiselectWidget.findItemFromData( 'item2' ).setDisabled( true );
+
+ for ( i = 0; i <= 12; i++ ) {
+ horizontalDragItems.push(
+ new Demo.DraggableItemWidget( {
+ data: 'item' + i,
+ icon: 'tag',
+ label: 'Inline item ' + i
+ } )
+ );
+ if ( i <= 6 ) {
+ verticalDragItems.push(
+ new Demo.DraggableItemWidget( {
+ data: 'item' + i,
+ icon: 'tag',
+ label: 'Item ' + i
+ } )
+ );
+ verticalHandledDragItems.push(
+ new Demo.DraggableHandledItemWidget( {
+ data: 'item' + i,
+ icon: 'draggable',
+ label: 'Item ' + i
+ } )
+ );
+ }
+ }
+
+ textInputForLabel = new OO.ui.TextInputWidget( { value: 'Input for label above' } );
+ labelForTextInput = new OO.ui.LabelWidget( {
+ label: 'Label for TextInputWidget below',
+ input: textInputForLabel
+ } );
+
+ radioSelectInputForLabel = new OO.ui.RadioSelectInputWidget( {
+ options: [
+ {
+ data: 'a',
+ label: 'Input for label above'
+ },
+ {
+ data: 'b',
+ label: 'Input for label above'
+ }
+ ]
+ } );
+ labelForRadioSelectInput = new OO.ui.LabelWidget( {
+ label: 'Label for RadioSelectInputWidget below',
+ input: radioSelectInputForLabel
+ } );
+
+ inputForValidation = new OO.ui.TextInputWidget( {
+ validate: function ( value ) {
+ return value.length % 2 === 0;
+ }
+ } );
+
+ fieldLayoutForValidation = new OO.ui.FieldLayout( inputForValidation, {
+ align: 'top',
+ label: 'FieldLayout aligned top with validation errors',
+ help: 'Enter only even number of characters'
+ } );
+
+ inputForValidation.$input.on( 'blur', function () {
+ inputForValidation.getValidity().then( function () {
+ fieldLayoutForValidation.setErrors( [] );
+ }, function () {
+ fieldLayoutForValidation.setErrors( [
+ 'Please enter an even number of characters'
+ ] );
+ } );
+ } );
+
+ fieldsets = [
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-buttons',
+ label: 'Buttons',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( { label: 'Normal' } ),
+ {
+ label: 'ButtonWidget (normal)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Progressive',
+ flags: [ 'progressive' ]
+ } ),
+ {
+ label: 'ButtonWidget (progressive)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Destructive',
+ flags: [ 'destructive' ]
+ } ),
+ {
+ label: 'ButtonWidget (destructive)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Primary progressive',
+ flags: [ 'primary', 'progressive' ]
+ } ),
+ {
+ label: 'ButtonWidget (primary, progressive)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Primary destructive',
+ flags: [ 'primary', 'destructive' ]
+ } ),
+ {
+ label: 'ButtonWidget (primary, destructive)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Disabled',
+ disabled: true
+ } ),
+ {
+ label: 'ButtonWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Progressive',
+ icon: 'tag',
+ flags: [ 'progressive' ],
+ disabled: true
+ } ),
+ {
+ label: 'ButtonWidget (progressive, icon, disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Icon',
+ icon: 'tag'
+ } ),
+ {
+ label: 'ButtonWidget (icon)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Icon',
+ icon: 'tag',
+ flags: [ 'progressive' ]
+ } ),
+ {
+ label: 'ButtonWidget (icon, progressive)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Indicator',
+ indicator: 'down'
+ } ),
+ {
+ label: 'ButtonWidget (indicator)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Indicator',
+ indicator: 'down',
+ flags: [ 'progressive' ]
+ } ),
+ {
+ label: 'ButtonWidget (indicator, progressive)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Access key: G',
+ accessKey: 'g'
+ } ),
+ {
+ label: 'ButtonWidget (with accesskey)\u200E',
+ align: 'top',
+ help: new OO.ui.HtmlSnippet( 'Notice: Using `accesskey` might <a href="http://webaim.org/techniques/keyboard/accesskey" target="_blank">negatively impact screen readers</a>!' )
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ icon: 'help',
+ title: 'Icon only, framed'
+ } ),
+ {
+ label: 'ButtonWidget (icon only)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ indicator: 'clear',
+ title: 'Indicator only, framed'
+ } ),
+ {
+ label: 'ButtonWidget (indicator only)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'help',
+ title: 'Icon only'
+ } ),
+ {
+ label: 'ButtonWidget (frameless, icon only)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ indicator: 'clear',
+ title: 'Indicator only'
+ } ),
+ {
+ label: 'ButtonWidget (frameless, indicator only)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'tag',
+ label: 'Labeled'
+ } ),
+ {
+ label: 'ButtonWidget (frameless)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ flags: [ 'progressive' ],
+ icon: 'check',
+ label: 'Progressive'
+ } ),
+ {
+ label: 'ButtonWidget (frameless, progressive)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ flags: [ 'warning' ],
+ icon: 'alert',
+ label: 'Warning'
+ } ),
+ {
+ label: 'ButtonWidget (frameless, warning)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ flags: [ 'destructive' ],
+ icon: 'trash',
+ label: 'Destructive'
+ } ),
+ {
+ label: 'ButtonWidget (frameless, destructive)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ flags: [ 'destructive' ],
+ label: 'Cancel'
+ } ),
+ {
+ label: 'ButtonWidget (frameless, label-only, destructive)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'tag',
+ label: 'Disabled',
+ disabled: true
+ } ),
+ {
+ label: 'ButtonWidget (frameless, disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'tag',
+ indicator: 'down',
+ label: 'Labeled'
+ } ),
+ {
+ label: 'ButtonWidget (frameless, icon & label & indicator)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ indicator: 'down',
+ label: 'Labeled'
+ } ),
+ {
+ label: 'ButtonWidget (frameless, label & indicator)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'tag',
+ indicator: 'down',
+ title: 'Icon & indicator'
+ } ),
+ {
+ label: 'ButtonWidget (frameless, icon & indicator)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonInputWidget( {
+ label: 'Submit the form',
+ type: 'submit',
+ flags: [ 'primary', 'progressive' ],
+ useInputTag: true
+ } ),
+ {
+ align: 'top',
+ label: 'ButtonInputWidget (using <input>)\u200E'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonInputWidget( {
+ label: 'Another button',
+ type: 'button'
+ } ),
+ {
+ align: 'top',
+ label: 'ButtonInputWidget (using <button>)\u200E'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonInputWidget( {
+ title: 'Accesskey is added to the title.',
+ label: 'Access key: H',
+ accessKey: 'h'
+ } ),
+ {
+ label: 'ButtonInputWidget (with accesskey & title)\u200E',
+ align: 'top',
+ help: new OO.ui.HtmlSnippet( 'Notice: Using `accesskey` might <a href="http://webaim.org/techniques/keyboard/accesskey" target="_blank">negatively impact screen readers</a>!' )
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonInputWidget( {
+ framed: false,
+ label: 'Another button',
+ type: 'button'
+ } ),
+ {
+ align: 'top',
+ label: 'ButtonInputWidget (frameless, using <button>)\u200E'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonInputWidget( {
+ framed: false,
+ label: 'Another button',
+ type: 'button',
+ useInputTag: true
+ } ),
+ {
+ align: 'top',
+ label: 'ButtonInputWidget (frameless, using <input>)\u200E'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ToggleButtonWidget( { label: 'Toggle' } ),
+ {
+ label: 'ToggleButtonWidget',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ToggleButtonWidget( { label: 'Toggle', value: true } ),
+ {
+ label: 'ToggleButtonWidget (initially active)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ToggleButtonWidget( { icon: 'next' } ),
+ {
+ label: 'ToggleButtonWidget (icon only)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ToggleButtonWidget( { icon: 'next', value: true } ),
+ {
+ label: 'ToggleButtonWidget (icon only, initially active)\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-button-sets',
+ label: 'Button sets',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonGroupWidget( {
+ items: [
+ new OO.ui.ButtonWidget( {
+ icon: 'tag',
+ label: 'One'
+ } ),
+ new OO.ui.ButtonWidget( {
+ label: 'Two'
+ } ),
+ new OO.ui.ButtonWidget( {
+ indicator: 'clear',
+ label: 'Three'
+ } )
+ ]
+ } ),
+ {
+ label: 'ButtonGroupWidget',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonGroupWidget( {
+ items: [
+ new OO.ui.ButtonWidget( {
+ label: 'One',
+ flags: [ 'destructive' ]
+ } ),
+ new OO.ui.ButtonWidget( {
+ label: 'Two',
+ flags: [ 'progressive' ]
+ } )
+ ]
+ } ),
+ {
+ label: 'ButtonGroupWidget (destructive and progressive ButtonWidget)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonGroupWidget( {
+ items: [
+ new OO.ui.ButtonWidget( {
+ icon: 'tag',
+ flags: [ 'destructive' ]
+ } ),
+ new OO.ui.ButtonWidget( {
+ label: 'Two',
+ flags: [ 'progressive' ]
+ } )
+ ]
+ } ),
+ {
+ label: 'ButtonGroupWidget (destructive icon and progressive text)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonGroupWidget( {
+ items: [
+ new OO.ui.ToggleButtonWidget( {
+ icon: 'tag',
+ label: 'One'
+ } ),
+ new OO.ui.ToggleButtonWidget( {
+ label: 'Two'
+ } ),
+ new OO.ui.ToggleButtonWidget( {
+ indicator: 'clear',
+ label: 'Three'
+ } )
+ ]
+ } ),
+ {
+ label: 'ButtonGroupWidget with ToggleButtonWidgets',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonSelectWidget( {
+ items: [
+ new OO.ui.ButtonOptionWidget( {
+ data: 'b',
+ icon: 'tag',
+ label: 'One'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'c',
+ label: 'Two'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'd',
+ indicator: 'clear',
+ label: 'Three'
+ } )
+ ]
+ } ),
+ {
+ label: 'ButtonSelectWidget',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonSelectWidget( {
+ disabled: true,
+ items: [
+ new OO.ui.ButtonOptionWidget( {
+ data: 'b',
+ icon: 'tag',
+ label: 'One'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'c',
+ label: 'Two'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'd',
+ indicator: 'clear',
+ label: 'Three'
+ } )
+ ]
+ } ),
+ {
+ label: 'ButtonSelectWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonSelectWidget( {
+ items: [
+ new OO.ui.ButtonOptionWidget( {
+ data: 'b',
+ icon: 'tag',
+ label: 'One',
+ disabled: true
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'c',
+ label: 'Two'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'd',
+ indicator: 'clear',
+ label: 'Three'
+ } )
+ ]
+ } ),
+ {
+ label: 'ButtonSelectWidget (disabled items)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonSelectWidget( {
+ items: [
+ new OO.ui.ButtonOptionWidget( {
+ data: 'a',
+ label: 'Access key: I',
+ accessKey: 'i'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'b',
+ label: 'Access key: J',
+ accessKey: 'j'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ data: 'c',
+ label: 'Access key: K',
+ accessKey: 'k'
+ } )
+ ]
+ } ),
+ {
+ label: 'ButtonSelectWidget (with accesskeys)\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-button-showcase',
+ label: 'Button style showcase',
+ items: [
+ new OO.ui.FieldLayout(
+ new Demo.ButtonStyleShowcaseWidget(),
+ {
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-inputs',
+ label: 'Inputs: TextInput, TextInput, MultilineTextInput, SearchInput, NumberInput',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( { value: 'Text input' } ),
+ {
+ label: 'TextInputWidget\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( { icon: 'help' } ),
+ {
+ label: 'TextInputWidget (icon)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ required: true,
+ validate: 'non-empty'
+ } ),
+ {
+ label: 'TextInputWidget (required)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ validate: function ( value ) {
+ return value.length % 2 === 0;
+ }
+ } ),
+ {
+ label: 'TextInputWidget (only allows even number of characters)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( { placeholder: 'Placeholder' } ),
+ {
+ label: 'TextInputWidget (placeholder)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ value: 'Title attribute',
+ title: 'Title attribute with more information about me.'
+ } ),
+ {
+ label: 'TextInputWidget (with title)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ value: 'Readonly',
+ readOnly: true
+ } ),
+ {
+ label: 'TextInputWidget (readonly)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ value: 'Disabled',
+ disabled: true
+ } ),
+ {
+ label: 'TextInputWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.MultilineTextInputWidget( {
+ value: 'Multiline\nMultiline'
+ } ),
+ {
+ label: 'MultilineTextInputWidget\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.MultilineTextInputWidget( {
+ rows: 15,
+ value: 'Multiline\nMultiline'
+ } ),
+ {
+ label: 'MultilineTextInputWidget (rows=15)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.MultilineTextInputWidget( {
+ autosize: true,
+ value: 'Autosize\nAutosize\nAutosize\nAutosize'
+ } ),
+ {
+ label: 'MultilineTextInputWidget (autosize)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.MultilineTextInputWidget( {
+ rows: 10,
+ autosize: true,
+ value: 'Autosize\nAutosize\nAutosize\nAutosize'
+ } ),
+ {
+ label: 'MultilineTextInputWidget (autosize, rows=10)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.MultilineTextInputWidget( {
+ autosize: true,
+ icon: 'tag',
+ indicator: 'clear',
+ label: 'Inline label',
+ value: 'Autosize\nAutosize\nAutosize\nAutosize'
+ } ),
+ {
+ label: 'MultilineTextInputWidget (autosize, icon, indicator, label)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ value: 'Text input with label',
+ label: 'Inline label'
+ } ),
+ {
+ label: 'TextInputWidget (label)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ value: 'Text input with label',
+ label: 'Inline label',
+ labelPosition: 'before'
+ } ),
+ {
+ label: 'TextInputWidget (label[position=before])\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ icon: 'tag',
+ indicator: 'clear',
+ value: 'Text input with label',
+ label: 'Inline label'
+ } ),
+ {
+ label: 'TextInputWidget (icon, indicator, label)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ icon: 'tag',
+ indicator: 'clear',
+ value: 'Text input with label',
+ label: 'Inline label',
+ labelPosition: 'before'
+ } ),
+ {
+ label: 'TextInputWidget (icon, indicator, label[position=before])\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ value: 'Disabled',
+ icon: 'tag',
+ indicator: 'clear',
+ label: 'Inline label',
+ disabled: true
+ } ),
+ {
+ label: 'TextInputWidget (icon, indicator, label, disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ value: 'Access key: S',
+ accessKey: 's'
+ } ),
+ {
+ label: 'TextInputWidget (with accesskey)\u200E',
+ align: 'top',
+ help: new OO.ui.HtmlSnippet( 'Notice: Using `accesskey` might <a href="http://webaim.org/techniques/keyboard/accesskey" target="_blank">negatively impact screen readers</a>!' )
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new Demo.DynamicLabelTextInputWidget( {
+ getLabelText: function ( value ) {
+ return String( value.length );
+ }
+ } ),
+ {
+ label: 'TextInputWidget (with dynamic label – length)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new Demo.DynamicLabelTextInputWidget( {
+ maxLength: 300,
+ getLabelText: function ( value ) {
+ return String( 300 - value.length );
+ }
+ } ),
+ {
+ label: 'TextInputWidget (with dynamic label – remaining length)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.SearchInputWidget(),
+ {
+ label: 'SearchInputWidget (type=search)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.SearchInputWidget( { disabled: true } ),
+ {
+ label: 'SearchInputWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.SearchInputWidget( { disabled: true, value: 'test' } ),
+ {
+ label: 'SearchInputWidget (disabled, filled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.NumberInputWidget(),
+ {
+ label: 'NumberInputWidget',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.NumberInputWidget( { disabled: true } ),
+ {
+ label: 'NumberInputWidget (disabled)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.NumberInputWidget( { min: 1, max: 5, isInteger: true } ),
+ {
+ label: 'NumberInputWidget (1–5, ints only)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.NumberInputWidget( { min: 0, max: 1, step: 0.1, pageStep: 0.25 } ),
+ {
+ label: 'NumberInputWidget (0–1, step by .1, page by .25)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.NumberInputWidget( { showButtons: false } ),
+ {
+ label: 'NumberInputWidget (no buttons)',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-inputs-binary',
+ label: 'Checkbox, Radio & ToggleSwitch',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.CheckboxInputWidget( {
+ selected: true
+ } ),
+ {
+ align: 'inline',
+ label: 'CheckboxInputWidget'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CheckboxInputWidget( {
+ selected: true,
+ disabled: true
+ } ),
+ {
+ align: 'inline',
+ label: 'CheckboxInputWidget (disabled)\u200E'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CheckboxInputWidget( {
+ selected: true,
+ accessKey: 't'
+ } ),
+ {
+ align: 'inline',
+ label: 'CheckboxInputWidget (with accesskey T and title)\u200E',
+ title: 'Access key is added to the title.'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.RadioInputWidget( {
+ name: 'oojs-ui-radio-demo'
+ } ),
+ {
+ align: 'inline',
+ label: 'Connected RadioInputWidget #1'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.RadioInputWidget( {
+ name: 'oojs-ui-radio-demo',
+ selected: true
+ } ),
+ {
+ align: 'inline',
+ label: 'Connected RadioInputWidget #2'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.RadioInputWidget( {
+ selected: true,
+ disabled: true
+ } ),
+ {
+ align: 'inline',
+ label: 'RadioInputWidget (disabled)\u200E'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.RadioSelectWidget( {
+ items: [
+ new OO.ui.RadioOptionWidget( {
+ data: 'cat',
+ label: 'Cat'
+ } ),
+ new OO.ui.RadioOptionWidget( {
+ data: 'dog',
+ label: 'Dog'
+ } ),
+ new OO.ui.RadioOptionWidget( {
+ data: 'goldfish',
+ label: 'Goldfish. By the way, this is a very long label. ' + loremIpsum,
+ disabled: true
+ } )
+ ]
+ } ),
+ {
+ align: 'top',
+ label: 'RadioSelectWidget'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CheckboxMultiselectWidget( {
+ items: [
+ new OO.ui.CheckboxMultioptionWidget( {
+ data: 'cat',
+ label: 'Cat'
+ } ),
+ new OO.ui.CheckboxMultioptionWidget( {
+ data: 'dog',
+ label: 'Dog'
+ } ),
+ new OO.ui.CheckboxMultioptionWidget( {
+ data: 'goldfish',
+ label: 'Goldfish. By the way, this is a very long label. ' + loremIpsum,
+ disabled: true
+ } )
+ ]
+ } ),
+ {
+ align: 'top',
+ label: 'CheckboxMultiselectWidget'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.RadioSelectInputWidget( {
+ value: 'dog',
+ options: [
+ {
+ data: 'cat',
+ label: 'Cat'
+ },
+ {
+ data: 'dog',
+ label: 'Dog'
+ },
+ {
+ data: 'goldfish',
+ label: 'Goldfish'
+ }
+ ]
+ } ),
+ {
+ align: 'top',
+ label: 'RadioSelectInputWidget'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CheckboxMultiselectInputWidget( {
+ value: [ 'dog', 'cat' ],
+ options: [
+ {
+ data: 'cat',
+ label: 'Cat'
+ },
+ {
+ data: 'dog',
+ label: 'Dog (disabled)\u200E',
+ disabled: true
+ },
+ {
+ data: 'goldfish',
+ label: 'Goldfish'
+ }
+ ]
+ } ),
+ {
+ align: 'top',
+ label: 'CheckboxMultiselectInputWidget'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.RadioSelectWidget( {
+ items: [
+ new OO.ui.RadioOptionWidget( {
+ data: 'a',
+ label: 'Access key: M',
+ accessKey: 'm'
+ } ),
+ new OO.ui.RadioOptionWidget( {
+ data: 'b',
+ label: 'Access key: N',
+ accessKey: 'n'
+ } ),
+ new OO.ui.RadioOptionWidget( {
+ data: 'c',
+ label: 'Access key: O',
+ accessKey: 'o'
+ } )
+ ]
+ } ),
+ {
+ align: 'top',
+ label: 'RadioSelectWidget (with accesskeys)\u200E'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ToggleSwitchWidget(),
+ {
+ label: 'ToggleSwitchWidget',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ToggleSwitchWidget( { disabled: true } ),
+ {
+ label: 'ToggleSwitchWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ToggleSwitchWidget( { disabled: true, value: true } ),
+ {
+ label: 'ToggleSwitchWidget (disabled, checked)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.RadioSelectWidget( {
+ items: [
+ new OO.ui.RadioOptionWidget( {
+ data: 'a',
+ label: $( $.parseHTML( 'Option A (<a href="https://example.com/a">details</a>)' ) )
+ } ),
+ new OO.ui.RadioOptionWidget( {
+ data: 'b',
+ label: $( $.parseHTML( 'Option B (<a href="https://example.com/b">details</a>)' ) )
+ } ),
+ new OO.ui.RadioOptionWidget( {
+ data: 'c',
+ label: $( $.parseHTML( 'Option C (<a href="https://example.com/c">details</a>)' ) )
+ } )
+ ]
+ } ),
+ {
+ label: 'RadioSelectWidget with links in the labels',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.RadioSelectWidget( {
+ items: [
+ new OO.ui.RadioOptionWidget( {
+ data: 'foo',
+ label: 'Foo'
+ } ),
+ new OO.ui.RadioOptionWidget( {
+ data: 'bar',
+ label: 'Bar'
+ } ),
+ new OO.ui.RadioOptionWidget( {
+ data: '',
+ label: $( [
+ document.createTextNode( 'Other: ' ),
+ new OO.ui.TextInputWidget().$element[ 0 ]
+ ] )
+ } )
+ ]
+ } ),
+ {
+ label: 'RadioSelectWidget with text input in a label',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-dropdown',
+ label: 'Dropdown',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownWidget( {
+ label: 'Select one',
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( {
+ data: 'a',
+ label: 'First'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'b',
+ label: 'Second',
+ indicator: 'clear'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'c',
+ label: 'Third'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'c',
+ label: 'The fourth option has a long label'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ icon: 'feedback',
+ data: 'd',
+ label: 'The fifth option has an icon'
+ } )
+ ]
+ }
+ } ),
+ {
+ label: 'DropdownWidget',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownWidget( {
+ label: 'Select one',
+ icon: 'tag',
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( {
+ data: 'a',
+ label: 'First'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'b',
+ label: 'Disabled second option',
+ indicator: 'clear',
+ disabled: true
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'c',
+ label: 'Third'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'd',
+ label: 'Disabled fourth option with long label',
+ disabled: true
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'c',
+ label: 'Third'
+ } )
+ ]
+ }
+ } ),
+ {
+ label: 'DropdownWidget (disabled options)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownWidget( {
+ label: 'Select one',
+ menu: {
+ items: [
+ new OO.ui.MenuSectionOptionWidget( {
+ label: 'Dogs'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'corgi',
+ label: 'Welsh Corgi',
+ indicator: 'required'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'poodle',
+ label: 'Standard Poodle',
+ icon: 'star'
+ } ),
+ new OO.ui.MenuSectionOptionWidget( {
+ label: 'Cats'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'lion',
+ label: 'Lion'
+ } )
+ ]
+ }
+ } ),
+ {
+ label: 'DropdownWidget (with MenuSectionOptionWidget)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownWidget( {
+ label: 'Select one',
+ disabled: true,
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( {
+ data: 'a',
+ label: 'First'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'b',
+ label: 'Second'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'c',
+ label: 'Third'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'd',
+ label: 'Fourth'
+ } )
+ ]
+ }
+ } ),
+ {
+ label: 'DropdownWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownWidget( {
+ label: 'Select one',
+ $overlay: true,
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( {
+ data: 'a',
+ label: 'First'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'b',
+ label: 'Second'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'c',
+ label: 'Third'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'd',
+ label: 'Fourth'
+ } )
+ ]
+ }
+ } ),
+ {
+ label: 'DropdownWidget (using default overlay)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownWidget( {
+ label: 'Select one',
+ $overlay: $overlay,
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( {
+ data: 'a',
+ label: 'First'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'b',
+ label: 'Second'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'c',
+ label: 'Third'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'd',
+ label: 'Fourth'
+ } )
+ ]
+ }
+ } ),
+ {
+ label: 'DropdownWidget (using custom overlay)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownWidget( {
+ label: 'Select one',
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( {
+ data: 'a',
+ label: 'First'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'b',
+ label: 'Second'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'c',
+ label: 'Third'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'd',
+ label: 'Fourth'
+ } )
+ ],
+ hideOnChoose: false
+ }
+ } ),
+ {
+ label: 'DropdownWidget (does not close on choose)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownWidget( {
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( {
+ data: 'a',
+ label: 'Access key: P',
+ accessKey: 'p'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'b',
+ label: 'Access key: Q',
+ accessKey: 'q'
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'c',
+ label: 'Access key: R',
+ accessKey: 'r'
+ } )
+ ]
+ }
+ } ),
+ {
+ align: 'top',
+ label: 'DropdownWidget (with accesskeys)\u200E'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownInputWidget( {
+ options: [
+ {
+ data: 'a',
+ label: 'First'
+ },
+ {
+ data: 'b',
+ label: 'Second'
+ },
+ {
+ data: 'c',
+ label: 'Third'
+ }
+ ],
+ value: 'b'
+ } ),
+ {
+ label: 'DropdownInputWidget',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownInputWidget( {
+ disabled: true
+ } ),
+ {
+ label: 'DropdownInputWidget (disabled)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownInputWidget( {
+ options: [
+ {
+ optgroup: 'Vowels'
+ },
+ {
+ data: 'a',
+ label: 'A'
+ },
+ {
+ optgroup: 'Consonants'
+ },
+ {
+ data: 'b',
+ label: 'B'
+ },
+ {
+ data: 'c',
+ label: 'C'
+ }
+ ],
+ value: 'b'
+ } ),
+ {
+ label: 'DropdownInputWidget (with optgroup)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.DropdownInputWidget( {
+ options: [
+ { data: 'sq', label: 'Albanian' },
+ { data: 'frp', label: 'Arpitan' },
+ { data: 'ba', label: 'Bashkir' },
+ { data: 'pt-br', label: 'Brazilian Portuguese' },
+ { data: 'tzm', label: 'Central Atlas Tamazight' },
+ { data: 'zh', label: 'Chinese' },
+ { data: 'co', label: 'Corsican' },
+ { data: 'del', label: 'Delaware' },
+ { data: 'eml', label: 'Emiliano-Romagnolo' },
+ { data: 'en', label: 'English' },
+ { data: 'fi', label: 'Finnish' },
+ { data: 'aln', label: 'Gheg Albanian' },
+ { data: 'he', label: 'Hebrew' },
+ { data: 'ilo', label: 'Iloko' },
+ { data: 'kbd', label: 'Kabardian' },
+ { data: 'csb', label: 'Kashubian' },
+ { data: 'avk', label: 'Kotava' },
+ { data: 'lez', label: 'Lezghian' },
+ { data: 'nds-nl', label: 'Low Saxon' },
+ { data: 'ml', label: 'Malayalam' },
+ { data: 'dum', label: 'Middle Dutch' },
+ { data: 'ary', label: 'Moroccan Arabic' },
+ { data: 'pih', label: 'Norfuk / Pitkern' },
+ { data: 'ny', label: 'Nyanja' },
+ { data: 'ang', label: 'Old English' },
+ { data: 'non', label: 'Old Norse' },
+ { data: 'pau', label: 'Palauan' },
+ { data: 'pdt', label: 'Plautdietsch' },
+ { data: 'ru', label: 'Russian' },
+ { data: 'stq', label: 'Saterland Frisian' },
+ { data: 'ii', label: 'Sichuan Yi' },
+ { data: 'bcc', label: 'Southern Balochi' },
+ { data: 'shi', label: 'Tachelhit' },
+ { data: 'th', label: 'Thai' },
+ { data: 'tr', label: 'Turkish' },
+ { data: 'fiu-vro', label: 'Võro' },
+ { data: 'vls', label: 'West Flemish' },
+ { data: 'zea', label: 'Zeelandic' }
+ ],
+ value: 'en'
+ } ),
+ {
+ label: 'DropdownInputWidget (long)\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-comboBox',
+ label: 'ComboBox',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.ComboBoxInputWidget( {
+ options: [
+ { data: 'asd', label: 'Label for asd' },
+ { data: 'fgh', label: 'Label for fgh' },
+ { data: 'jkl', label: 'Label for jkl' },
+ { data: 'zxc', label: 'Label for zxc' },
+ { data: 'vbn', label: 'Label for vbn' }
+ ]
+ } ),
+ {
+ label: 'ComboBoxInputWidget',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ComboBoxInputWidget( {
+ options: [
+ { data: 'asd', label: 'A Label for asd' },
+ { data: 'fgh', label: 'A Label for fgh' },
+ { data: 'jkl', label: 'A Label for jkl' },
+ { data: 'zxc', label: 'A Label for zxc' },
+ { data: 'vbn', label: 'A Label for vbn' },
+ { data: 'asd', label: 'B Label for asd' },
+ { data: 'fgh', label: 'B Label for fgh' },
+ { data: 'jkl', label: 'B Label for jkl' },
+ { data: 'zxc', label: 'B Label for zxc' },
+ { data: 'vbn', label: 'B Label for vbn' },
+ { data: 'asd', label: 'C Label for asd' },
+ { data: 'fgh', label: 'C Label for fgh' },
+ { data: 'jkl', label: 'C Label for jkl' },
+ { data: 'zxc', label: 'C Label for zxc' },
+ { data: 'vbn', label: 'C Label for vbn' },
+ { data: 'asd', label: 'D Label for asd' },
+ { data: 'fgh', label: 'D Label for fgh' },
+ { data: 'jkl', label: 'D Label for jkl' },
+ { data: 'zxc', label: 'D Label for zxc' },
+ { data: 'vbn', label: 'D Label for vbn' },
+ { data: 'asd', label: 'E Label for asd' },
+ { data: 'fgh', label: 'E Label for fgh' },
+ { data: 'jkl', label: 'E Label for jkl' },
+ { data: 'zxc', label: 'E Label for zxc' },
+ { data: 'vbn', label: 'E Label for vbn' }
+ ],
+ menu: {
+ filterFromInput: true
+ }
+ } ),
+ {
+ label: 'ComboBoxInputWidget (filtering on input)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ComboBoxInputWidget( {
+ options: [
+ { data: 'Option 1' },
+ { data: 'Option 2' },
+ { data: 'Option 3' },
+ { data: 'Option 4' },
+ { data: 'Option 5' }
+ ]
+ } ),
+ {
+ label: 'ComboBoxInputWidget (no labels given)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ComboBoxInputWidget( {
+ disabled: true,
+ options: [
+ { data: 'asd', label: 'Label for asd' },
+ { data: 'fgh', label: 'Label for fgh' },
+ { data: 'jkl', label: 'Label for jkl' },
+ { data: 'zxc', label: 'Label for zxc' },
+ { data: 'vbn', label: 'Label for vbn' }
+ ]
+ } ),
+ {
+ label: 'ComboBoxInputWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ComboBoxInputWidget(),
+ {
+ label: 'ComboBoxInputWidget (empty)\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-selectFile',
+ label: 'SelectFile',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.SelectFileWidget( {} ),
+ {
+ label: 'SelectFileWidget\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.SelectFileWidget( { accept: [ 'image/png', 'image/jpeg' ] } ),
+ {
+ label: 'SelectFileWidget (accept PNG and JPEG)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.SelectFileWidget( {
+ icon: 'tag',
+ indicator: 'clear'
+ } ),
+ {
+ label: 'SelectFileWidget (icon, indicator)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.SelectFileWidget( {
+ icon: 'tag',
+ indicator: 'clear',
+ disabled: true
+ } ),
+ {
+ label: 'SelectFileWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new Demo.UnsupportedSelectFileWidget(),
+ {
+ label: 'SelectFileWidget (no browser support)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.SelectFileWidget( { showDropTarget: true } ),
+ {
+ label: 'SelectFileWidget (with drop target)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.SelectFileWidget( {
+ showDropTarget: true,
+ disabled: true
+ } ),
+ {
+ label: 'SelectFileWidget (with drop target, disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new Demo.UnsupportedSelectFileWidget( {
+ showDropTarget: true
+ } ),
+ {
+ label: 'SelectFileWidget (with drop target, no browser support)\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-tagMultiselect',
+ label: 'TagMultiselect, MenuTagMultiselect, CapsuleMultiselect',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.TagMultiselectWidget( {
+ placeholder: 'Add tags',
+ allowArbitrary: true
+ } ),
+ {
+ label: 'TagMultiselectWidget (allowArbitrary, inline input, placeholder)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ disabledItemsTagMultiselectWidget,
+ {
+ label: 'TagMultiselectWidget with disabled items',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TagMultiselectWidget( {
+ placeholder: 'Add tags',
+ allowArbitrary: true,
+ disabled: true
+ } ),
+ {
+ label: 'TagMultiselectWidget (disabled, inline input, placeholder)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TagMultiselectWidget( {
+ allowArbitrary: false,
+ allowDisplayInvalidTags: true,
+ allowedValues: [ 'foo', 'bar', 'baz' ]
+ } ),
+ {
+ label: 'TagMultiselectWidget (inline input, allowed values: [ \'foo\', \'bar\', \'baz\' ], allowDisplayInvalidTags)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TagMultiselectWidget( {
+ placeholder: 'Add tags',
+ allowArbitrary: true,
+ inputPosition: 'outline'
+ } ),
+ {
+ label: 'TagMultiselectWidget (allowArbitrary, inputPosition:outline, placeholder)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TagMultiselectWidget( {
+ allowArbitrary: true,
+ inputPosition: 'outline',
+ inputWidget: new OO.ui.NumberInputWidget()
+ } ),
+ {
+ label: 'TagMultiselectWidget (inputwidget: OO.ui.NumberInputWidget, inputPosition:outline)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupTagMultiselectWidget( {
+ allowArbitrary: true,
+ icon: 'tag',
+ indicator: 'clear'
+ } ),
+ {
+ label: 'PopupTagMultiselectWidget (icon, indicator, allowArbitrary)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.MenuTagMultiselectWidget( {
+ selected: [
+ { data: 'foo', label: 'Label for foo' },
+ { data: 'bar', label: 'Label for bar' }
+ ],
+ options: [
+ { data: 'foo', label: 'Label for foo' },
+ { data: 'bar', label: 'Label for bar' },
+ { data: 'baz', label: 'Label for baz' }
+ ]
+ } ),
+ {
+ label: 'MenuTagMultiselectWidget (initially selected, preset options)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.MenuTagMultiselectWidget( {
+ selected: [ 'foo', 'bar' ],
+ allowArbitrary: true
+ } ),
+ {
+ label: 'MenuTagMultiselectWidget (initially selected, allowArbitrary)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.MenuTagMultiselectWidget( {
+ allowArbitrary: false,
+ options: [
+ { data: 'abc', label: 'Label for abc' },
+ { data: 'asd', label: 'Label for asd' },
+ { data: 'jkl', label: 'Label for jkl' }
+ ]
+ } ),
+ {
+ label: 'MenuTagMultiselectWidget (allowArbitrary:false)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.MenuTagMultiselectWidget( {
+ inputPosition: 'outline',
+ allowArbitrary: false,
+ options: [
+ { data: 'abc', label: 'Label for abc' },
+ { data: 'asd', label: 'Label for asd' },
+ { data: 'jkl', label: 'Label for jkl' }
+ ]
+ } ),
+ {
+ label: 'MenuTagMultiselectWidget (inputPosition:outline, allowArbitrary:false)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CapsuleMultiselectWidget( {
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( { data: 'abc', label: 'Label for abc' } ),
+ new OO.ui.MenuOptionWidget( { data: 'asd', label: 'Label for asd' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jkl', label: 'Label for jkl' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jjj', label: 'Label for jjj' } ),
+ new OO.ui.MenuOptionWidget( { data: 'zxc', label: 'Label for zxc' } ),
+ new OO.ui.MenuOptionWidget( { data: 'vbn', label: 'Label for vbn' } )
+ ]
+ }
+ } ),
+ {
+ label: 'CapsuleMultiselectWidget',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CapsuleMultiselectWidget( {
+ placeholder: 'Type like a cat…',
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( { data: 'abc', label: 'Label for abc' } ),
+ new OO.ui.MenuOptionWidget( { data: 'asd', label: 'Label for asd' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jkl', label: 'Label for jkl' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jjj', label: 'Label for jjj' } ),
+ new OO.ui.MenuOptionWidget( { data: 'zxc', label: 'Label for zxc' } ),
+ new OO.ui.MenuOptionWidget( { data: 'vbn', label: 'Label for vbn' } )
+ ]
+ }
+ } ),
+ {
+ label: 'CapsuleMultiselectWidget (with placeholder)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CapsuleMultiselectWidget( {
+ allowArbitrary: true,
+ icon: 'tag',
+ indicator: 'clear',
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( { data: 'abc', label: 'Label for abc' } ),
+ new OO.ui.MenuOptionWidget( { data: 'asd', label: 'Label for asd' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jkl', label: 'Label for jkl' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jjj', label: 'Label for jjj' } ),
+ new OO.ui.MenuOptionWidget( { data: 'zxc', label: 'Label for zxc' } ),
+ new OO.ui.MenuOptionWidget( { data: 'vbn', label: 'Label for vbn' } )
+ ]
+ }
+ } ),
+ {
+ label: 'CapsuleMultiselectWidget (icon, indicator, arbitrary values allowed)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CapsuleMultiselectWidget( {
+ disabled: true,
+ icon: 'tag',
+ indicator: 'clear',
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( { data: 'abc', label: 'Label for abc' } ),
+ new OO.ui.MenuOptionWidget( { data: 'asd', label: 'Label for asd' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jkl', label: 'Label for jkl' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jjj', label: 'Label for jjj' } ),
+ new OO.ui.MenuOptionWidget( { data: 'zxc', label: 'Label for zxc' } ),
+ new OO.ui.MenuOptionWidget( { data: 'vbn', label: 'Label for vbn' } )
+ ]
+ }
+ } ),
+ {
+ label: 'CapsuleMultiselectWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CapsuleMultiselectWidget( {
+ disabled: true,
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( { data: 'abc', label: 'Label for abc' } ),
+ new OO.ui.MenuOptionWidget( { data: 'asd', label: 'Label for asd' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jkl', label: 'Label for jkl' } )
+ ]
+ }
+ } ).addItemsFromData( [ 'abc', 'asd' ] ),
+ {
+ label: 'CapsuleMultiselectWidget (disabled, initially selected)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CapsuleMultiselectWidget( {
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( { data: 'abc', label: 'Label for abc' } ),
+ new OO.ui.MenuOptionWidget( { data: 'asd', label: 'Label for asd' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jkl', label: 'Label for jkl' } )
+ ]
+ }
+ } ).addItemsFromData( [ 'abc', 'asd' ] ),
+ {
+ label: 'CapsuleMultiselectWidget (initially selected)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CapsuleMultiselectWidget( {
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( { data: 'abc', label: 'Label for abc' } ),
+ new OO.ui.MenuSectionOptionWidget( { label: 'Foo' } ),
+ new OO.ui.MenuOptionWidget( { data: 'asd', label: 'Label for asd' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jkl', label: 'Label for jkl' } ),
+ new OO.ui.MenuSectionOptionWidget( { label: 'Bar' } ),
+ new OO.ui.MenuOptionWidget( { data: 'jjj', label: 'Label for jjj' } ),
+ new OO.ui.MenuOptionWidget( { data: 'zxc', label: 'Label for zxc' } ),
+ new OO.ui.MenuSectionOptionWidget( { label: 'Baz' } ),
+ new OO.ui.MenuOptionWidget( { data: 'vbn', label: 'Label for vbn' } )
+ ]
+ }
+ } ),
+ {
+ label: 'CapsuleMultiselectWidget (sectioned by MenuSectionOptionWidget)',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new Demo.CapsuleNumberPopupMultiselectWidget(),
+ {
+ label: 'CapsuleMultiselectWidget with NumberInputWidget popup\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-lookupElement',
+ label: 'LookupElement',
+ items: [
+ new OO.ui.FieldLayout(
+ new Demo.NumberLookupTextInputWidget(),
+ {
+ label: 'LookupElement (try inputting an integer)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new Demo.NumberLookupTextInputWidget( {
+ highlightFirst: false
+ } ),
+ {
+ label: 'LookupElement without highlighting 1st term (try inputting an integer)\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-popupButton',
+ label: 'PopupButton',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'info',
+ framed: false,
+ popup: {
+ head: true,
+ label: 'More information',
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'force-left'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (frameless, with popup head, align: force-left)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'info',
+ framed: false,
+ popup: {
+ head: true,
+ label: 'More information',
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'force-right'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (frameless, with popup head align: force-right)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'info',
+ framed: false,
+ popup: {
+ head: true,
+ label: 'More information',
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'backwards'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (frameless, with popup head align: backwards)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'info',
+ framed: false,
+ popup: {
+ head: true,
+ label: 'More information',
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'forwards'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (frameless, with popup head align: forwards)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'info',
+ framed: false,
+ popup: {
+ head: true,
+ label: 'More information',
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'center'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (frameless, with popup head align: center)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'info',
+ framed: false,
+ popup: {
+ head: true,
+ label: 'More information',
+ $content: $( '<p>' + loremIpsum + '</p><ul><li>Item one</li><li>Item two</li><li>Item three</li><li>Item four</li></ul><p>Even more text here which might well be clipped off the visible area.</p>' ),
+ $footer: $( '<p>And maybe a footer whilst we\'re at it?</p>' ),
+ padded: true,
+ align: 'forwards'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (frameless, with popup head and footer, align: forwards)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'menu',
+ label: 'Options',
+ popup: {
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'forwards'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (framed, no popup head, align: forwards)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'menu',
+ label: 'Options',
+ popup: {
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'backwards'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (framed, no popup head, align: backwards)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'menu',
+ label: 'Options',
+ popup: {
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'center'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (framed, no popup head, align: center)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'menu',
+ label: 'Options',
+ popup: {
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'center',
+ position: 'above'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (framed, no popup head, position: above)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'menu',
+ label: 'Options',
+ popup: {
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'center',
+ position: 'before'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (framed, no popup head, position: before)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'menu',
+ label: 'Options',
+ popup: {
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ align: 'center',
+ position: 'after'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (framed, no popup head, position: after)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'menu',
+ label: 'Options',
+ popup: {
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ anchor: false,
+ align: 'center'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (no anchor, align: center)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'menu',
+ label: 'Options',
+ popup: {
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ anchor: false,
+ align: 'forwards'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (no anchor, align: forwards)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.PopupButtonWidget( {
+ icon: 'menu',
+ label: 'Options',
+ popup: {
+ $content: $( '<p>' ).text( loremIpsum ),
+ padded: true,
+ anchor: false,
+ align: 'backwards'
+ }
+ } ),
+ {
+ label: 'PopupButtonWidget (no anchor, align: backwards)\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-draggable',
+ label: 'Draggable',
+ items: [
+ new OO.ui.FieldLayout(
+ new Demo.DraggableGroupWidget( {
+ orientation: 'horizontal',
+ items: horizontalDragItems
+ } ),
+ {
+ label: 'DraggableGroupWidget (horizontal)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new Demo.DraggableGroupWidget( {
+ items: verticalDragItems
+ } ),
+ {
+ label: 'DraggableGroupWidget (vertical)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new Demo.DraggableGroupWidget( {
+ items: verticalHandledDragItems
+ } ),
+ {
+ label: 'DraggableGroupWidget with handles (vertical)\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-progressBar',
+ label: 'Progress bar',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.ProgressBarWidget( {
+ progress: 33
+ } ),
+ {
+ label: 'Progress bar',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ProgressBarWidget( {
+ progress: 50,
+ disabled: true
+ } ),
+ {
+ label: 'Progress bar (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ProgressBarWidget( {
+ progress: false
+ } ),
+ {
+ label: 'Progress bar (indeterminate)\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-others',
+ label: 'Other widgets',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.IconWidget( {
+ icon: 'search',
+ title: 'Search icon'
+ } ),
+ {
+ label: 'IconWidget (normal)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.IconWidget( {
+ icon: 'trash',
+ flags: 'destructive',
+ title: 'Remove icon'
+ } ),
+ {
+ label: 'IconWidget (flagged)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.IconWidget( {
+ icon: 'search',
+ title: 'Search icon',
+ disabled: true
+ } ),
+ {
+ label: 'IconWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.IndicatorWidget( {
+ indicator: 'clear',
+ title: 'Required indicator'
+ } ),
+ {
+ label: 'IndicatorWidget (normal)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.IndicatorWidget( {
+ indicator: 'clear',
+ title: 'Required indicator',
+ disabled: true
+ } ),
+ {
+ label: 'IndicatorWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.LabelWidget( {
+ label: 'Label'
+ } ),
+ {
+ label: 'LabelWidget (normal)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.LabelWidget( {
+ label: 'Label',
+ disabled: true
+ } ),
+ {
+ label: 'LabelWidget (disabled)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.LabelWidget( {
+ label: new OO.ui.HtmlSnippet( '<b>Fancy</b> <i>text</i> <u>formatting</u>!' )
+ } ),
+ {
+ label: 'LabelWidget (with HTML)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ labelForTextInput,
+ {
+ label: 'LabelWidget (with an associated TextInputWidget)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ textInputForLabel,
+ {
+ label: 'TextInputWidget (with an associated label)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ labelForRadioSelectInput,
+ {
+ label: 'LabelWidget (with an associated RadioSelectInputWidget)\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ radioSelectInputForLabel,
+ {
+ label: 'RadioSelectInputWidget (with an associated label)\u200E',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-fieldLayouts',
+ label: 'Field layouts',
+ icon: 'tag',
+ help: loremIpsum,
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'FieldLayout with help',
+ help: loremIpsum,
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'FieldLayout with HTML help',
+ help: new OO.ui.HtmlSnippet( '<b>Bold text</b> is helpful!' ),
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'FieldLayout with title',
+ title: 'Field title text',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: $( '<i>' ).text( 'FieldLayout with rich text label' ),
+ align: 'top'
+ }
+ ),
+ new OO.ui.ActionFieldLayout(
+ new OO.ui.TextInputWidget(),
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'ActionFieldLayout aligned top',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget(),
+ {
+ label: 'FieldLayout aligned top with help',
+ help: loremIpsum,
+ align: 'top'
+ }
+ ),
+ new OO.ui.ActionFieldLayout(
+ new OO.ui.TextInputWidget(),
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'ActionFieldLayout aligned top with help',
+ help: loremIpsum,
+ align: 'top'
+ }
+ ),
+ new OO.ui.ActionFieldLayout(
+ new OO.ui.CheckboxInputWidget( { selected: true } ),
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'ActionFieldLayout aligned inline',
+ align: 'inline'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CheckboxInputWidget( { selected: true } ),
+ {
+ label: 'FieldLayout aligned inline with help',
+ help: loremIpsum,
+ align: 'inline'
+ }
+ ),
+ new OO.ui.ActionFieldLayout(
+ new OO.ui.CheckboxInputWidget( { selected: true } ),
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'ActionFieldLayout aligned inline with help',
+ help: loremIpsum,
+ align: 'inline'
+ }
+ ),
+ new OO.ui.ActionFieldLayout(
+ new OO.ui.TextInputWidget(),
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'ActionFieldLayout aligned left',
+ align: 'left'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget(),
+ {
+ label: 'FieldLayout aligned left with help',
+ help: loremIpsum,
+ align: 'left'
+ }
+ ),
+ new OO.ui.ActionFieldLayout(
+ new OO.ui.TextInputWidget(),
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'ActionFieldLayout aligned left with help',
+ help: loremIpsum,
+ align: 'left'
+ }
+ ),
+ new OO.ui.ActionFieldLayout(
+ new OO.ui.TextInputWidget(),
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'ActionFieldLayout aligned right',
+ align: 'right'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget(),
+ {
+ label: 'FieldLayout aligned right with help',
+ help: loremIpsum,
+ align: 'right'
+ }
+ ),
+ new OO.ui.ActionFieldLayout(
+ new OO.ui.TextInputWidget(),
+ new OO.ui.ButtonWidget( {
+ label: 'Button'
+ } ),
+ {
+ label: 'ActionFieldLayout aligned right with help',
+ help: loremIpsum,
+ align: 'right'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget(),
+ {
+ label: 'FieldLayout aligned top with very long label. ' + loremIpsum,
+ help: loremIpsum,
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CheckboxInputWidget( { selected: true } ),
+ {
+ label: 'FieldLayout aligned inline with very long label. ' + loremIpsum,
+ help: loremIpsum,
+ align: 'inline'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget(),
+ {
+ label: 'FieldLayout aligned left with very long label. ' + loremIpsum,
+ help: loremIpsum,
+ align: 'left'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget(),
+ {
+ label: 'FieldLayout aligned right with very long label. ' + loremIpsum,
+ help: loremIpsum,
+ align: 'right'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ value: ''
+ } ),
+ {
+ label: 'FieldLayout with notice',
+ notices: [ 'Please input a number.' ],
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ value: 'Foo'
+ } ),
+ {
+ label: 'FieldLayout with error message',
+ errors: [ 'The value must be a number.' ],
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ value: 'Foo'
+ } ),
+ {
+ label: 'FieldLayout with notice and error message',
+ notices: [ 'Please input a number.' ],
+ errors: [ 'The value must be a number.' ],
+ align: 'top'
+ }
+ ),
+ fieldLayoutForValidation
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-horizontalLayout',
+ label: 'HorizontalLayout',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.Widget( {
+ content: [ new OO.ui.HorizontalLayout( {
+ items: [
+ new OO.ui.ButtonWidget( { label: 'Button' } ),
+ new OO.ui.ButtonGroupWidget( { items: [
+ new OO.ui.ToggleButtonWidget( { label: 'A' } ),
+ new OO.ui.ToggleButtonWidget( { label: 'B' } )
+ ] } ),
+ new OO.ui.ButtonInputWidget( { label: 'ButtonInput' } ),
+ new OO.ui.TextInputWidget( { value: 'TextInput' } ),
+ new OO.ui.DropdownInputWidget( { options: [
+ {
+ label: 'DropdownInput',
+ data: null
+ }
+ ] } ),
+ new OO.ui.CheckboxInputWidget( { selected: true } ),
+ new OO.ui.RadioInputWidget( { selected: true } ),
+ new OO.ui.LabelWidget( { label: 'Label' } )
+ ]
+ } ) ]
+ } ),
+ {
+ label: 'Multiple widgets shown as a single line, ' +
+ 'as used in compact forms or in parts of a bigger widget.',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-other-layouts',
+ label: 'Other layouts',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.Widget( {
+ content: [
+ new OO.ui.PanelLayout( {
+ expanded: false,
+ framed: true,
+ content: [
+ new OO.ui.BookletLayout( {
+ expanded: false,
+ outlined: true
+ } ).addPages( [
+ new Demo.SamplePage( 'first', {
+ expanded: false,
+ label: 'One'
+ } ),
+ new Demo.SamplePage( 'second', {
+ expanded: false,
+ label: 'Two'
+ } ),
+ new Demo.SamplePage( 'third', {
+ expanded: false,
+ label: 'Three'
+ } ),
+ new Demo.SamplePage( 'fourth', {
+ expanded: false,
+ label: 'Four'
+ } ),
+ new Demo.SamplePage( 'long', {
+ expanded: false,
+ label: 'Long',
+ content: [
+ $( '<p>' ).text( loremIpsum ),
+ $( '<p>' ).text( loremIpsum ),
+ $( '<p>' ).text( loremIpsum ),
+ $( '<p>' ).text( loremIpsum ),
+ $( '<p>' ).text( loremIpsum ),
+ $( '<p>' ).text( loremIpsum ),
+ $( '<p>' ).text( loremIpsum )
+ ]
+ } )
+ ] )
+ ]
+ } )
+ ]
+ } ),
+ {
+ label: 'Outlined BookletLayout',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.Widget( {
+ content: [
+ new OO.ui.PanelLayout( {
+ expanded: false,
+ framed: true,
+ content: [
+ new OO.ui.IndexLayout( {
+ expanded: false
+ } ).addTabPanels( [
+ new Demo.SampleTabPanel( 'first', {
+ expanded: false,
+ label: 'One tab'
+ } ),
+ new Demo.SampleTabPanel( 'second', {
+ expanded: false,
+ label: 'Two tab'
+ } ),
+ new Demo.SampleTabPanel( 'third', {
+ expanded: false,
+ label: 'Three tab'
+ } ),
+ new Demo.SampleTabPanel( 'fourth', {
+ expanded: false,
+ label: 'Four tab'
+ } ),
+ new Demo.SampleTabPanel( 'long', {
+ expanded: false,
+ label: 'Long tab',
+ content: [
+ $( '<p>' ).text( loremIpsum ),
+ $( '<p>' ).text( loremIpsum ),
+ $( '<p>' ).text( loremIpsum )
+ ]
+ } )
+ ] )
+ ]
+ } )
+ ]
+ } ),
+ {
+ label: 'IndexLayout',
+ align: 'top'
+ }
+ )
+ ]
+ } ),
+ new OO.ui.FormLayout( {
+ method: 'GET',
+ action: 'demos.php',
+ items: [
+ new OO.ui.FieldsetLayout( {
+ id: 'demo-section-formLayout',
+ label: 'Form layout (compounded example)',
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ name: 'username'
+ } ),
+ {
+ label: 'User name',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ name: 'password',
+ type: 'password'
+ } ),
+ {
+ label: 'Password',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonSelectWidget( {
+ items: [
+ new OO.ui.ButtonOptionWidget( {
+ label: 'One'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ label: 'Two'
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ indicator: 'clear',
+ label: 'Three'
+ } )
+ ]
+ } ),
+ {
+ label: 'Select one of multiple ButtonSelectWidget Buttons',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.SelectFileWidget( {} ),
+ {
+ label: 'Select a file with SelectFileWidget\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CapsuleMultiselectWidget( {
+ menu: {
+ items: [
+ new OO.ui.MenuOptionWidget( { data: 'abc', label: 'Abc Label' } ),
+ new OO.ui.MenuOptionWidget( { data: 'def', label: 'Def Label' } ),
+ new OO.ui.MenuOptionWidget( { data: 'ghi', label: 'Ghi Label' } )
+ ]
+ }
+ } ).addItemsFromData( [ 'abc', 'def' ] ),
+ {
+ label: 'Select from multiple CapsuleMultiselectWidget items\u200E',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.RadioSelectWidget( {
+ items: [
+ new OO.ui.RadioOptionWidget( {
+ data: 'mouse',
+ label: 'Mouse'
+ } ),
+ new OO.ui.RadioOptionWidget( {
+ data: 'elephant',
+ label: 'Elephant'
+ } )
+ ]
+ } ),
+ {
+ align: 'top',
+ label: 'Toggle the RadioSelectWidget'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ToggleSwitchWidget( { value: true } ),
+ {
+ label: 'Switch the ToggleSwitchWidget (checked)',
+ align: 'right'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.CheckboxInputWidget( {
+ name: 'rememberme',
+ selected: true
+ } ),
+ {
+ label: 'Remember me',
+ align: 'inline'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.HiddenInputWidget( {
+ name: 'hidden',
+ value: 'hidden value'
+ } )
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.ButtonInputWidget( {
+ type: 'submit',
+ label: 'Submit form'
+ } )
+ )
+ ]
+ } ),
+ new OO.ui.FieldsetLayout( {
+ label: null,
+ items: [
+ new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget(),
+ {
+ label: 'Summary',
+ align: 'top'
+ }
+ ),
+ new OO.ui.FieldLayout(
+ new OO.ui.Widget( {
+ content: [ new OO.ui.HorizontalLayout( {
+ items: [
+ new OO.ui.ButtonInputWidget( {
+ name: 'login',
+ label: 'Log in',
+ type: 'submit',
+ flags: [ 'primary', 'progressive' ],
+ icon: 'userAvatar'
+ } ),
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ flags: [ 'destructive' ],
+ label: 'Cancel'
+ } ),
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'tag',
+ label: 'Random icon button'
+ } ),
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'help',
+ title: 'Icon only'
+ } )
+ ]
+ } ) ]
+ } ),
+ {
+ label: null,
+ align: 'top'
+ }
+ )
+ ]
+ } )
+ ]
+ } )
+ ];
+
+ $.each( fieldsets, function ( i, fieldsetLayout ) {
+ var showLayoutCode = false;
+
+ if (
+ fieldsetLayout instanceof OO.ui.FormLayout ||
+ fieldsetLayout.getLabel() === 'Field layouts'
+ ) {
+ showLayoutCode = true;
+ }
+
+ $.each( fieldsetLayout.getItems(), function ( j, fieldLayout ) {
+ fieldLayout.$element.append(
+ demo.buildLinkExample( fieldLayout, fieldsetLayout instanceof OO.ui.FormLayout ? fieldLayout : fieldsetLayout ),
+ demo.buildConsole( fieldLayout, 'layout', 'widget', showLayoutCode )
+ );
+ } );
+ } );
+
+ $demo.append(
+ new OO.ui.PanelLayout( {
+ expanded: false,
+ framed: true
+ } ).$element
+ .addClass( 'demo-container' )
+ .attr( 'role', 'main' )
+ .append(
+ $( fieldsets.map( function ( fieldset ) { return fieldset.$element[ 0 ]; } ) )
+ )
+ );
+
+ $overlay.appendTo( 'body' );
+
+ demo.once( 'destroy', function () {
+ // We are removing all of the widgets from the page, so also remove their "detached"
+ // menus and stuff, otherwise they can remain visible forever.
+ $overlay.remove();
+ OO.ui.$defaultOverlay.empty();
+ } );
+};
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/pages/widgets.php b/www/wiki/vendor/oojs/oojs-ui/demos/pages/widgets.php
new file mode 100644
index 00000000..04a5bb76
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/pages/widgets.php
@@ -0,0 +1,1180 @@
+<?php
+if ( !defined( 'OOUI_DEMOS' ) ) {
+ header( 'Location: ../demos.php' );
+ exit;
+}
+
+$loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " .
+ "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\xE2\x80\x8E";
+
+$demoContainer = new OOUI\PanelLayout( [
+ 'expanded' => false,
+ 'padded' => true,
+ 'framed' => true,
+] );
+
+$demoContainer->addClasses( [ 'demo-container' ] );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-buttons',
+ 'infusable' => true,
+ 'label' => 'Buttons',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [ 'label' => 'Normal' ] ),
+ [
+ 'label' => "ButtonWidget (normal)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Progressive',
+ 'flags' => [ 'progressive' ]
+ ] ),
+ [
+ 'label' => "ButtonWidget (progressive)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Destructive',
+ 'flags' => [ 'destructive' ]
+ ] ),
+ [
+ 'label' => "ButtonWidget (destructive)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Primary progressive',
+ 'flags' => [ 'primary', 'progressive' ]
+ ] ),
+ [
+ 'label' => "ButtonWidget (primary, progressive)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Primary destructive',
+ 'flags' => [ 'primary', 'destructive' ]
+ ] ),
+ [
+ 'label' => "ButtonWidget (primary, destructive)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Disabled',
+ 'disabled' => true
+ ] ),
+ [
+ 'label' => "ButtonWidget (disabled)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Progressive',
+ 'icon' => 'tag',
+ 'flags' => [ 'progressive' ],
+ 'disabled' => true
+ ] ),
+ [
+ 'label' => "ButtonWidget (progressive, icon, disabled)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Icon',
+ 'icon' => 'tag'
+ ] ),
+ [
+ 'label' => "ButtonWidget (icon)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Icon',
+ 'icon' => 'tag',
+ 'flags' => [ 'progressive' ]
+ ] ),
+ [
+ 'label' => "ButtonWidget (icon, progressive)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Indicator',
+ 'indicator' => 'down'
+ ] ),
+ [
+ 'label' => "ButtonWidget (indicator)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Indicator',
+ 'indicator' => 'down',
+ 'flags' => [ 'progressive' ]
+ ] ),
+ [
+ 'label' => "ButtonWidget (indicator, progressive)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'framed' => false,
+ 'icon' => 'help',
+ 'title' => 'Icon only'
+ ] ),
+ [
+ 'label' => "ButtonWidget (frameless, icon only)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'framed' => false,
+ 'icon' => 'tag',
+ 'label' => 'Labeled'
+ ] ),
+ [
+ 'label' => "ButtonWidget (frameless)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'framed' => false,
+ 'flags' => [ 'progressive' ],
+ 'icon' => 'check',
+ 'label' => 'Progressive'
+ ] ),
+ [
+ 'label' => "ButtonWidget (frameless, progressive)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'framed' => false,
+ 'flags' => [ 'destructive' ],
+ 'icon' => 'trash',
+ 'label' => 'Destructive'
+ ] ),
+ [
+ 'label' => "ButtonWidget (frameless, destructive)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'framed' => false,
+ 'flags' => [ 'destructive' ],
+ 'label' => 'Cancel'
+ ] ),
+ [
+ 'label' => "ButtonWidget (frameless, label-only, destructive)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'framed' => false,
+ 'icon' => 'tag',
+ 'label' => 'Disabled',
+ 'disabled' => true
+ ] ),
+ [
+ 'label' => "ButtonWidget (frameless, disabled)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonInputWidget( [
+ 'label' => 'Submit the form',
+ 'type' => 'submit',
+ 'flags' => [ 'primary', 'progressive' ],
+ 'useInputTag' => true
+ ] ),
+ [
+ 'align' => 'top',
+ 'label' => "ButtonInputWidget (using <input>)\xE2\x80\x8E"
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonInputWidget( [
+ 'label' => 'Another button',
+ 'type' => 'button'
+ ] ),
+ [
+ 'align' => 'top',
+ 'label' => "ButtonInputWidget (using <button>)\xE2\x80\x8E"
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonInputWidget( [
+ 'framed' => false,
+ 'label' => 'Another button',
+ 'type' => 'button'
+ ] ),
+ [
+ 'align' => 'top',
+ 'label' => "ButtonInputWidget (frameless)\xE2\x80\x8E"
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonInputWidget( [
+ 'framed' => false,
+ 'label' => 'Another button',
+ 'type' => 'button',
+ 'useInputTag' => true
+ ] ),
+ [
+ 'align' => 'top',
+ 'label' => "ButtonInputWidget (frameless, using <input>)\xE2\x80\x8E"
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Access key: G',
+ 'accessKey' => 'g'
+ ] ),
+ [
+ 'label' => "ButtonWidget (with accesskey)\xE2\x80\x8E",
+ 'align' => 'top',
+ 'help' => new OOUI\HtmlSnippet( 'Notice: Using `accesskey` might ' .
+ '<a href="http://webaim.org/techniques/keyboard/accesskey" target="_blank">' .
+ 'negatively impact screen readers</a>!' )
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonInputWidget( [
+ 'title' => 'Access key is added to the title.',
+ 'label' => 'Access key: H',
+ 'accessKey' => 'h'
+ ] ),
+ [
+ 'label' => "ButtonInputWidget (with accesskey and title)\xE2\x80\x8E",
+ 'align' => 'top',
+ ]
+ )
+ ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-button-sets',
+ 'infusable' => true,
+ 'label' => 'Button sets',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\ButtonGroupWidget( [
+ 'items' => [
+ new OOUI\ButtonWidget( [
+ 'icon' => 'tag',
+ 'label' => 'One'
+ ] ),
+ new OOUI\ButtonWidget( [
+ 'label' => 'Two'
+ ] ),
+ new OOUI\ButtonWidget( [
+ 'indicator' => 'clear',
+ 'label' => 'Three'
+ ] )
+ ]
+ ] ),
+ [
+ 'label' => 'ButtonGroupWidget',
+ 'align' => 'top'
+ ]
+ )
+ ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-button-showcase',
+ 'infusable' => true,
+ 'label' => 'Button style showcase',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new Demo\ButtonStyleShowcaseWidget(),
+ [
+ 'align' => 'top',
+ ]
+ )
+ ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-inputs',
+ 'infusable' => true,
+ 'label' => 'TextInput',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [ 'value' => 'Text input' ] ),
+ [
+ 'label' => "TextInputWidget\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [ 'icon' => 'help' ] ),
+ [
+ 'label' => "TextInputWidget (icon)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'required' => true
+ ] ),
+ [
+ 'label' => "TextInputWidget (required)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [ 'placeholder' => 'Placeholder' ] ),
+ [
+ 'label' => "TextInputWidget (placeholder)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'value' => 'Title attribute',
+ 'title' => 'Title attribute with more information about me.'
+ ] ),
+ [
+ 'label' => "TextInputWidget (with title)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [ 'type' => 'search' ] ),
+ [
+ 'label' => "TextInputWidget (type=search)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\SearchInputWidget(),
+ [
+ 'label' => "SearchInputWidget",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'value' => 'Access key: S',
+ 'accessKey' => 's'
+ ] ),
+ [
+ 'label' => "TextInputWidget (with accesskey)\xE2\x80\x8E",
+ 'align' => 'top',
+ 'help' => new OOUI\HtmlSnippet( 'Notice: Using `accesskey` might ' .
+ '<a href="http://webaim.org/techniques/keyboard/accesskey" target="_blank">' .
+ 'negatively impact screen readers</a>!' )
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'value' => 'Readonly',
+ 'readOnly' => true
+ ] ),
+ [
+ 'label' => "TextInputWidget (readonly)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'value' => 'Disabled',
+ 'disabled' => true
+ ] ),
+ [
+ 'label' => "TextInputWidget (disabled)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\MultilineTextInputWidget( [
+ 'value' => "Multiline\nMultiline"
+ ] ),
+ [
+ 'label' => "MultilineTextInputWidget \xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\MultilineTextInputWidget( [
+ 'rows' => 15,
+ 'value' => "Multiline\nMultiline"
+ ] ),
+ [
+ 'label' => "MultilineTextInputWidget (rows=15)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\MultilineTextInputWidget( [
+ 'value' => "Multiline\nMultiline",
+ 'icon' => 'tag',
+ 'indicator' => 'required'
+ ] ),
+ [
+ 'label' => "MultilineTextInputWidget (icon, indicator)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ )
+ ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-inputs-binary',
+ 'infusable' => true,
+ 'label' => 'Checkbox & Radio',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\CheckboxInputWidget( [
+ 'selected' => true
+ ] ),
+ [
+ 'align' => 'inline',
+ 'label' => 'CheckboxInputWidget'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\CheckboxInputWidget( [
+ 'selected' => true,
+ 'disabled' => true
+ ] ),
+ [
+ 'align' => 'inline',
+ 'label' => "CheckboxInputWidget (disabled)\xE2\x80\x8E"
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\CheckboxInputWidget( [
+ 'selected' => true,
+ 'accessKey' => 't'
+ ] ),
+ [
+ 'align' => 'inline',
+ 'label' => "CheckboxInputWidget (with accesskey T and title)\xE2\x80\x8E",
+ 'title' => 'Access key is added to the title.',
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\RadioInputWidget( [
+ 'name' => 'oojs-ui-radio-demo'
+ ] ),
+ [
+ 'align' => 'inline',
+ 'label' => 'Connected RadioInputWidget #1'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\RadioInputWidget( [
+ 'name' => 'oojs-ui-radio-demo',
+ 'selected' => true
+ ] ),
+ [
+ 'align' => 'inline',
+ 'label' => 'Connected RadioInputWidget #2'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\RadioInputWidget( [
+ 'selected' => true,
+ 'disabled' => true
+ ] ),
+ [
+ 'align' => 'inline',
+ 'label' => "RadioInputWidget (disabled)\xE2\x80\x8E"
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\RadioSelectInputWidget( [
+ 'value' => 'dog',
+ 'options' => [
+ [
+ 'data' => 'cat',
+ 'label' => 'Cat'
+ ],
+ [
+ 'data' => 'dog',
+ 'label' => 'Dog'
+ ],
+ [
+ 'data' => 'goldfish',
+ 'label' => 'Goldfish'
+ ],
+ ]
+ ] ),
+ [
+ 'align' => 'top',
+ 'label' => 'RadioSelectInputWidget',
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\CheckboxMultiselectInputWidget( [
+ 'value' => [ 'dog', 'cat' ],
+ 'options' => [
+ [
+ 'data' => 'cat',
+ 'label' => 'Cat'
+ ],
+ [
+ 'data' => 'dog',
+ 'label' => "Dog (disabled)\xE2\x80\x8E",
+ 'disabled' => true
+ ],
+ [
+ 'data' => 'goldfish',
+ 'label' => 'Goldfish'
+ ],
+ ]
+ ] ),
+ [
+ 'align' => 'top',
+ 'label' => 'CheckboxMultiselectInputWidget',
+ ]
+ )
+ ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-dropdown',
+ 'infusable' => true,
+ 'label' => 'Dropdown',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\DropdownInputWidget( [
+ 'options' => [
+ [
+ 'data' => 'a',
+ 'label' => 'First'
+ ],
+ [
+ 'data' => 'b',
+ 'label' => 'Second'
+ ],
+ [
+ 'data' => 'c',
+ 'label' => 'Third'
+ ]
+ ],
+ 'value' => 'b'
+ ] ),
+ [
+ 'label' => 'DropdownInputWidget',
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\DropdownInputWidget( [
+ 'disabled' => true
+ ] ),
+ [
+ 'label' => 'DropdownInputWidget (disabled)',
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\DropdownInputWidget( [
+ 'options' => [
+ [
+ 'optgroup' => 'Vowels'
+ ],
+ [
+ 'data' => 'a',
+ 'label' => 'A'
+ ],
+ [
+ 'optgroup' => 'Consonants'
+ ],
+ [
+ 'data' => 'b',
+ 'label' => 'B'
+ ],
+ [
+ 'data' => 'c',
+ 'label' => 'C'
+ ]
+ ],
+ 'value' => 'b'
+ ] ),
+ [
+ 'label' => 'DropdownInputWidget (with optgroup)',
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\DropdownInputWidget( [
+ 'options' => [
+ [ 'data' => 'sq', 'label' => 'Albanian' ],
+ [ 'data' => 'frp', 'label' => 'Arpitan' ],
+ [ 'data' => 'ba', 'label' => 'Bashkir' ],
+ [ 'data' => 'pt-br', 'label' => 'Brazilian Portuguese' ],
+ [ 'data' => 'tzm', 'label' => 'Central Atlas Tamazight' ],
+ [ 'data' => 'zh', 'label' => 'Chinese' ],
+ [ 'data' => 'co', 'label' => 'Corsican' ],
+ [ 'data' => 'del', 'label' => 'Delaware' ],
+ [ 'data' => 'eml', 'label' => 'Emiliano-Romagnolo' ],
+ [ 'data' => 'en', 'label' => 'English' ],
+ [ 'data' => 'fi', 'label' => 'Finnish' ],
+ [ 'data' => 'aln', 'label' => 'Gheg Albanian' ],
+ [ 'data' => 'he', 'label' => 'Hebrew' ],
+ [ 'data' => 'ilo', 'label' => 'Iloko' ],
+ [ 'data' => 'kbd', 'label' => 'Kabardian' ],
+ [ 'data' => 'csb', 'label' => 'Kashubian' ],
+ [ 'data' => 'avk', 'label' => 'Kotava' ],
+ [ 'data' => 'lez', 'label' => 'Lezghian' ],
+ [ 'data' => 'nds-nl', 'label' => 'Low Saxon' ],
+ [ 'data' => 'ml', 'label' => 'Malayalam' ],
+ [ 'data' => 'dum', 'label' => 'Middle Dutch' ],
+ [ 'data' => 'ary', 'label' => 'Moroccan Arabic' ],
+ [ 'data' => 'pih', 'label' => 'Norfuk / Pitkern' ],
+ [ 'data' => 'ny', 'label' => 'Nyanja' ],
+ [ 'data' => 'ang', 'label' => 'Old English' ],
+ [ 'data' => 'non', 'label' => 'Old Norse' ],
+ [ 'data' => 'pau', 'label' => 'Palauan' ],
+ [ 'data' => 'pdt', 'label' => 'Plautdietsch' ],
+ [ 'data' => 'ru', 'label' => 'Russian' ],
+ [ 'data' => 'stq', 'label' => 'Saterland Frisian' ],
+ [ 'data' => 'ii', 'label' => 'Sichuan Yi' ],
+ [ 'data' => 'bcc', 'label' => 'Southern Balochi' ],
+ [ 'data' => 'shi', 'label' => 'Tachelhit' ],
+ [ 'data' => 'th', 'label' => 'Thai' ],
+ [ 'data' => 'tr', 'label' => 'Turkish' ],
+ [ 'data' => 'fiu-vro', 'label' => 'Võro' ],
+ [ 'data' => 'vls', 'label' => 'West Flemish' ],
+ [ 'data' => 'zea', 'label' => 'Zeelandic' ],
+ ],
+ 'value' => 'en',
+ ] ),
+ [
+ 'label' => "DropdownInputWidget (long)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ )
+ ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-comboBox',
+ 'infusable' => true,
+ 'label' => 'ComboBox',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\ComboBoxInputWidget( [
+ 'options' => [
+ [ 'data' => 'asd', 'label' => 'Label for asd' ],
+ [ 'data' => 'fgh', 'label' => 'Label for fgh' ],
+ [ 'data' => 'jkl', 'label' => 'Label for jkl' ],
+ [ 'data' => 'zxc', 'label' => 'Label for zxc' ],
+ [ 'data' => 'vbn', 'label' => 'Label for vbn' ],
+ ]
+ ] ),
+ [
+ 'label' => 'ComboBoxInputWidget',
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ComboBoxInputWidget( [
+ 'disabled' => true,
+ 'options' => [
+ [ 'data' => 'asd', 'label' => 'Label for asd' ],
+ [ 'data' => 'fgh', 'label' => 'Label for fgh' ],
+ [ 'data' => 'jkl', 'label' => 'Label for jkl' ],
+ [ 'data' => 'zxc', 'label' => 'Label for zxc' ],
+ [ 'data' => 'vbn', 'label' => 'Label for vbn' ],
+ ]
+ ] ),
+ [
+ 'label' => "ComboBoxInputWidget (disabled)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ComboBoxInputWidget(),
+ [
+ 'label' => "ComboBoxInputWidget (empty)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ )
+ ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-progressBar',
+ 'infusable' => true,
+ 'label' => 'Progress bar',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\ProgressBarWidget( [
+ 'progress' => 33
+ ] ),
+ [
+ 'label' => 'Progress bar',
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ProgressBarWidget( [
+ 'disabled' => true,
+ 'progress' => 50
+ ] ),
+ [
+ 'label' => 'Progress bar (disabled)',
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ProgressBarWidget( [
+ 'progress' => false
+ ] ),
+ [
+ 'label' => 'Progress bar (indeterminate)',
+ 'align' => 'top'
+ ]
+ ),
+ ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-others',
+ 'infusable' => true,
+ 'label' => 'Other widgets',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\IconWidget( [
+ 'icon' => 'search',
+ 'title' => 'Search icon'
+ ] ),
+ [
+ 'label' => "IconWidget (normal)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\IconWidget( [
+ 'icon' => 'trash',
+ 'flags' => 'destructive',
+ 'title' => 'Remove icon'
+ ] ),
+ [
+ 'label' => "IconWidget (flagged)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\IconWidget( [
+ 'icon' => 'search',
+ 'title' => 'Search icon',
+ 'disabled' => true
+ ] ),
+ [
+ 'label' => "IconWidget (disabled)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\IndicatorWidget( [
+ 'indicator' => 'required',
+ 'title' => 'Required indicator'
+ ] ),
+ [
+ 'label' => "IndicatorWidget (normal)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\IndicatorWidget( [
+ 'indicator' => 'required',
+ 'title' => 'Required indicator',
+ 'disabled' => true
+ ] ),
+ [
+ 'label' => "IndicatorWidget (disabled)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\LabelWidget( [
+ 'label' => 'Label'
+ ] ),
+ [
+ 'label' => "LabelWidget (normal)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\LabelWidget( [
+ 'label' => 'Label',
+ 'disabled' => true,
+ ] ),
+ [
+ 'label' => "LabelWidget (disabled)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\LabelWidget( [
+ 'label' => new OOUI\HtmlSnippet( '<b>Fancy</b> <i>text</i> <u>formatting</u>!' ),
+ ] ),
+ [
+ 'label' => "LabelWidget (with html)\xE2\x80\x8E",
+ 'align' => 'top'
+ ]
+ )
+ ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-fieldLayouts',
+ 'infusable' => true,
+ 'label' => 'Field layouts',
+ 'icon' => 'tag',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'FieldLayout with help',
+ 'help' => $loremIpsum,
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'FieldLayout with HTML help',
+ 'help' => new OOUI\HtmlSnippet( '<b>Bold text</b> is helpful!' ),
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'FieldLayout with title',
+ 'title' => 'Field title text',
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => new OOUI\HtmlSnippet( '<i>FieldLayout with rich text label</i>' ),
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\ActionFieldLayout(
+ new OOUI\TextInputWidget(),
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'ActionFieldLayout aligned top',
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget(),
+ [
+ 'label' => 'FieldLayout aligned top with help',
+ 'help' => $loremIpsum,
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\ActionFieldLayout(
+ new OOUI\TextInputWidget(),
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'ActionFieldLayout aligned top with help',
+ 'help' => $loremIpsum,
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\ActionFieldLayout(
+ new OOUI\CheckboxInputWidget( [ 'selected' => true ] ),
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'ActionFieldLayout aligned inline',
+ 'align' => 'inline',
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\CheckboxInputWidget( [ 'selected' => true ] ),
+ [
+ 'label' => 'FieldLayout aligned inline with help',
+ 'help' => $loremIpsum,
+ 'align' => 'inline',
+ ]
+ ),
+ new OOUI\ActionFieldLayout(
+ new OOUI\CheckboxInputWidget( [ 'selected' => true ] ),
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'ActionFieldLayout aligned inline with help',
+ 'help' => $loremIpsum,
+ 'align' => 'inline',
+ ]
+ ),
+ new OOUI\ActionFieldLayout(
+ new OOUI\TextInputWidget(),
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'ActionFieldLayout aligned left',
+ 'align' => 'left',
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget(),
+ [
+ 'label' => 'FieldLayout aligned left with help',
+ 'help' => $loremIpsum,
+ 'align' => 'left',
+ ]
+ ),
+ new OOUI\ActionFieldLayout(
+ new OOUI\TextInputWidget(),
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'ActionFieldLayout aligned left with help',
+ 'help' => $loremIpsum,
+ 'align' => 'left',
+ ]
+ ),
+ new OOUI\ActionFieldLayout(
+ new OOUI\TextInputWidget(),
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'ActionFieldLayout aligned right',
+ 'align' => 'right',
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget(),
+ [
+ 'label' => 'FieldLayout aligned right with help',
+ 'help' => $loremIpsum,
+ 'align' => 'right',
+ ]
+ ),
+ new OOUI\ActionFieldLayout(
+ new OOUI\TextInputWidget(),
+ new OOUI\ButtonWidget( [
+ 'label' => 'Button'
+ ] ),
+ [
+ 'label' => 'ActionFieldLayout aligned right with help',
+ 'help' => $loremIpsum,
+ 'align' => 'right',
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'value' => ''
+ ] ),
+ [
+ 'label' => 'FieldLayout with notice',
+ 'notices' => [ 'Please input a number.' ],
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'value' => 'Foo'
+ ] ),
+ [
+ 'label' => 'FieldLayout with error message',
+ 'errors' => [ 'The value must be a number.' ],
+ 'align' => 'top'
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'value' => 'Foo'
+ ] ),
+ [
+ 'label' => 'FieldLayout with notice and error message',
+ 'notices' => [ 'Please input a number.' ],
+ 'errors' => [ 'The value must be a number.' ],
+ 'align' => 'top'
+ ]
+ )
+ ]
+] ) );
+
+// We can't make the outer FieldsetLayout infusable, because the Widget in its FieldLayout
+// is added with 'content', which is not preserved after infusion. But we need the Widget
+// to wrap the HorizontalLayout. Need to think about this at some point.
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-horizontalLayout',
+ 'infusable' => false,
+ 'label' => 'HorizontalLayout',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\Widget( [
+ 'content' => new OOUI\HorizontalLayout( [
+ 'infusable' => true,
+ 'items' => [
+ new OOUI\ButtonWidget( [ 'label' => 'Button' ] ),
+ new OOUI\ButtonGroupWidget( [ 'items' => [
+ new OOUI\ButtonWidget( [ 'label' => 'A' ] ),
+ new OOUI\ButtonWidget( [ 'label' => 'B' ] )
+ ] ] ),
+ new OOUI\ButtonInputWidget( [ 'label' => 'ButtonInput' ] ),
+ new OOUI\TextInputWidget( [ 'value' => 'TextInput' ] ),
+ new OOUI\DropdownInputWidget( [ 'options' => [
+ [
+ 'label' => 'DropdownInput',
+ 'data' => null
+ ]
+ ] ] ),
+ new OOUI\CheckboxInputWidget( [ 'selected' => true ] ),
+ new OOUI\RadioInputWidget( [ 'selected' => true ] ),
+ new OOUI\LabelWidget( [ 'label' => 'Label' ] )
+ ],
+ ] ),
+ ] ),
+ [
+ 'label' => 'Multiple widgets shown as a single line, ' .
+ 'as used in compact forms or in parts of a bigger widget.',
+ 'align' => 'top'
+ ]
+ ),
+ ],
+] ) );
+
+$demoContainer->appendContent( new OOUI\FormLayout( [
+ 'infusable' => true,
+ 'method' => 'GET',
+ 'action' => 'demos.php',
+ 'items' => [
+ new OOUI\FieldsetLayout( [
+ 'id' => 'demo-section-formLayout',
+ 'label' => 'Form layout',
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'name' => 'username',
+ ] ),
+ [
+ 'label' => 'User name',
+ 'align' => 'top',
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'name' => 'password',
+ 'type' => 'password',
+ ] ),
+ [
+ 'label' => 'Password',
+ 'align' => 'top',
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\CheckboxInputWidget( [
+ 'name' => 'rememberme',
+ 'selected' => true,
+ ] ),
+ [
+ 'label' => 'Remember me',
+ 'align' => 'inline',
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\HiddenInputWidget( [
+ 'name' => 'hidden',
+ 'value' => 'hidden value',
+ ] )
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\ButtonInputWidget( [
+ 'type' => 'submit',
+ 'label' => 'Submit form',
+ ] )
+ ),
+ ]
+ ] ),
+ new OOUI\FieldsetLayout( [
+ 'label' => null,
+ 'items' => [
+ new OOUI\FieldLayout(
+ new OOUI\TextInputWidget( [
+ 'name' => 'summary',
+ ] ),
+ [
+ 'label' => 'Summary',
+ 'align' => 'top',
+ ]
+ ),
+ new OOUI\FieldLayout(
+ new OOUI\Widget( [
+ 'content' => new OOUI\HorizontalLayout( [
+ 'items' => [
+ new OOUI\ButtonInputWidget( [
+ 'name' => 'login',
+ 'label' => 'Log in',
+ 'type' => 'submit',
+ 'flags' => [ 'primary', 'progressive' ],
+ 'icon' => 'userAvatar',
+ ] ),
+ new OOUI\ButtonInputWidget( [
+ 'framed' => false,
+ 'flags' => [ 'destructive' ],
+ 'label' => 'Cancel',
+ ] ),
+ new OOUI\ButtonInputWidget( [
+ 'framed' => false,
+ 'icon' => 'tag',
+ 'label' => 'Random icon button',
+ ] ),
+ ]
+ ] ),
+ ] ),
+ [
+ 'label' => null,
+ 'align' => 'top',
+ ]
+ ),
+ ]
+ ] ),
+ ]
+] ) );
+
+echo $demoContainer;
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/styles/demo.css b/www/wiki/vendor/oojs/oojs-ui/demos/styles/demo.css
new file mode 100644
index 00000000..6ba71221
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/styles/demo.css
@@ -0,0 +1,600 @@
+body {
+ color: #222;
+ margin: 0 1em;
+ padding: 0;
+ font-family: sans-serif;
+}
+
+.oo-ui-theme-wikimediaui {
+ font-size: 0.875em;
+}
+
+.oo-ui-theme-apex {
+ font-size: 0.8em;
+}
+
+code {
+ /* Support: Blink, Gecko, Webkit */
+ /* Specify a valid second value to fix size, see T176636 */
+ font-family: monospace, monospace;
+}
+
+p {
+ margin: 0.5em 0;
+}
+
+/* Layout */
+.demo {
+ max-width: 62.5em;
+ margin: 0 auto 4.5em;
+}
+
+.demo-menu {
+ min-width: 320px; /* Let's not pretend it works on anything lower than that */
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.demo-menu > .oo-ui-widget {
+ display: inline-block;
+ vertical-align: middle;
+ margin-right: 1em;
+ margin-bottom: 1em;
+}
+
+.demo-menu .demo-pageDropdown {
+ width: 10em;
+}
+
+.demo-container {
+ /* Needed for applying `padding` further below */
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+/* Console */
+/* stylelint-disable selector-pseudo-element-colon-notation */
+.demo-console {
+ clear: both;
+ position: relative;
+ border: 1px solid transparent;
+ margin-bottom: -2px;
+ line-height: 1.4;
+ /* @noflip */
+ direction: ltr;
+}
+
+.demo-console-expanded {
+ width: 100%;
+ background-color: #fff;
+ border-color: #a2a9b1;
+ margin: 0.5em 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.demo-link-example,
+.demo-console-toggle {
+ float: right;
+ margin-top: -2.5em;
+ cursor: pointer;
+ -webkit-transition: background-color 100ms, color 100ms;
+ -moz-transition: background-color 100ms, color 100ms;
+ transition: background-color 100ms, color 100ms;
+}
+
+.demo-link-example {
+ position: relative;
+ top: 1px;
+ right: 2em;
+ opacity: 0;
+ -webkit-transition: opacity 100ms;
+ -moz-transition: opacity 100ms;
+ transition: opacity 100ms;
+}
+
+.oo-ui-fieldsetLayout-group > .oo-ui-fieldLayout:first-child .demo-link-example {
+ right: 7.2em;
+ opacity: 1;
+}
+
+.demo-console-expanded .demo-console-toggle {
+ margin-top: -3em;
+}
+
+.demo-link-example::after,
+.demo-console-toggle::after {
+ color: #36c;
+ position: relative;
+ display: inline-block;
+ margin-right: -1.2em;
+ padding: 0.703125em 0.9375em 0.625em; /* equals frameless button */
+ border-radius: 2px;
+ line-height: 1.172em;
+ font-weight: bold;
+ text-align: center;
+ -webkit-transition: color 100ms;
+ -moz-transition: color 100ms;
+ transition: color 100ms;
+}
+
+.demo-link-example:hover::after,
+.demo-console-toggle:hover::after {
+ color: #447ff5;
+}
+
+.demo-link-example::after {
+ content: '#';
+}
+
+.demo-container > .oo-ui-fieldsetLayout:first-child .oo-ui-fieldLayout:first-child .demo-link-example::after {
+ content: 'Link to this example #';
+}
+
+.demo-console-toggle::after {
+ content: '↓';
+}
+
+.demo-console-expanded .demo-console-toggle::after {
+ content: '↑';
+}
+
+.oo-ui-fieldsetLayout-group > .oo-ui-fieldLayout:first-child .demo-console-toggle::after {
+ content: 'Show code ↓';
+}
+
+.oo-ui-fieldsetLayout-group > .oo-ui-fieldLayout:first-child .demo-console-expanded .demo-console-toggle::after {
+ content: 'Hide code ↑';
+}
+
+.demo-link-example:focus,
+.oo-ui-fieldLayout:hover > .demo-link-example {
+ opacity: 1;
+}
+
+.demo-console-collapsed .demo-sample-code,
+.demo-console-collapsed .demo-console-log,
+.demo-console-collapsed .demo-console-label,
+.demo-console-collapsed .demo-console-submit {
+ display: none;
+}
+
+/* @noflip */
+.demo-console-log {
+ border: 1px solid #a2a9b1;
+ border-width: 0 0 1px 0;
+ max-height: 5em;
+ overflow: auto;
+}
+
+/* @noflip */
+.demo-console-log-line {
+ position: relative;
+ padding-left: 20px;
+}
+
+.demo-console-log-line-input {
+ font-style: italic;
+ color: #54595d;
+}
+
+/* @noflip */
+.demo-console-log-line-input::before {
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 20px;
+ text-align: center;
+ bottom: 0;
+ content: '→';
+}
+
+.demo-console-log-line-error {
+ color: #d33;
+}
+
+/* @noflip */
+.demo-console-label {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ padding-left: 20px;
+ padding-right: 20px;
+ margin-right: -20px;
+ cursor: pointer;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+/* @noflip */
+.demo-console-label::before {
+ content: '→';
+ color: #00f;
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 20px;
+ text-align: center;
+}
+
+.demo-console-input {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ width: 100%;
+}
+
+.demo-console-input:focus {
+ outline: 0;
+}
+
+.demo-console-submit {
+ background: #f8f9fa;
+ color: #222;
+ display: inline-block;
+ position: relative;
+ width: 20px;
+ line-height: 1.6;
+ text-align: center;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ cursor: pointer;
+ -webkit-transition: background-color 100ms, color 100ms;
+ -moz-transition: background-color 100ms, color 100ms;
+ transition: background-color 100ms, color 100ms;
+}
+
+.demo-console-submit:hover {
+ background: #fff;
+ color: #444;
+}
+
+.demo-sample-code {
+ /* Need to override Prism (syntax highlighter) styles */
+ background-color: #eaecf0;
+ margin: 0 !important; /* stylelint-disable-line declaration-no-important */
+}
+
+/* Toolbars demo */
+
+.demo-container.demo-toolbars {
+ padding: 0;
+}
+
+.demo-toolbar {
+ margin-top: 4em;
+}
+
+.demo-toolbars-contents {
+ padding: 2em;
+ min-height: 100px;
+}
+
+/*
+ * VisualEditor FormatTool styles.
+ *
+ * @copyright 2011-2018 VisualEditor Team and others; see http://ve.mit-license.org
+ */
+
+.oo-ui-menuToolGroup .oo-ui-tool-name-paragraph .oo-ui-tool-title {
+ font-weight: normal;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-name-heading1 .oo-ui-tool-title {
+ font-size: 190%;
+ font-weight: normal;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-name-heading2 .oo-ui-tool-title {
+ font-size: 150%;
+ font-weight: normal;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-name-heading3 .oo-ui-tool-title {
+ font-size: 130%;
+ font-weight: bold;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-name-heading4 .oo-ui-tool-title {
+ font-size: 115%;
+ font-weight: bold;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-name-heading5 .oo-ui-tool-title {
+ font-size: 100%;
+ font-weight: bold;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-name-heading6 .oo-ui-tool-title {
+ font-size: 80%;
+ font-weight: bold;
+}
+
+.oo-ui-theme-apex .oo-ui-menuToolGroup .oo-ui-tool-name-heading1 .oo-ui-tool-title,
+.oo-ui-theme-apex .oo-ui-menuToolGroup .oo-ui-tool-name-heading2 .oo-ui-tool-title,
+.oo-ui-theme-apex .oo-ui-menuToolGroup .oo-ui-tool-name-heading3 .oo-ui-tool-title,
+.oo-ui-theme-apex .oo-ui-menuToolGroup .oo-ui-tool-name-heading4 .oo-ui-tool-title,
+.oo-ui-theme-apex .oo-ui-menuToolGroup .oo-ui-tool-name-heading5 .oo-ui-tool-title,
+.oo-ui-theme-apex .oo-ui-menuToolGroup .oo-ui-tool-name-heading6 .oo-ui-tool-title {
+ /* Use px so padding is not changed by font size. This is normally 0.5em. */
+ padding-left: 6.4px;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-name-preformatted .oo-ui-tool-title {
+ /* Support: Blink, Gecko, Webkit */
+ /* Specify a valid second value to fix size, see T176636 */
+ font-family: monospace, monospace;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-name-blockquote .oo-ui-tool-title {
+ /* Indent in addition to padding */
+ text-indent: 1.5em;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-name-tableCellHeader .oo-ui-tool-title {
+ font-weight: bold;
+}
+
+/* Icons demo */
+
+.demo-icons .oo-ui-buttonSelectWidget {
+ margin-bottom: 2em;
+}
+
+.demo-icons .oo-ui-fieldLayout {
+ display: inline-block;
+ margin: 1em 1em 1em 0;
+ width: 13.75em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.demo-icons .oo-ui-fieldsetLayout-group {
+ margin-right: -1em;
+}
+/* stylelint-disable indentation */
+.demo-icons .oo-ui-fieldLayout .oo-ui-iconElement:not( .oo-ui-image-progressive ):not( .oo-ui-image-destructive ),
+.demo-icons .oo-ui-fieldLayout .oo-ui-indicatorElement {
+ opacity: 0.87; /* brings icons/indicators closer to text color */
+ /* Support Chrome by promoting layer to GPU, see T182257 */
+ -webkit-transform: translateZ( 0 );
+ transform: translateZ( 0 );
+}
+/* stylelint-enable indentation */
+.demo-icons .oo-ui-fieldLayout:hover .oo-ui-labelElement-label {
+ color: #000;
+}
+.demo-icons .oo-ui-fieldLayout:hover .oo-ui-iconElement,
+.demo-icons .oo-ui-fieldLayout:hover .oo-ui-indicatorElement {
+ opacity: 1 !important; /* stylelint-disable-line declaration-no-important */
+}
+
+/* Widgets demo */
+
+.oo-ui-horizontalLayout > .oo-ui-textInputWidget,
+.oo-ui-horizontalLayout > .oo-ui-dropdownInputWidget {
+ max-width: 10em;
+}
+
+.demo-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+/* Special cases: ActionFieldLayout top aligned,
+FieldLayout left & right aligned */
+.oo-ui-fieldLayout-align-left,
+.oo-ui-fieldLayout-align-right {
+ max-width: 50em;
+}
+
+.oo-ui-fieldLayout-align-top.oo-ui-actionFieldLayout .demo-link-example,
+.oo-ui-fieldLayout-align-top.oo-ui-actionFieldLayout .demo-console-toggle,
+.oo-ui-fieldLayout-align-left .demo-link-example,
+.oo-ui-fieldLayout-align-left .demo-console-toggle,
+.oo-ui-fieldLayout-align-right .demo-link-example,
+.oo-ui-fieldLayout-align-right .demo-console-toggle {
+ margin-right: -2em;
+}
+
+.oo-ui-fieldLayout-body:after {
+ content: ' ';
+ clear: both;
+ display: block;
+}
+
+/* Special case: FieldsetLayout with "Summary" */
+.oo-ui-formLayout .oo-ui-fieldsetLayout:last-child {
+ background-color: #eaecf0;
+ border: 1px solid #c8ccd1;
+ padding: 1em 1em 1.5em 1em;
+}
+
+/*
+ * Support: iOS 9.2, Android 4.4.4, Op Mobile 37, Chrome/Android 57, Fx/Android 52, UC Browser 11.4, Baidu 7.12
+ * Workaround for weak ancient mobile browser support of `fixed` positioning
+ */
+@supports ( position: fixed ) {
+ .demo-menu {
+ background-color: #fff;
+ position: fixed;
+ top: 0;
+ border-bottom: 1px solid #a2a9b1;
+ padding-top: 1em;
+ box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.25 );
+ z-index: 5;
+ }
+
+ /* This needs extra specificity to beat PanelLayout styles */
+ .demo-container.oo-ui-panelLayout {
+ /* Apex overrides. WikimediaUI wins for now in the demo framing in this browser subset */
+ border-color: #a2a9b1;
+ border-radius: 2px;
+ box-shadow: none;
+ }
+
+ .oo-ui-windowManager-modal > .oo-ui-dialog,
+ .oo-ui-processDialog-errors {
+ z-index: 6;
+ }
+}
+
+/* Media Queries */
+@media ( min-width: 320px ) {
+ .oo-ui-theme-wikimediaui,
+ .oo-ui-theme-apex {
+ font-size: 1em;
+ }
+
+ .demo-menu > .oo-ui-widget {
+ margin-bottom: 1em;
+ }
+
+ .demo-container {
+ border-radius: 0;
+ border-width: 1px 0 0;
+ padding: 1.5em 2.5em 1em 0;
+ }
+
+ .demo-container.demo-toolbars {
+ border-width: 1px;
+ }
+
+ .demo-console-expanded {
+ width: calc( 100% + 2.5em ); /* equals `100%` + `padding` of `.demo-container` above */
+ }
+
+ .demo-link-example,
+ .demo-console-toggle {
+ margin-right: -2.5em;
+ }
+
+ .demo-console-expanded .demo-console-toggle {
+ margin-right: 0;
+ }
+
+ .oo-ui-fieldsetLayout-group > .oo-ui-fieldLayout:first-child .demo-link-example,
+ .oo-ui-fieldsetLayout-group > .oo-ui-fieldLayout:first-child .demo-console-toggle {
+ margin-top: 0;
+ }
+
+ .oo-ui-fieldsetLayout-group > .oo-ui-fieldLayout:first-child .demo-console-expanded .demo-console-toggle {
+ margin-top: -0.5em;
+ }
+
+ @supports ( position: fixed ) {
+ .demo-menu {
+ min-height: 11.4em;
+ left: 1em;
+ right: 1em;
+ }
+
+ /* Hide “Docs“ Button on very small screens */
+ .demo-menu > .demo-button-docs {
+ display: none;
+ }
+
+ /* This needs extra specificity to beat PanelLayout styles */
+ .demo-menu + .demo-container.oo-ui-panelLayout {
+ margin-top: 11.4em;
+ }
+
+ /* Avoid `box-shadow` from menu lurkin into toolbar demo, +1.2em to be harmonious with menu */
+ .demo-menu + .demo-container.oo-ui-panelLayout.demo-toolbars {
+ margin-top: 12.6em;
+ }
+ }
+}
+
+@media ( min-width: 568px ) {
+ @supports ( position: fixed ) {
+ .demo-menu {
+ min-height: 7.5em;
+ }
+
+ .demo-menu > .demo-button-docs {
+ display: inline-block;
+ }
+
+ .demo-menu + .demo-container.oo-ui-panelLayout {
+ margin-top: 7.5em;
+ }
+
+ .demo-menu + .demo-container.oo-ui-panelLayout.demo-toolbars {
+ margin-top: 8.7em;
+ }
+
+ .demo-console-expanded .demo-console-toggle {
+ margin-right: 0.5em;
+ }
+ }
+}
+
+/* @media ( min-width: 768px ) {} */
+
+@media ( min-width: 960px ) {
+ .oo-ui-theme-wikimediaui {
+ font-size: 0.875em;
+ }
+
+ .oo-ui-theme-apex {
+ font-size: 0.8em;
+ }
+
+ .demo-container {
+ border-radius: 2px;
+ border-width: 1px;
+ padding: 2em;
+ }
+
+ .demo-menu {
+ width: 62.5em;
+ white-space: nowrap;
+ }
+
+ .demo-console-expanded {
+ width: 100%;
+ }
+
+ .demo-link-example,
+ .demo-console-toggle,
+ .demo-console-expanded .demo-console-toggle {
+ margin-right: 0;
+ }
+
+ .oo-ui-fieldsetLayout-group > .oo-ui-fieldLayout:first-child .demo-link-example,
+ .oo-ui-fieldsetLayout-group > .oo-ui-fieldLayout:first-child .demo-console-toggle {
+ margin-top: -2.5em;
+ }
+
+ .oo-ui-fieldsetLayout-group > .oo-ui-fieldLayout:first-child .demo-console-expanded .demo-console-toggle {
+ margin-top: -3em;
+ }
+
+ @supports ( position: fixed ) {
+ .demo-menu {
+ min-height: 4.5em;
+ left: auto;
+ right: auto;
+ }
+
+ .demo-menu + .demo-container.oo-ui-panelLayout {
+ margin-top: 4.5em;
+ }
+
+ .demo-menu + .demo-container.oo-ui-panelLayout.demo-toolbars {
+ margin-top: 5.7em;
+ }
+ }
+}
+/* stylelint-enable selector-pseudo-element-colon-notation */
diff --git a/www/wiki/vendor/oojs/oojs-ui/demos/widgets.php b/www/wiki/vendor/oojs/oojs-ui/demos/widgets.php
new file mode 100644
index 00000000..6f95205d
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/demos/widgets.php
@@ -0,0 +1,3 @@
+<?php
+// Redirect to keep old URLs working
+header( 'Location: demos.php?' . http_build_query( $_GET ) );
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ace.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ace.json
new file mode 100644
index 00000000..0fdc1a89
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ace.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Si Gam Acèh"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pinah item u yup",
+ "ooui-outline-control-move-up": "Pinah item u ateuëh",
+ "ooui-toolbar-more": "Lom"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/af.json b/www/wiki/vendor/oojs/oojs-ui/i18n/af.json
new file mode 100644
index 00000000..ed56521f
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/af.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Naudefj",
+ "Fwolff"
+ ]
+ },
+ "ooui-outline-control-move-down": "Skuif item af",
+ "ooui-outline-control-move-up": "Skuif item op",
+ "ooui-outline-control-remove": "Verwyder item",
+ "ooui-toolbar-more": "Meer",
+ "ooui-toolgroup-expand": "Meer",
+ "ooui-toolgroup-collapse": "Minder",
+ "ooui-dialog-message-accept": "Regso",
+ "ooui-dialog-message-reject": "Kanselleer",
+ "ooui-dialog-process-error": "Iets het verkeerd gegaan",
+ "ooui-dialog-process-dismiss": "Sluit",
+ "ooui-dialog-process-retry": "Probeer weer",
+ "ooui-dialog-process-continue": "Gaan voort",
+ "ooui-selectfile-button-select": "Kies 'n lêer",
+ "ooui-selectfile-not-supported": "Lêers kan nie gekies word nie",
+ "ooui-selectfile-placeholder": "Geen lêer is gekies nie",
+ "ooui-selectfile-dragdrop-placeholder": "Laat val die lêer hier"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ais.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ais.json
new file mode 100644
index 00000000..42eb8c2e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ais.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bunukwiki",
+ "Benel"
+ ]
+ },
+ "ooui-outline-control-move-down": "miliad kasacacay tasasa’",
+ "ooui-outline-control-move-up": "miliad kasacacay tapabaw",
+ "ooui-outline-control-remove": "misipu kasacacay",
+ "ooui-toolbar-more": "yadah",
+ "ooui-toolgroup-expand": "yadah",
+ "ooui-toolgroup-collapse": "ma’ngadis mangalep",
+ "ooui-item-remove": "milimad",
+ "ooui-dialog-message-accept": "malucekay",
+ "ooui-dialog-message-reject": "palawpes",
+ "ooui-dialog-process-error": "tahkal ku caykapulitaay a mungangaw",
+ "ooui-dialog-process-dismiss": "edeben",
+ "ooui-dialog-process-retry": "pitaneng henay aca",
+ "ooui-dialog-process-continue": "palalid",
+ "ooui-selectfile-button-select": "mipili’ cacay a tangan",
+ "ooui-selectfile-not-supported": "la’cus midama mipili’ay a tangan",
+ "ooui-selectfile-placeholder": "caay henay mipili’ tu tangan",
+ "ooui-selectfile-dragdrop-placeholder": "mutengteng tangan katukuh itini"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/am.json b/www/wiki/vendor/oojs/oojs-ui/i18n/am.json
new file mode 100644
index 00000000..bfe9d5c3
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/am.json
@@ -0,0 +1,7 @@
+{
+ "@metadata": {
+ "authors": [
+ "Elfalem"
+ ]
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ar.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ar.json
new file mode 100644
index 00000000..ad2995a7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ar.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ciphers",
+ "Claw eg",
+ "Elfalem",
+ "Jdforrester",
+ "Mido",
+ "OsamaK",
+ "زكريا",
+ "مشعل الحربي",
+ "ترجمان05",
+ "Abanima",
+ "محمد أحمد عبد الفتاح",
+ "Hiba Alshawi",
+ "Meno25"
+ ]
+ },
+ "ooui-outline-control-move-down": "انقل العنصر للأسفل",
+ "ooui-outline-control-move-up": "انقل العنصر للأعلى",
+ "ooui-outline-control-remove": "أزل العنصر",
+ "ooui-toolbar-more": "مزيد",
+ "ooui-toolgroup-expand": "مزيد",
+ "ooui-toolgroup-collapse": "أقل",
+ "ooui-item-remove": "إزالة",
+ "ooui-dialog-message-accept": "موافق",
+ "ooui-dialog-message-reject": "ألغ",
+ "ooui-dialog-process-error": "حدث خطأ",
+ "ooui-dialog-process-dismiss": "أغلق",
+ "ooui-dialog-process-retry": "حاول مرة أخرى",
+ "ooui-dialog-process-continue": "استمر",
+ "ooui-selectfile-button-select": "اختر ملفا",
+ "ooui-selectfile-not-supported": "اختيار الملفات غير مدعوم",
+ "ooui-selectfile-placeholder": "لم يتم اختيار أي ملف",
+ "ooui-selectfile-dragdrop-placeholder": "اترك الملف هنا"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/arc.json b/www/wiki/vendor/oojs/oojs-ui/i18n/arc.json
new file mode 100644
index 00000000..de5b7aff
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/arc.json
@@ -0,0 +1,7 @@
+{
+ "@metadata": {
+ "authors": [
+ "Basharh"
+ ]
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/arq.json b/www/wiki/vendor/oojs/oojs-ui/i18n/arq.json
new file mode 100644
index 00000000..61eb3844
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/arq.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bachounda"
+ ]
+ },
+ "ooui-outline-control-move-down": "هبط الشيئ للتحت",
+ "ooui-outline-control-move-up": "طلع الشيئ للفوق",
+ "ooui-outline-control-remove": "أمحي العنصر",
+ "ooui-toolbar-more": "زيادة",
+ "ooui-toolgroup-expand": "زيادة",
+ "ooui-toolgroup-collapse": "قليل",
+ "ooui-dialog-message-accept": "مليح",
+ "ooui-dialog-message-reject": "رجَع",
+ "ooui-dialog-process-error": "حاجه ما خدمتش مليح",
+ "ooui-dialog-process-dismiss": "أرفضها",
+ "ooui-dialog-process-retry": "عاود جرب",
+ "ooui-dialog-process-continue": "واصل",
+ "ooui-selectfile-not-supported": "تحديد الفيشيات ما هوش محدد",
+ "ooui-selectfile-placeholder": "ما اختاريتش حتا ملف"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/as.json b/www/wiki/vendor/oojs/oojs-ui/i18n/as.json
new file mode 100644
index 00000000..54a42441
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/as.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gitartha.bordoloi",
+ "Dibya Dutta",
+ "IKHazarika"
+ ]
+ },
+ "ooui-outline-control-move-down": "সমল তললৈ স্থানান্তৰ কৰক",
+ "ooui-outline-control-move-up": "সমল ওপৰলৈ স্থানান্তৰ কৰক",
+ "ooui-outline-control-remove": "সমল আঁতৰাওক",
+ "ooui-toolbar-more": "অধিক",
+ "ooui-toolgroup-expand": "অধিক",
+ "ooui-toolgroup-collapse": "কম দেখাওক",
+ "ooui-dialog-message-accept": "বাৰু",
+ "ooui-dialog-message-reject": "বাতিল কৰক",
+ "ooui-dialog-process-error": "কিবা ত্ৰুটি হৈছে",
+ "ooui-dialog-process-dismiss": "বাতিল",
+ "ooui-dialog-process-retry": "পুনৰ চেষ্টা কৰক",
+ "ooui-dialog-process-continue": "অব্যাহত ৰাখক",
+ "ooui-selectfile-button-select": "ফাইল নিৰ্বাচন কৰক",
+ "ooui-selectfile-not-supported": "নথি নিৰ্বাচন সমৰ্থন কৰা নাই",
+ "ooui-selectfile-placeholder": "কোনো নথি নিৰ্বাচিত কৰা হোৱা নাই",
+ "ooui-selectfile-dragdrop-placeholder": "ইয়াত ফাইল এৰক"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ast.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ast.json
new file mode 100644
index 00000000..623892df
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ast.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Basharh",
+ "Bishnu Saikia",
+ "Xuacu"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mover abaxo l'elementu",
+ "ooui-outline-control-move-up": "Mover arriba l'elementu",
+ "ooui-outline-control-remove": "Desaniciar elementu",
+ "ooui-toolbar-more": "Más",
+ "ooui-toolgroup-expand": "Más",
+ "ooui-toolgroup-collapse": "Menos",
+ "ooui-item-remove": "Desaniciar",
+ "ooui-dialog-message-accept": "Aceutar",
+ "ooui-dialog-message-reject": "Encaboxar",
+ "ooui-dialog-process-error": "Daqué funcionó mal",
+ "ooui-dialog-process-dismiss": "Descartar",
+ "ooui-dialog-process-retry": "Vuelvi a intentalo",
+ "ooui-dialog-process-continue": "Siguir",
+ "ooui-selectfile-button-select": "Seleicionar un ficheru",
+ "ooui-selectfile-not-supported": "Nun hai encontu pa la seleición de ficheros",
+ "ooui-selectfile-placeholder": "Nun se seleicionó nengún ficheru",
+ "ooui-selectfile-dragdrop-placeholder": "Soltar el ficheru equí"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/awa.json b/www/wiki/vendor/oojs/oojs-ui/i18n/awa.json
new file mode 100644
index 00000000..f78ed326
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/awa.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "1AnuraagPandey"
+ ]
+ },
+ "ooui-toolbar-more": "अउर"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/az.json b/www/wiki/vendor/oojs/oojs-ui/i18n/az.json
new file mode 100644
index 00000000..96b95d1a
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/az.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cekli829",
+ "Interfase",
+ "Jduranboger",
+ "Wertuose"
+ ]
+ },
+ "ooui-outline-control-move-down": "Bəndi aşağı apar",
+ "ooui-outline-control-move-up": "Bəndi yuxarı apar",
+ "ooui-outline-control-remove": "Bəndi sil",
+ "ooui-toolbar-more": "Daha artıq",
+ "ooui-toolgroup-collapse": "Daha az"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/azb.json b/www/wiki/vendor/oojs/oojs-ui/i18n/azb.json
new file mode 100644
index 00000000..313122ce
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/azb.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sadiqr"
+ ]
+ },
+ "ooui-dialog-message-reject": "وازگئچ",
+ "ooui-dialog-process-continue": "داوام ائت",
+ "ooui-selectfile-button-select": "بیر فایل سئچ",
+ "ooui-selectfile-placeholder": "هئچ فایل سئچیلمه‌ییب"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ba.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ba.json
new file mode 100644
index 00000000..d8c99aaf
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ba.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "AiseluRB",
+ "Amire80",
+ "Assele",
+ "Haqmar",
+ "Sagan",
+ "Рустам Нурыев",
+ "Азат Хәлилов"
+ ]
+ },
+ "ooui-outline-control-move-down": "Элементты аҫҡа күсерергә",
+ "ooui-outline-control-move-up": "Элементты өҫкә күсерергә",
+ "ooui-outline-control-remove": "Биттәрҙе юйырға",
+ "ooui-toolbar-more": "Тағы",
+ "ooui-toolgroup-expand": "Күберәк",
+ "ooui-toolgroup-collapse": "Аҙыраҡ",
+ "ooui-dialog-message-accept": "Тамам",
+ "ooui-dialog-message-reject": "Кире алырға",
+ "ooui-dialog-process-error": "Нимәлер килеп сыҡманы.",
+ "ooui-dialog-process-dismiss": "Йәшерергә",
+ "ooui-dialog-process-retry": "Ҡабатлап ҡарарға.",
+ "ooui-dialog-process-continue": "Дауам итергә",
+ "ooui-selectfile-button-select": "Файлды һайлағыҙ",
+ "ooui-selectfile-not-supported": "Файл һайлау хупланмай.",
+ "ooui-selectfile-placeholder": "Файл һайланмаған",
+ "ooui-selectfile-dragdrop-placeholder": "Файлды бында күсерегеҙ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/bcc.json b/www/wiki/vendor/oojs/oojs-ui/i18n/bcc.json
new file mode 100644
index 00000000..a340a881
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/bcc.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Baloch Afghanistan"
+ ]
+ },
+ "ooui-dialog-message-accept": "اوکی",
+ "ooui-dialog-process-retry": "پدا کوشش کورتین"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/bcl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/bcl.json
new file mode 100644
index 00000000..bc2251e8
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/bcl.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Geopoet",
+ "Sky Harbor"
+ ]
+ },
+ "ooui-outline-control-move-down": "Balyuhon an aytem paibaba",
+ "ooui-outline-control-move-up": "Balyuhon an aytem paitaas",
+ "ooui-toolbar-more": "Kadugangan"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/be-tarask.json b/www/wiki/vendor/oojs/oojs-ui/i18n/be-tarask.json
new file mode 100644
index 00000000..40a6efd0
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/be-tarask.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "EugeneZelenko",
+ "Wizardist",
+ "Чаховіч Уладзіслаў",
+ "Zedlik",
+ "Red Winged Duck",
+ "Renessaince"
+ ]
+ },
+ "ooui-outline-control-move-down": "Перасунуць элемэнт ніжэй",
+ "ooui-outline-control-move-up": "Перасунуць элемэнт вышэй",
+ "ooui-outline-control-remove": "Выдаліць пункт",
+ "ooui-toolbar-more": "Болей",
+ "ooui-toolgroup-expand": "Болей",
+ "ooui-toolgroup-collapse": "Меней",
+ "ooui-item-remove": "Выдаліць",
+ "ooui-dialog-message-accept": "Добра",
+ "ooui-dialog-message-reject": "Скасаваць",
+ "ooui-dialog-process-error": "Нешта пайшло ня так",
+ "ooui-dialog-process-dismiss": "Прапусьціць",
+ "ooui-dialog-process-retry": "Паспрабаваць зноў",
+ "ooui-dialog-process-continue": "Працягваць",
+ "ooui-selectfile-button-select": "Абраць файл",
+ "ooui-selectfile-not-supported": "Выбар файлу не падтрымліваецца",
+ "ooui-selectfile-placeholder": "Ніводзін файл не абраны",
+ "ooui-selectfile-dragdrop-placeholder": "Перацягніце файл сюды"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/be.json b/www/wiki/vendor/oojs/oojs-ui/i18n/be.json
new file mode 100644
index 00000000..7b4e5468
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/be.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Чаховіч Уладзіслаў",
+ "Artificial123",
+ "Goshaproject",
+ "Mechanizatar"
+ ]
+ },
+ "ooui-outline-control-move-down": "Перамясціць элемент ўніз",
+ "ooui-outline-control-move-up": "Перамясціць элемент уверх",
+ "ooui-outline-control-remove": "Выдаліць элемент",
+ "ooui-toolbar-more": "Яшчэ",
+ "ooui-toolgroup-expand": "Яшчэ",
+ "ooui-toolgroup-collapse": "Менш",
+ "ooui-dialog-message-accept": "ОК",
+ "ooui-dialog-message-reject": "Адмяніць",
+ "ooui-dialog-process-error": "Штось пайшло не так…",
+ "ooui-dialog-process-dismiss": "Прапусціць",
+ "ooui-dialog-process-retry": "Паспрабаваць яшчэ раз",
+ "ooui-dialog-process-continue": "Працягнуць",
+ "ooui-selectfile-button-select": "Выбраць файл",
+ "ooui-selectfile-not-supported": "Выбраны файл не падтрымліваецца",
+ "ooui-selectfile-placeholder": "Файл не выбраны"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/bg.json b/www/wiki/vendor/oojs/oojs-ui/i18n/bg.json
new file mode 100644
index 00000000..3ae0ec9e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/bg.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "DCLXVI",
+ "Hristofor.mirchev",
+ "පසිඳු කාවින්ද",
+ "Mitzev",
+ "Aquilax",
+ "Vodnokon4e",
+ "StanProg"
+ ]
+ },
+ "ooui-outline-control-move-down": "Преместване на елемента надолу",
+ "ooui-outline-control-move-up": "Преместване на елемента нагоре",
+ "ooui-outline-control-remove": "Премахване на обекта",
+ "ooui-toolbar-more": "Още",
+ "ooui-toolgroup-expand": "Още",
+ "ooui-toolgroup-collapse": "По-малко",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Отказ",
+ "ooui-dialog-process-error": "Нещо се обърка",
+ "ooui-dialog-process-dismiss": "Затваряне",
+ "ooui-dialog-process-retry": "Опитайте отново",
+ "ooui-dialog-process-continue": "Продължаване",
+ "ooui-selectfile-button-select": "Избиране на файл",
+ "ooui-selectfile-not-supported": "Избраният файл не се поддържа",
+ "ooui-selectfile-placeholder": "Не е избран файл",
+ "ooui-selectfile-dragdrop-placeholder": "Пуснете файла тук"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/bho.json b/www/wiki/vendor/oojs/oojs-ui/i18n/bho.json
new file mode 100644
index 00000000..9697db02
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/bho.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "SatyamMishra"
+ ]
+ },
+ "ooui-outline-control-move-down": "आइटम नीचे घसकाईं",
+ "ooui-outline-control-move-up": "आइटम ऊपर घसकाईं",
+ "ooui-outline-control-remove": "आइटम हटाईं",
+ "ooui-toolbar-more": "अउरी",
+ "ooui-toolgroup-expand": "अउरी",
+ "ooui-toolgroup-collapse": "कम",
+ "ooui-dialog-message-accept": "ओके",
+ "ooui-dialog-message-reject": "कैंसिल",
+ "ooui-dialog-process-error": "कुछ गड़बड़ी हो गइल",
+ "ooui-dialog-process-dismiss": "रद्द",
+ "ooui-dialog-process-retry": "दोबारा कोसिस करीं",
+ "ooui-dialog-process-continue": "जारी राखीं",
+ "ooui-selectfile-button-select": "एगो फाइल चुनीं",
+ "ooui-selectfile-not-supported": "फाइल के चुनाव के सपोर्ट नइखे",
+ "ooui-selectfile-placeholder": "कौनों फाइल नइखे चुनल गइल",
+ "ooui-selectfile-dragdrop-placeholder": "फाइल इहाँ ड्रॉप करीं"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/bn.json b/www/wiki/vendor/oojs/oojs-ui/i18n/bn.json
new file mode 100644
index 00000000..273b7db1
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/bn.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aftab1995",
+ "Bellayet",
+ "Jayantanth",
+ "Nasir8891",
+ "Runab",
+ "Sayak Sarkar",
+ "Aftabuzzaman",
+ "RYasmeen (WMF)",
+ "NahidSultan"
+ ]
+ },
+ "ooui-outline-control-move-down": "আইটেম নিচে স্থানান্তর",
+ "ooui-outline-control-move-up": "আইটেম উপরে স্থানান্তর",
+ "ooui-outline-control-remove": "আইটেম সরান",
+ "ooui-toolbar-more": "আরও",
+ "ooui-toolgroup-expand": "আরও",
+ "ooui-toolgroup-collapse": "কম দেখাও",
+ "ooui-item-remove": "সরান",
+ "ooui-dialog-message-accept": "ঠিক আছে",
+ "ooui-dialog-message-reject": "বাতিল",
+ "ooui-dialog-process-error": "কিছু একটায় ত্রুটি হয়েছে",
+ "ooui-dialog-process-dismiss": "বাতিল করুন",
+ "ooui-dialog-process-retry": "আবার চেষ্টা করুন",
+ "ooui-dialog-process-continue": "অগ্রসর হোন",
+ "ooui-selectfile-button-select": "একটি ফাইল নির্বাচন করুন",
+ "ooui-selectfile-not-supported": "চিত্র নির্বাচন সমর্থিত নয়",
+ "ooui-selectfile-placeholder": "কোন চিত্র নির্বাচিত হয়নি",
+ "ooui-selectfile-dragdrop-placeholder": "এখানে ফাইল ছাড়ুন"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/bqi.json b/www/wiki/vendor/oojs/oojs-ui/i18n/bqi.json
new file mode 100644
index 00000000..a0e53b36
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/bqi.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mogoeilor"
+ ]
+ },
+ "ooui-outline-control-move-down": "ڤا دڤۈن بوردن آیتم",
+ "ooui-outline-control-move-up": "ڤارو بردن آیتم",
+ "ooui-outline-control-remove": "ڤورداشتن آیتم",
+ "ooui-toolbar-more": "بیشتر",
+ "ooui-toolgroup-expand": "بیشتر",
+ "ooui-toolgroup-collapse": "کمتر",
+ "ooui-dialog-message-accept": "خۈڤإ",
+ "ooui-dialog-message-reject": "أنجومشيڤ کردن",
+ "ooui-dialog-process-error": "یأ چي ايچو إشتوا إ",
+ "ooui-dialog-process-retry": "ز نۉ تلاش کونين",
+ "ooui-dialog-process-continue": "ديندا گرهڌن",
+ "ooui-selectfile-button-select": "گولإڤورچين کردن جانیا",
+ "ooui-selectfile-not-supported": "گول ڤورچی کردن جانیا کونشتکاری نڤابیڌ",
+ "ooui-selectfile-placeholder": "هيژ جانيایي گولإ ڤورچين نڤابيڌإ",
+ "ooui-selectfile-dragdrop-placeholder": "جانيانأ ڤأنين ايچو"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/br.json b/www/wiki/vendor/oojs/oojs-ui/i18n/br.json
new file mode 100644
index 00000000..1383d9aa
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/br.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Fohanno",
+ "Fulup",
+ "Y-M D",
+ "Maoris",
+ "Gwendal"
+ ]
+ },
+ "ooui-outline-control-move-down": "Lakaat an elfenn da ziskenn",
+ "ooui-outline-control-move-up": "Lakaat an elfenn da bignat",
+ "ooui-outline-control-remove": "Tennañ an elfenn",
+ "ooui-toolbar-more": "Muioc'h",
+ "ooui-toolgroup-expand": "Muioc'h",
+ "ooui-toolgroup-collapse": "Nebeutoc'h",
+ "ooui-item-remove": "Dilemel",
+ "ooui-dialog-message-accept": "Mat eo",
+ "ooui-dialog-message-reject": "Nullañ",
+ "ooui-dialog-process-error": "Un dra bennak a-dreuz a zo bet",
+ "ooui-dialog-process-dismiss": "Disteurel",
+ "ooui-dialog-process-retry": "Klask en-dro",
+ "ooui-dialog-process-continue": "Kenderc'hel",
+ "ooui-selectfile-button-select": "Diuzañ ur restr",
+ "ooui-selectfile-not-supported": "N'eo ket skoret an diuzañ restroù",
+ "ooui-selectfile-placeholder": "N'eus bet diuzet restr ebet",
+ "ooui-selectfile-dragdrop-placeholder": "Lezel ar restr amañ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/bs.json b/www/wiki/vendor/oojs/oojs-ui/i18n/bs.json
new file mode 100644
index 00000000..2bc85233
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/bs.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "DzWiki",
+ "Semso98",
+ "Srdjan m"
+ ]
+ },
+ "ooui-outline-control-move-down": "Premjesti stavku dolje",
+ "ooui-outline-control-move-up": "Premjesti stavku gore",
+ "ooui-outline-control-remove": "Ukloni stavku",
+ "ooui-toolbar-more": "Više",
+ "ooui-toolgroup-expand": "Više",
+ "ooui-toolgroup-collapse": "Manje",
+ "ooui-item-remove": "Ukloni",
+ "ooui-dialog-message-accept": "U redu",
+ "ooui-dialog-message-reject": "Otkaži",
+ "ooui-dialog-process-error": "Nešto nije u redu",
+ "ooui-dialog-process-dismiss": "Odbaci",
+ "ooui-dialog-process-retry": "Pokušaj ponovo",
+ "ooui-dialog-process-continue": "Nastavi",
+ "ooui-selectfile-button-select": "Izaberite datoteku",
+ "ooui-selectfile-not-supported": "Izbor datoteke nije podržan",
+ "ooui-selectfile-placeholder": "Datoteka nije izabrana",
+ "ooui-selectfile-dragdrop-placeholder": "Prevucite datoteku ovdje"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ca.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ca.json
new file mode 100644
index 00000000..96d782ee
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ca.json
@@ -0,0 +1,35 @@
+{
+ "@metadata": {
+ "authors": [
+ "Alvaro Vidal-Abarca",
+ "Amire80",
+ "Arnaugir",
+ "Pginer",
+ "QuimGil",
+ "SMP",
+ "Vriullop",
+ "Toniher",
+ "Edustus",
+ "Davidpar",
+ "Maceleiro",
+ "Kippelboy",
+ "Macofe"
+ ]
+ },
+ "ooui-outline-control-move-down": "Baixa l'element",
+ "ooui-outline-control-move-up": "Puja l'element",
+ "ooui-outline-control-remove": "Esborra l'ítem",
+ "ooui-toolbar-more": "Més",
+ "ooui-toolgroup-expand": "Més",
+ "ooui-toolgroup-collapse": "Menys",
+ "ooui-dialog-message-accept": "D'acord",
+ "ooui-dialog-message-reject": "Cancel·la",
+ "ooui-dialog-process-error": "Alguna cosa no ha funcionat",
+ "ooui-dialog-process-dismiss": "Descarta",
+ "ooui-dialog-process-retry": "Torneu-ho a provar",
+ "ooui-dialog-process-continue": "Continua",
+ "ooui-selectfile-button-select": "Seleccioneu un fitxer",
+ "ooui-selectfile-not-supported": "El tipus de fitxer no és compatible",
+ "ooui-selectfile-placeholder": "No s'ha seleccionat cap fitxer",
+ "ooui-selectfile-dragdrop-placeholder": "Deseu els arxius aquí"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/cdo.json b/www/wiki/vendor/oojs/oojs-ui/i18n/cdo.json
new file mode 100644
index 00000000..cb46b437
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/cdo.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Yejianfei"
+ ]
+ },
+ "ooui-outline-control-move-down": "下移項目",
+ "ooui-outline-control-move-up": "上移項目",
+ "ooui-outline-control-remove": "移除項目",
+ "ooui-toolbar-more": "更価",
+ "ooui-toolgroup-expand": "更価",
+ "ooui-toolgroup-collapse": "更少",
+ "ooui-dialog-message-accept": "確定",
+ "ooui-dialog-message-reject": "取消",
+ "ooui-dialog-process-error": "什乇出毛病了",
+ "ooui-dialog-process-dismiss": "關閉",
+ "ooui-dialog-process-retry": "重試",
+ "ooui-dialog-process-continue": "繼續",
+ "ooui-selectfile-button-select": "選擇蜀萆文件",
+ "ooui-selectfile-not-supported": "𣍐支持選擇其文件",
+ "ooui-selectfile-placeholder": "未選文件",
+ "ooui-selectfile-dragdrop-placeholder": "共文件拖遘嚽塊"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ce.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ce.json
new file mode 100644
index 00000000..3f8dfb13
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ce.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Умар"
+ ]
+ },
+ "ooui-outline-control-move-down": "Лаха яккха элемент",
+ "ooui-outline-control-move-up": "Лаккха яккха элемент",
+ "ooui-outline-control-remove": "ДӀадаха меттиг",
+ "ooui-toolbar-more": "Кхин",
+ "ooui-toolgroup-expand": "Дукха",
+ "ooui-toolgroup-collapse": "КӀезиг",
+ "ooui-dialog-message-accept": "ХӀаъ",
+ "ooui-dialog-message-reject": "Цаоьшу",
+ "ooui-dialog-process-continue": "Кхин дӀа",
+ "ooui-selectfile-button-select": "Харжа файл",
+ "ooui-selectfile-placeholder": "Файл хаьржина яц"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ckb.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ckb.json
new file mode 100644
index 00000000..999fae04
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ckb.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Calak",
+ "Muhammed taha",
+ "Serwan",
+ "Pirehelokan",
+ "Sarchia"
+ ]
+ },
+ "ooui-toolbar-more": "زیاتر",
+ "ooui-toolgroup-expand": "زیاتر",
+ "ooui-toolgroup-collapse": "کەمتر",
+ "ooui-dialog-message-accept": "باشە",
+ "ooui-dialog-message-reject": "پاشگەزبوونەوە",
+ "ooui-dialog-process-error": "ھەڵەیەک ڕووی داوە",
+ "ooui-dialog-process-dismiss": "لێگەڕان",
+ "ooui-dialog-process-retry": "دیسان ھەوڵ بدە",
+ "ooui-dialog-process-continue": "درێژە بدە",
+ "ooui-selectfile-button-select": "پەڕگەیەک دەستنیشان بکە",
+ "ooui-selectfile-placeholder": "ھیچ فایلێک ھەڵنەبژێراوە",
+ "ooui-selectfile-dragdrop-placeholder": "پەڕگەکان بخەرە ئێرە"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/co.json b/www/wiki/vendor/oojs/oojs-ui/i18n/co.json
new file mode 100644
index 00000000..01d181d7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/co.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Paulu"
+ ]
+ },
+ "ooui-outline-control-move-down": "Fà falà l'ogettu",
+ "ooui-outline-control-move-up": "Fà cullà l'ogettu"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/crh-cyrl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/crh-cyrl.json
new file mode 100644
index 00000000..ccc00269
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/crh-cyrl.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Don Alessandro"
+ ]
+ },
+ "ooui-toolbar-more": "Даа зияде"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/crh-latn.json b/www/wiki/vendor/oojs/oojs-ui/i18n/crh-latn.json
new file mode 100644
index 00000000..7ad7b0bb
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/crh-latn.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Don Alessandro"
+ ]
+ },
+ "ooui-toolbar-more": "Daa ziyade"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/cs.json b/www/wiki/vendor/oojs/oojs-ui/i18n/cs.json
new file mode 100644
index 00000000..8e3d1af1
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/cs.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chmee2",
+ "Jkjk",
+ "Juandev",
+ "Koo6",
+ "Littledogboy",
+ "Michaelbrabec",
+ "Mormegil",
+ "Polda18",
+ "Tchoř",
+ "ශ්වෙත",
+ "Vojtěch Dostál",
+ "Matěj Suchánek",
+ "Martin Urbanec"
+ ]
+ },
+ "ooui-outline-control-move-down": "Přesunout položku dolů",
+ "ooui-outline-control-move-up": "Přesunout položku nahoru",
+ "ooui-outline-control-remove": "Odstranit položku",
+ "ooui-toolbar-more": "Další",
+ "ooui-toolgroup-expand": "Více",
+ "ooui-toolgroup-collapse": "Méně",
+ "ooui-item-remove": "Odebrat",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Storno",
+ "ooui-dialog-process-error": "Něco se pokazilo",
+ "ooui-dialog-process-dismiss": "Zavřít",
+ "ooui-dialog-process-retry": "Zkusit znovu",
+ "ooui-dialog-process-continue": "Pokračovat",
+ "ooui-selectfile-button-select": "Vybrat soubor",
+ "ooui-selectfile-not-supported": "Výběr souboru není podporován",
+ "ooui-selectfile-placeholder": "Nebyl vybrán žádný soubor",
+ "ooui-selectfile-dragdrop-placeholder": "Umístěte soubor sem"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/cu.json b/www/wiki/vendor/oojs/oojs-ui/i18n/cu.json
new file mode 100644
index 00000000..d627de06
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/cu.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "ОйЛ"
+ ]
+ },
+ "ooui-toolbar-more": "вѧщє",
+ "ooui-toolgroup-expand": "вѧщє",
+ "ooui-dialog-process-error": "нѣчьто ꙁълѣ сѧ авило"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/cy.json b/www/wiki/vendor/oojs/oojs-ui/i18n/cy.json
new file mode 100644
index 00000000..f3c7e3c4
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/cy.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lloffiwr",
+ "Robin Owain",
+ "ОйЛ",
+ "DChan (WMF)",
+ "Jdforrester"
+ ]
+ },
+ "ooui-outline-control-move-down": "Symud yr eitem i lawr",
+ "ooui-outline-control-move-up": "Symud yr eitem i fyny",
+ "ooui-outline-control-remove": "Tynnu'r eitem",
+ "ooui-toolbar-more": "Rhagor",
+ "ooui-toolgroup-expand": "Mwy",
+ "ooui-toolgroup-collapse": "Llai",
+ "ooui-dialog-message-accept": "Iawn",
+ "ooui-dialog-message-reject": "Canslo",
+ "ooui-dialog-process-error": "Aeth rhywbeth o’i le",
+ "ooui-dialog-process-dismiss": "Gadael",
+ "ooui-dialog-process-retry": "Ailgeisio",
+ "ooui-dialog-process-continue": "Parhau",
+ "ooui-selectfile-button-select": "Dewis ffeil",
+ "ooui-selectfile-not-supported": "Nid oes modd dewis ffeil",
+ "ooui-selectfile-placeholder": "Dim ffeil wedi'i dewis",
+ "ooui-selectfile-dragdrop-placeholder": "Gollwng ffeil yma"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/da.json b/www/wiki/vendor/oojs/oojs-ui/i18n/da.json
new file mode 100644
index 00000000..3a5590ae
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/da.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cgtdk",
+ "Christian List",
+ "EileenSanda",
+ "Laketown",
+ "Palnatoke",
+ "Simeondahl",
+ "Tehnix",
+ "Macofe",
+ "Peter Alberti",
+ "Joedalton"
+ ]
+ },
+ "ooui-outline-control-move-down": "Flyt ned",
+ "ooui-outline-control-move-up": "Flyt op",
+ "ooui-toolbar-more": "Mere",
+ "ooui-toolgroup-expand": "Mere",
+ "ooui-toolgroup-collapse": "Færre",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Afbryd",
+ "ooui-dialog-process-error": "Noget gik galt",
+ "ooui-dialog-process-retry": "Prøv igen",
+ "ooui-dialog-process-continue": "Fortsæt",
+ "ooui-selectfile-button-select": "Vælg en fil",
+ "ooui-selectfile-dragdrop-placeholder": "Smid filen her"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/de.json b/www/wiki/vendor/oojs/oojs-ui/i18n/de.json
new file mode 100644
index 00000000..a9eea8aa
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/de.json
@@ -0,0 +1,33 @@
+{
+ "@metadata": {
+ "authors": [
+ "APPER",
+ "G.Hagedorn",
+ "Inkowik",
+ "Jcornelius",
+ "Jdforrester",
+ "Kghbln",
+ "Metalhead64",
+ "Murma174",
+ "Se4598",
+ "Tomabrafix"
+ ]
+ },
+ "ooui-outline-control-move-down": "Element nach unten verschieben",
+ "ooui-outline-control-move-up": "Element nach oben verschieben",
+ "ooui-outline-control-remove": "Element entfernen",
+ "ooui-toolbar-more": "Mehr",
+ "ooui-toolgroup-expand": "Mehr",
+ "ooui-toolgroup-collapse": "Weniger",
+ "ooui-item-remove": "Entfernen",
+ "ooui-dialog-message-accept": "Okay",
+ "ooui-dialog-message-reject": "Abbrechen",
+ "ooui-dialog-process-error": "Etwas ist schief gelaufen",
+ "ooui-dialog-process-dismiss": "Ausblenden",
+ "ooui-dialog-process-retry": "Erneut versuchen",
+ "ooui-dialog-process-continue": "Fortfahren",
+ "ooui-selectfile-button-select": "Eine Datei auswählen",
+ "ooui-selectfile-not-supported": "Die Dateiauswahl wird nicht unterstützt",
+ "ooui-selectfile-placeholder": "Keine Datei ausgewählt",
+ "ooui-selectfile-dragdrop-placeholder": "Dateien hier ablegen"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/diq.json b/www/wiki/vendor/oojs/oojs-ui/i18n/diq.json
new file mode 100644
index 00000000..bf6b0873
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/diq.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Erdemaslancan",
+ "Gorizon",
+ "Kghbln",
+ "Marmase",
+ "Mirzali",
+ "Se4598",
+ "Kumkumuk"
+ ]
+ },
+ "ooui-outline-control-move-down": "Bendi bere cêr",
+ "ooui-outline-control-move-up": "Bendi bere cor",
+ "ooui-outline-control-remove": "Obcey wedare",
+ "ooui-toolbar-more": "Zewbi",
+ "ooui-toolgroup-expand": "Dehana",
+ "ooui-toolgroup-collapse": "Deha tayn",
+ "ooui-dialog-message-accept": "TEMAM",
+ "ooui-dialog-message-reject": "Bıtexelne",
+ "ooui-dialog-process-error": "Tayê çi ğelet şi...",
+ "ooui-dialog-process-dismiss": "Racın",
+ "ooui-dialog-process-retry": "Fına bıcerbın",
+ "ooui-dialog-process-continue": "Dewam ke",
+ "ooui-selectfile-button-select": "Yu dosya weçinê",
+ "ooui-selectfile-not-supported": "Dosya weçinayış desteg nêvine na",
+ "ooui-selectfile-placeholder": "Dosya nêwçineya",
+ "ooui-selectfile-dragdrop-placeholder": "Dosya tiyara ake"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/dsb.json b/www/wiki/vendor/oojs/oojs-ui/i18n/dsb.json
new file mode 100644
index 00000000..7ad3f200
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/dsb.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Michawiki"
+ ]
+ },
+ "ooui-outline-control-move-down": "Element dołoj pśesunuś",
+ "ooui-outline-control-move-up": "Element górjej pśesunuś",
+ "ooui-outline-control-remove": "Zapisk wótpóraś",
+ "ooui-toolbar-more": "Wěcej"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/dty.json b/www/wiki/vendor/oojs/oojs-ui/i18n/dty.json
new file mode 100644
index 00000000..21742b69
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/dty.json
@@ -0,0 +1,18 @@
+{
+ "@metadata": {
+ "authors": [
+ "जनक राज भट्ट"
+ ]
+ },
+ "ooui-outline-control-move-down": "वस्तुलाई तल साददे",
+ "ooui-outline-control-move-up": "वस्तुलाई मथि साददे",
+ "ooui-outline-control-remove": "वस्तुलाई हटुन्या",
+ "ooui-toolbar-more": "झिक्क",
+ "ooui-toolgroup-expand": "झिक्क",
+ "ooui-toolgroup-collapse": "थोका",
+ "ooui-dialog-message-accept": "हुन्छ",
+ "ooui-dialog-message-reject": "रद्द",
+ "ooui-dialog-process-dismiss": "खारेज गद्दे",
+ "ooui-dialog-process-retry": "दोसरया प्रयास गर",
+ "ooui-dialog-process-continue": "जारी राख्या"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/egl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/egl.json
new file mode 100644
index 00000000..624ecaa3
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/egl.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lévi",
+ "Gloria sah"
+ ]
+ },
+ "ooui-outline-control-move-down": "Spôsta in bâs",
+ "ooui-outline-control-move-up": "Spôsta in êlt",
+ "ooui-outline-control-remove": "Armōv l'elemèint",
+ "ooui-toolbar-more": "Êter",
+ "ooui-dialog-message-accept": "'D acòrdi",
+ "ooui-dialog-message-reject": "Scanślèr"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/el.json b/www/wiki/vendor/oojs/oojs-ui/i18n/el.json
new file mode 100644
index 00000000..55d1e8bb
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/el.json
@@ -0,0 +1,33 @@
+{
+ "@metadata": {
+ "authors": [
+ "Astralnet",
+ "Dipa1965",
+ "Evropi",
+ "FocalPoint",
+ "Geraki",
+ "Glavkos",
+ "Nikosguard",
+ "Tifa93",
+ "Stam.nikos",
+ "Nikosgranturismogt"
+ ]
+ },
+ "ooui-outline-control-move-down": "Μετακίνηση στοιχείου προς τα κάτω",
+ "ooui-outline-control-move-up": "Μετακίνηση στοιχείου προς τα επάνω",
+ "ooui-outline-control-remove": "Αφαίρεση στοιχείου",
+ "ooui-toolbar-more": "Περισσότερα",
+ "ooui-toolgroup-expand": "Περισσότερα",
+ "ooui-toolgroup-collapse": "Λιγότερα",
+ "ooui-item-remove": "Αφαίρεση",
+ "ooui-dialog-message-accept": "ΟΚ",
+ "ooui-dialog-message-reject": "Ακύρωση",
+ "ooui-dialog-process-error": "Κάτι πήγε στραβά",
+ "ooui-dialog-process-dismiss": "Απόρριψη",
+ "ooui-dialog-process-retry": "Δοκιμάστε ξανά",
+ "ooui-dialog-process-continue": "Συνέχεια",
+ "ooui-selectfile-button-select": "Επιλέξτε ένα αρχείο",
+ "ooui-selectfile-not-supported": "Επιλογή αρχείου δεν υποστηρίζεται",
+ "ooui-selectfile-placeholder": "Κανένα αρχείο δεν είναι επιλεγμένο",
+ "ooui-selectfile-dragdrop-placeholder": "Σύρετε το αρχείο εδώ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/eml.json b/www/wiki/vendor/oojs/oojs-ui/i18n/eml.json
new file mode 100644
index 00000000..6d9e8bf0
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/eml.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gloria sah",
+ "Lévi"
+ ]
+ },
+ "ooui-outline-control-move-down": "Spôsta in bâs",
+ "ooui-outline-control-move-up": "Spôsta in êlta",
+ "ooui-outline-control-remove": "Tór vìa 'l elemèint",
+ "ooui-toolbar-more": "Êter",
+ "ooui-dialog-message-accept": "'D acòrdi",
+ "ooui-dialog-message-reject": "Scanślèr"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/en-ca.json b/www/wiki/vendor/oojs/oojs-ui/i18n/en-ca.json
new file mode 100644
index 00000000..1a8e31be
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/en-ca.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Skyllful"
+ ]
+ },
+ "ooui-outline-control-move-down": "Move item down",
+ "ooui-outline-control-move-up": "Move item up",
+ "ooui-outline-control-remove": "Remove item",
+ "ooui-toolbar-more": "More",
+ "ooui-toolgroup-expand": "More",
+ "ooui-toolgroup-collapse": "Less",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancel",
+ "ooui-dialog-process-error": "Something went wrong",
+ "ooui-dialog-process-dismiss": "Dismiss",
+ "ooui-dialog-process-retry": "Try again",
+ "ooui-dialog-process-continue": "Continue",
+ "ooui-selectfile-not-supported": "File(s) not supported",
+ "ooui-selectfile-placeholder": "No file selected",
+ "ooui-selectfile-dragdrop-placeholder": "Drop file here (or click to browse your computer)"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/en-gb.json b/www/wiki/vendor/oojs/oojs-ui/i18n/en-gb.json
new file mode 100644
index 00000000..5bdc6f47
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/en-gb.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Pierpao"
+ ]
+ },
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancel",
+ "ooui-dialog-process-dismiss": "Dismiss",
+ "ooui-dialog-process-retry": "Try again",
+ "ooui-dialog-process-continue": "Continue",
+ "ooui-selectfile-button-select": "Select a file",
+ "ooui-selectfile-not-supported": "File selection is not supported",
+ "ooui-selectfile-placeholder": "No file is selected"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/en.json b/www/wiki/vendor/oojs/oojs-ui/i18n/en.json
new file mode 100644
index 00000000..fd311503
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/en.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Trevor Parscal",
+ "Ed Sanders",
+ "James D. Forrester",
+ "Raimond Spekking",
+ "Erik Moeller",
+ "Moriel Schottlender",
+ "Yuki Shira",
+ "Siebrand Mazeland",
+ "Rob Moen",
+ "Timo Tijhof",
+ "Roan Kattouw",
+ "Christian Williams",
+ "Amir E. Aharoni"
+ ]
+ },
+ "ooui-outline-control-move-down": "Move item down",
+ "ooui-outline-control-move-up": "Move item up",
+ "ooui-outline-control-remove": "Remove item",
+ "ooui-toolbar-more": "More",
+ "ooui-toolgroup-expand": "More",
+ "ooui-toolgroup-collapse": "Fewer",
+ "ooui-item-remove": "Remove",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancel",
+ "ooui-dialog-process-error": "Something went wrong",
+ "ooui-dialog-process-dismiss": "Dismiss",
+ "ooui-dialog-process-retry": "Try again",
+ "ooui-dialog-process-continue": "Continue",
+ "ooui-selectfile-button-select": "Select a file",
+ "ooui-selectfile-not-supported": "File selection is not supported",
+ "ooui-selectfile-placeholder": "No file is selected",
+ "ooui-selectfile-dragdrop-placeholder": "Drop file here"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/eo.json b/www/wiki/vendor/oojs/oojs-ui/i18n/eo.json
new file mode 100644
index 00000000..ff2a2b31
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/eo.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Happy5214",
+ "KuboF",
+ "Shirayuki",
+ "Yekrats",
+ "Kvardek du",
+ "Psychoslave"
+ ]
+ },
+ "ooui-outline-control-move-down": "Movi eron suben",
+ "ooui-outline-control-move-up": "Movi eron supren",
+ "ooui-outline-control-remove": "Forigi eron",
+ "ooui-toolbar-more": "Pli",
+ "ooui-toolgroup-expand": "Pli",
+ "ooui-toolgroup-collapse": "Mapli",
+ "ooui-dialog-message-accept": "Bone",
+ "ooui-dialog-message-reject": "Nuligi",
+ "ooui-dialog-process-error": "Io rompiĝis",
+ "ooui-dialog-process-dismiss": "Elimini",
+ "ooui-dialog-process-retry": "Reprovi",
+ "ooui-dialog-process-continue": "Daŭrigi",
+ "ooui-selectfile-button-select": "Elekti dosieron",
+ "ooui-selectfile-not-supported": "Dosieroselekto ne estas subtenata.",
+ "ooui-selectfile-placeholder": "Vi ne selektis dosieron",
+ "ooui-selectfile-dragdrop-placeholder": "Ĵetu dosieron ĉi tie."
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/es.json b/www/wiki/vendor/oojs/oojs-ui/i18n/es.json
new file mode 100644
index 00000000..7873c95c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/es.json
@@ -0,0 +1,38 @@
+{
+ "@metadata": {
+ "authors": [
+ "Armando-Martin",
+ "Aruizdr",
+ "Benfutbol10",
+ "DJ Nietzsche",
+ "Erdemaslancan",
+ "Fitoschido",
+ "Imre",
+ "Invadinado",
+ "Jdforrester",
+ "Jduranboger",
+ "PoLuX124",
+ "Ralgis",
+ "Thehelpfulone",
+ "Gloria sah",
+ "Macofe"
+ ]
+ },
+ "ooui-outline-control-move-down": "Bajar elemento",
+ "ooui-outline-control-move-up": "Subir elemento",
+ "ooui-outline-control-remove": "Eliminar elemento",
+ "ooui-toolbar-more": "Más",
+ "ooui-toolgroup-expand": "Más",
+ "ooui-toolgroup-collapse": "Menos",
+ "ooui-item-remove": "Quitar",
+ "ooui-dialog-message-accept": "Aceptar",
+ "ooui-dialog-message-reject": "Cancelar",
+ "ooui-dialog-process-error": "Algo salió mal",
+ "ooui-dialog-process-dismiss": "Descartar",
+ "ooui-dialog-process-retry": "Intentar de nuevo",
+ "ooui-dialog-process-continue": "Continuar",
+ "ooui-selectfile-button-select": "Selecciona un archivo",
+ "ooui-selectfile-not-supported": "No se admite la selección de archivos",
+ "ooui-selectfile-placeholder": "Ningún archivo seleccionado",
+ "ooui-selectfile-dragdrop-placeholder": "Suelta el archivo aquí"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/et.json b/www/wiki/vendor/oojs/oojs-ui/i18n/et.json
new file mode 100644
index 00000000..326baaff
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/et.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Avjoska",
+ "Pikne",
+ "Suwa"
+ ]
+ },
+ "ooui-outline-control-move-down": "Liiguta üksust allapoole",
+ "ooui-outline-control-move-up": "Liiguta üksust ülespoole",
+ "ooui-outline-control-remove": "Eemalda üksus",
+ "ooui-toolbar-more": "Veel",
+ "ooui-toolgroup-expand": "Veel",
+ "ooui-toolgroup-collapse": "Vähem",
+ "ooui-dialog-message-accept": "Sobib",
+ "ooui-dialog-message-reject": "Loobu",
+ "ooui-dialog-process-error": "Midagi läks valesti",
+ "ooui-dialog-process-dismiss": "Sule",
+ "ooui-dialog-process-retry": "Proovi uuesti",
+ "ooui-dialog-process-continue": "Jätka",
+ "ooui-selectfile-button-select": "Vali fail",
+ "ooui-selectfile-not-supported": "Faili valiku tugi puudub",
+ "ooui-selectfile-placeholder": "Faili ei ole valitud",
+ "ooui-selectfile-dragdrop-placeholder": "Lohista fail siia"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/eu.json b/www/wiki/vendor/oojs/oojs-ui/i18n/eu.json
new file mode 100644
index 00000000..c715ae6f
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/eu.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "An13sa",
+ "Unai Fdz. de Betoño",
+ "Xabier Armendaritz",
+ "Subi",
+ "Sator",
+ "Mikel Ibaiba"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mugitu itema beherantz",
+ "ooui-outline-control-move-up": "Mugitu itema gorantz",
+ "ooui-outline-control-remove": "Elementua kendu",
+ "ooui-toolbar-more": "Gehiago",
+ "ooui-toolgroup-expand": "Gehiago",
+ "ooui-toolgroup-collapse": "Gutxiago",
+ "ooui-item-remove": "Ezabatu",
+ "ooui-dialog-message-accept": "Ados",
+ "ooui-dialog-message-reject": "Utzi",
+ "ooui-dialog-process-error": "Zerbaitek huts egin du",
+ "ooui-dialog-process-dismiss": "Utzi",
+ "ooui-dialog-process-retry": "Saiatu berriro",
+ "ooui-dialog-process-continue": "Jarraitu",
+ "ooui-selectfile-button-select": "Fitxategi bat aukeratu",
+ "ooui-selectfile-not-supported": "Fitxategi aukeraketa ez da onartzen",
+ "ooui-selectfile-placeholder": "Ez da fitxategirik hautatu",
+ "ooui-selectfile-dragdrop-placeholder": "Fitxategia hemen utzi"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/fa.json b/www/wiki/vendor/oojs/oojs-ui/i18n/fa.json
new file mode 100644
index 00000000..8aa519b1
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/fa.json
@@ -0,0 +1,37 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dalba",
+ "Ebraminio",
+ "Jdforrester",
+ "Ladsgroup",
+ "Mjbmr",
+ "Nojan Madinehi",
+ "Reza1615",
+ "Taha",
+ "درفش کاویانی",
+ "Armin1392",
+ "Alirezaaa",
+ "Leyth",
+ "الناز",
+ "فلورانس"
+ ]
+ },
+ "ooui-outline-control-move-down": "انتقال مورد به پایین",
+ "ooui-outline-control-move-up": "انتقال مورد به بالا",
+ "ooui-outline-control-remove": "حذف مورد",
+ "ooui-toolbar-more": "بیشتر",
+ "ooui-toolgroup-expand": "بیشتر",
+ "ooui-toolgroup-collapse": "کمتر",
+ "ooui-item-remove": "حذف",
+ "ooui-dialog-message-accept": "تأیید",
+ "ooui-dialog-message-reject": "لغو",
+ "ooui-dialog-process-error": "مشکلی وجود دارد",
+ "ooui-dialog-process-dismiss": "رد",
+ "ooui-dialog-process-retry": "دوباره امتحان کنید",
+ "ooui-dialog-process-continue": "ادامه",
+ "ooui-selectfile-button-select": "یک فایل انتخاب کنید",
+ "ooui-selectfile-not-supported": "انتخاب پرونده پشتیبانی نمی‌شود",
+ "ooui-selectfile-placeholder": "هیچ پرونده‌ای انتخاب نشده است",
+ "ooui-selectfile-dragdrop-placeholder": "فایل را اینجا رها کنید"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/fi.json b/www/wiki/vendor/oojs/oojs-ui/i18n/fi.json
new file mode 100644
index 00000000..4f46aef1
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/fi.json
@@ -0,0 +1,37 @@
+{
+ "@metadata": {
+ "authors": [
+ "Beluga",
+ "Crt",
+ "Harriv",
+ "Linnea",
+ "Nedergard",
+ "Nike",
+ "Olli",
+ "Pxos",
+ "Samoasambia",
+ "Silvonen",
+ "Skalman",
+ "Stryn",
+ "VezonThunder",
+ "Alluk."
+ ]
+ },
+ "ooui-outline-control-move-down": "Siirrä kohdetta alaspäin",
+ "ooui-outline-control-move-up": "Siirrä kohdetta ylöspäin",
+ "ooui-outline-control-remove": "Poista kohde",
+ "ooui-toolbar-more": "Lisää",
+ "ooui-toolgroup-expand": "Näytä lisää",
+ "ooui-toolgroup-collapse": "Näytä vähemmän",
+ "ooui-item-remove": "Poista",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Peru",
+ "ooui-dialog-process-error": "Jokin meni pieleen",
+ "ooui-dialog-process-dismiss": "Hylkää",
+ "ooui-dialog-process-retry": "Yritä uudelleen",
+ "ooui-dialog-process-continue": "Jatka",
+ "ooui-selectfile-button-select": "Valitse tiedosto",
+ "ooui-selectfile-not-supported": "Tiedoston valitsemista ei tueta",
+ "ooui-selectfile-placeholder": "Tiedostoa ei ole valittu",
+ "ooui-selectfile-dragdrop-placeholder": "Pudota tiedosto tähän"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/fo.json b/www/wiki/vendor/oojs/oojs-ui/i18n/fo.json
new file mode 100644
index 00000000..6230cc9b
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/fo.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "EileenSanda"
+ ]
+ },
+ "ooui-outline-control-move-down": "Flyt lutin niður",
+ "ooui-outline-control-move-up": "Flyt lutin upp",
+ "ooui-outline-control-remove": "Tak ein lut burtur",
+ "ooui-toolbar-more": "Meira",
+ "ooui-toolgroup-expand": "Meira",
+ "ooui-toolgroup-collapse": "Færri",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Avbrót",
+ "ooui-dialog-process-error": "Okkurt gekk galið",
+ "ooui-dialog-process-dismiss": "Lat aftur",
+ "ooui-dialog-process-retry": "Royn aftur",
+ "ooui-dialog-process-continue": "Halt fram"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/fr.json b/www/wiki/vendor/oojs/oojs-ui/i18n/fr.json
new file mode 100644
index 00000000..1c004d45
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/fr.json
@@ -0,0 +1,53 @@
+{
+ "@metadata": {
+ "authors": [
+ "Automatik",
+ "Benoit Rochon",
+ "Boniface",
+ "Brunoperel",
+ "Crochet.david",
+ "DavidL",
+ "Dereckson",
+ "Gomoko",
+ "Guillom",
+ "Hello71",
+ "Jean-Frédéric",
+ "Linedwell",
+ "Ltrlg",
+ "Metroitendo",
+ "NemesisIII",
+ "Nicolas NALLET",
+ "Npettiaux",
+ "Rastus Vernon",
+ "Seb35",
+ "Sherbrooke",
+ "Tpt",
+ "Trizek",
+ "Urhixidur",
+ "Verdy p",
+ "Wyz",
+ "SnowedEarth",
+ "Jdforrester",
+ "Wladek92",
+ "Harmonia Amanda",
+ "The RedBurn"
+ ]
+ },
+ "ooui-outline-control-move-down": "Descendre l’élément",
+ "ooui-outline-control-move-up": "Monter l’élément",
+ "ooui-outline-control-remove": "Supprimer l’élément",
+ "ooui-toolbar-more": "Plus",
+ "ooui-toolgroup-expand": "Plus",
+ "ooui-toolgroup-collapse": "Moins",
+ "ooui-item-remove": "Supprimer",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Annuler",
+ "ooui-dialog-process-error": "Quelque chose s'est mal passé",
+ "ooui-dialog-process-dismiss": "Fermer",
+ "ooui-dialog-process-retry": "Réessayer",
+ "ooui-dialog-process-continue": "Continuer",
+ "ooui-selectfile-button-select": "Sélectionner un fichier",
+ "ooui-selectfile-not-supported": "La sélection de fichier n’est pas prise en charge",
+ "ooui-selectfile-placeholder": "Aucun fichier sélectionné",
+ "ooui-selectfile-dragdrop-placeholder": "Déposer le fichier ici"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/frr.json b/www/wiki/vendor/oojs/oojs-ui/i18n/frr.json
new file mode 100644
index 00000000..54d0fb22
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/frr.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "ChrisPtDe",
+ "Murma174"
+ ]
+ },
+ "ooui-outline-control-move-down": "Element efter onern sküüw",
+ "ooui-outline-control-move-up": "Element efter boowen sküüw",
+ "ooui-outline-control-remove": "Element wechnem",
+ "ooui-toolbar-more": "Muar"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/fur.json b/www/wiki/vendor/oojs/oojs-ui/i18n/fur.json
new file mode 100644
index 00000000..83c2fd9e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/fur.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Klenje",
+ "Tocaibon"
+ ]
+ },
+ "ooui-outline-control-move-down": "sposte sot",
+ "ooui-outline-control-move-up": "sposte in su",
+ "ooui-toolbar-more": "Altri"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/fy.json b/www/wiki/vendor/oojs/oojs-ui/i18n/fy.json
new file mode 100644
index 00000000..ddf9ff75
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/fy.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Robin0van0der0vliet"
+ ]
+ },
+ "ooui-toolbar-more": "Mear",
+ "ooui-toolgroup-expand": "Mear",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Annulearje"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/gd.json b/www/wiki/vendor/oojs/oojs-ui/i18n/gd.json
new file mode 100644
index 00000000..6a83c9c0
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/gd.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "GunChleoc"
+ ]
+ },
+ "ooui-outline-control-move-down": "Gluais nì sìos",
+ "ooui-outline-control-move-up": "Gluais nì suas",
+ "ooui-outline-control-remove": "Thoir air falbh an nì",
+ "ooui-toolbar-more": "Barrachd",
+ "ooui-dialog-message-accept": "Ceart ma-thà",
+ "ooui-dialog-message-reject": "Sguir dheth"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/gl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/gl.json
new file mode 100644
index 00000000..2c3cce31
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/gl.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Alison",
+ "Kscanne",
+ "Toliño",
+ "Elisardojm",
+ "Banjo"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mover o elemento abaixo",
+ "ooui-outline-control-move-up": "Mover o elemento arriba",
+ "ooui-outline-control-remove": "Eliminar o elemento",
+ "ooui-toolbar-more": "Máis",
+ "ooui-toolgroup-expand": "Máis",
+ "ooui-toolgroup-collapse": "Menos",
+ "ooui-item-remove": "Eliminar",
+ "ooui-dialog-message-accept": "Aceptar",
+ "ooui-dialog-message-reject": "Cancelar",
+ "ooui-dialog-process-error": "Algo foi mal",
+ "ooui-dialog-process-dismiss": "Agochar",
+ "ooui-dialog-process-retry": "Inténteo de novo",
+ "ooui-dialog-process-continue": "Continuar",
+ "ooui-selectfile-button-select": "Seleccionar un ficheiro",
+ "ooui-selectfile-not-supported": "Non está soportada a selección de ficheiros",
+ "ooui-selectfile-placeholder": "Non se seleccionou ningún ficheiro",
+ "ooui-selectfile-dragdrop-placeholder": "Solte un ficheiro aquí"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/glk.json b/www/wiki/vendor/oojs/oojs-ui/i18n/glk.json
new file mode 100644
index 00000000..e6020621
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/glk.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "V6rg",
+ "شیخ"
+ ]
+ },
+ "ooui-outline-control-move-down": "مأسمکه جابجا بۊکۊن جير",
+ "ooui-outline-control-move-up": "مأسمکه جابجا بۊکۊن جؤر",
+ "ooui-outline-control-remove": "مأسمکه حذفأکۊن",
+ "ooui-toolbar-more": "ويشتر",
+ "ooui-toolgroup-expand": "ويشتر",
+ "ooui-toolgroup-collapse": "کمتر",
+ "ooui-dialog-message-accept": "خؤ",
+ "ooui-dialog-message-reject": "لغو",
+ "ooui-dialog-process-error": "ىک مؤشکلي هنأ",
+ "ooui-dialog-process-dismiss": "وأبدي",
+ "ooui-dialog-process-retry": "هندئه حقسأى بۊکۊنين",
+ "ooui-dialog-process-continue": "ايدامه",
+ "ooui-selectfile-button-select": "ىکته فاىله دؤجين بۊکۊنين",
+ "ooui-selectfile-not-supported": "نشأنه فاىله دؤجين گۊدن",
+ "ooui-selectfile-placeholder": "هيچ فاىلي دؤجين نۊبؤ",
+ "ooui-selectfile-dragdrop-placeholder": "فاىله ائره رها بکۊنين"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/gom-latn.json b/www/wiki/vendor/oojs/oojs-ui/i18n/gom-latn.json
new file mode 100644
index 00000000..afd47100
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/gom-latn.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "The Discoverer"
+ ]
+ },
+ "ooui-toolbar-more": "Anik",
+ "ooui-toolgroup-expand": "Anik",
+ "ooui-dialog-message-reject": "Rodd'dd kor",
+ "ooui-dialog-process-retry": "Porot proyotn kor",
+ "ooui-selectfile-button-select": "Ek fayl nivodd",
+ "ooui-selectfile-placeholder": "Khuimchech fayl nivddunk nam",
+ "ooui-selectfile-dragdrop-placeholder": "Fayl hanga udoi"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/gor.json b/www/wiki/vendor/oojs/oojs-ui/i18n/gor.json
new file mode 100644
index 00000000..ca0f1b42
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/gor.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Marwan Mohamad"
+ ]
+ },
+ "ooui-outline-control-move-down": "Heyiya botu ode tibawa",
+ "ooui-outline-control-move-up": "Heyiya botu ode yitaato",
+ "ooui-outline-control-remove": "Yinggila botu",
+ "ooui-toolbar-more": "Pe'eentapo",
+ "ooui-toolgroup-expand": "Pe'eentapo",
+ "ooui-toolgroup-collapse": "ngoolo botu",
+ "ooui-dialog-message-accept": "Jo",
+ "ooui-dialog-message-reject": "Bataliya",
+ "ooui-dialog-process-error": "Woluwo u yilotalawa",
+ "ooui-dialog-process-dismiss": "He'uti",
+ "ooui-dialog-process-retry": "Yimontali pooli",
+ "ooui-dialog-process-continue": "Turusi",
+ "ooui-selectfile-button-select": "Tulawota berkas tuwawu",
+ "ooui-selectfile-not-supported": "Berkas tilulawoto ja motuhatawa",
+ "ooui-selectfile-placeholder": "Diya'a berkas u letulawoto",
+ "ooui-selectfile-dragdrop-placeholder": "Dutuwa berkas teeya"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/gu.json b/www/wiki/vendor/oojs/oojs-ui/i18n/gu.json
new file mode 100644
index 00000000..e7dfeb20
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/gu.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ashok modhvadia",
+ "KartikMistry",
+ "The Discoverer",
+ "NehalDaveND",
+ "Dsvyas"
+ ]
+ },
+ "ooui-outline-control-move-down": "વસ્તુ નીચે ખસેડો",
+ "ooui-outline-control-move-up": "વસ્તુ ઉપર ખસેડો",
+ "ooui-outline-control-remove": "વસ્તુ હટાવો",
+ "ooui-toolbar-more": "વધુ",
+ "ooui-toolgroup-expand": "વધુ",
+ "ooui-toolgroup-collapse": "ઓછા",
+ "ooui-dialog-message-accept": "બરાબર",
+ "ooui-dialog-message-reject": "રદ કરો",
+ "ooui-dialog-process-error": "કંઇક ગરબડ થઇ",
+ "ooui-dialog-process-dismiss": "વિસર્જન",
+ "ooui-dialog-process-retry": "ફરી પ્રયત્ન કરો",
+ "ooui-dialog-process-continue": "ચાલુ રાખો",
+ "ooui-selectfile-button-select": "ફાઈલ પસંદ કરો",
+ "ooui-selectfile-not-supported": "ફાઇલ પસંદગીની જોગવાઈ નથી",
+ "ooui-selectfile-placeholder": "કોઇ ફાઇલ પસંદ નથી કરાઈ",
+ "ooui-selectfile-dragdrop-placeholder": "અહીં ફાઇલ મૂકો"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/he.json b/www/wiki/vendor/oojs/oojs-ui/i18n/he.json
new file mode 100644
index 00000000..0864ed9c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/he.json
@@ -0,0 +1,35 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "ExampleTomer",
+ "Guycn2",
+ "Matanya",
+ "Mooeypoo",
+ "Orsa",
+ "Shimmin Beg",
+ "אור שפירא",
+ "חיים",
+ "ערן",
+ "פוילישער",
+ "קיפודנחש"
+ ]
+ },
+ "ooui-outline-control-move-down": "להזיז את הפריט מטה",
+ "ooui-outline-control-move-up": "להזיז את הפריט מעלה",
+ "ooui-outline-control-remove": "להסיר את הפריט",
+ "ooui-toolbar-more": "עוד",
+ "ooui-toolgroup-expand": "יותר",
+ "ooui-toolgroup-collapse": "פחות",
+ "ooui-item-remove": "הסרה",
+ "ooui-dialog-message-accept": "אישור",
+ "ooui-dialog-message-reject": "ביטול",
+ "ooui-dialog-process-error": "משהו השתבש",
+ "ooui-dialog-process-dismiss": "לוותר",
+ "ooui-dialog-process-retry": "לנסות שוב",
+ "ooui-dialog-process-continue": "המשך",
+ "ooui-selectfile-button-select": "נא לבחור קובץ",
+ "ooui-selectfile-not-supported": "בחירת קבצים אינה נתמכת",
+ "ooui-selectfile-placeholder": "לא נבחר שום קובץ",
+ "ooui-selectfile-dragdrop-placeholder": "נא לשחרר את הקובץ כאן"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/hi.json b/www/wiki/vendor/oojs/oojs-ui/i18n/hi.json
new file mode 100644
index 00000000..2bb5559d
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/hi.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ansumang",
+ "Devayon",
+ "Rajesh",
+ "Siddhartha Ghai",
+ "Goelujjwal",
+ "Ankita-ks",
+ "Param Mudgal",
+ "Sfic",
+ "Rishi.Singh"
+ ]
+ },
+ "ooui-outline-control-move-down": "प्रविष्टि नीचे ले जाएँ",
+ "ooui-outline-control-move-up": "प्रविष्टि ऊपर ले जाएँ",
+ "ooui-outline-control-remove": "आइटम हटाएँ",
+ "ooui-toolbar-more": "अधिक",
+ "ooui-toolgroup-expand": "अधिक",
+ "ooui-toolgroup-collapse": "कम",
+ "ooui-item-remove": "हटायें",
+ "ooui-dialog-message-accept": "ठीक है",
+ "ooui-dialog-message-reject": "रद्द करें",
+ "ooui-dialog-process-error": "कुछ गलत हुअा है",
+ "ooui-dialog-process-dismiss": "ख़ारिज करें",
+ "ooui-dialog-process-retry": "पुनः प्रयास करें",
+ "ooui-dialog-process-continue": "जारी रखें",
+ "ooui-selectfile-button-select": "फ़ाइल चुनें",
+ "ooui-selectfile-not-supported": "फ़ाइल का चयन समर्थित नहीं है",
+ "ooui-selectfile-placeholder": "कोई फाइल चुनी नही गई हेै",
+ "ooui-selectfile-dragdrop-placeholder": "फ़ाइल यहाँ डालें"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/hif-latn.json b/www/wiki/vendor/oojs/oojs-ui/i18n/hif-latn.json
new file mode 100644
index 00000000..9e903ca5
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/hif-latn.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Thakurji"
+ ]
+ },
+ "ooui-outline-control-move-down": "Item ke niche karo",
+ "ooui-outline-control-move-up": "Item ke uppar karo",
+ "ooui-outline-control-remove": "Item ke hatao",
+ "ooui-toolbar-more": "Aur",
+ "ooui-toolgroup-expand": "Aur",
+ "ooui-toolgroup-collapse": "Kamtii",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancel karo",
+ "ooui-dialog-process-error": "Koi chij wrong hoe gais",
+ "ooui-dialog-process-dismiss": "Dismiss karo",
+ "ooui-dialog-process-retry": "Fir se try karo",
+ "ooui-dialog-process-continue": "Continue",
+ "ooui-selectfile-button-select": "Ek file ke select karo",
+ "ooui-selectfile-not-supported": "File selection ke support nai karaa jaawe hai",
+ "ooui-selectfile-placeholder": "Koi file ke nai select karaa gais hai",
+ "ooui-selectfile-dragdrop-placeholder": "Hian pe file ke girao"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/hr.json b/www/wiki/vendor/oojs/oojs-ui/i18n/hr.json
new file mode 100644
index 00000000..4eae569c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/hr.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "MaGa",
+ "Roberta F.",
+ "SpeedyGonsales",
+ "Zeljko.filipin",
+ "Bugoslav"
+ ]
+ },
+ "ooui-outline-control-move-down": "Premjesti stavku dolje",
+ "ooui-outline-control-move-up": "Premjesti stavku gore",
+ "ooui-outline-control-remove": "Ukloni",
+ "ooui-toolbar-more": "Više",
+ "ooui-toolgroup-expand": "Više",
+ "ooui-toolgroup-collapse": "Manje",
+ "ooui-item-remove": "Ukloni",
+ "ooui-dialog-message-accept": "U redu",
+ "ooui-dialog-message-reject": "Odustani",
+ "ooui-dialog-process-error": "Nešto nije u redu",
+ "ooui-dialog-process-dismiss": "Zatvori",
+ "ooui-dialog-process-retry": "Pokušajte ponovo",
+ "ooui-dialog-process-continue": "Nastavi",
+ "ooui-selectfile-button-select": "Odaberi datoteku",
+ "ooui-selectfile-not-supported": "Izbor datoteke nije podržan",
+ "ooui-selectfile-placeholder": "Datoteka nije označena",
+ "ooui-selectfile-dragdrop-placeholder": "Povucite datoteku ovdje"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/hrx.json b/www/wiki/vendor/oojs/oojs-ui/i18n/hrx.json
new file mode 100644
index 00000000..1534af76
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/hrx.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Midnight Gambler"
+ ]
+ },
+ "ooui-toolbar-more": "Meahr",
+ "ooui-toolgroup-expand": "Meahr",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Abbreche",
+ "ooui-dialog-process-dismiss": "Ausblenne"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/hsb.json b/www/wiki/vendor/oojs/oojs-ui/i18n/hsb.json
new file mode 100644
index 00000000..00894e4e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/hsb.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "J budissin",
+ "Michawiki"
+ ]
+ },
+ "ooui-outline-control-move-down": "Zapisk dele přesunyć",
+ "ooui-outline-control-move-up": "Zapisk horje přesunyć",
+ "ooui-outline-control-remove": "Zapisk wotstronić",
+ "ooui-toolbar-more": "Wjace",
+ "ooui-toolgroup-expand": "Wjace",
+ "ooui-toolgroup-collapse": "Mjenje",
+ "ooui-dialog-message-accept": "W porjadku",
+ "ooui-dialog-message-reject": "Přetorhnyć",
+ "ooui-dialog-process-error": "Něšto je so nimokuliło",
+ "ooui-dialog-process-dismiss": "Schować",
+ "ooui-dialog-process-retry": "Hišće raz spytać",
+ "ooui-dialog-process-continue": "Dale"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/hu-formal.json b/www/wiki/vendor/oojs/oojs-ui/i18n/hu-formal.json
new file mode 100644
index 00000000..34aa0ae6
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/hu-formal.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Misibacsi"
+ ]
+ },
+ "ooui-outline-control-move-down": "Elem mozgatása lefelé",
+ "ooui-outline-control-move-up": "Elem mozgatása felfelé",
+ "ooui-outline-control-remove": "Elem eltávolítása",
+ "ooui-toolbar-more": "Tovább...",
+ "ooui-toolgroup-expand": "Tovább",
+ "ooui-toolgroup-collapse": "Kevesebb",
+ "ooui-dialog-message-accept": "Rendben",
+ "ooui-dialog-message-reject": "Mégse",
+ "ooui-dialog-process-error": "Valami elromlott.",
+ "ooui-dialog-process-dismiss": "Mégse",
+ "ooui-dialog-process-retry": "Próbálja újra",
+ "ooui-dialog-process-continue": "Folytatás",
+ "ooui-selectfile-not-supported": "A fájl kiválasztása nincs támogatva",
+ "ooui-selectfile-placeholder": "Nincs fájl kiválasztva"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/hu.json b/www/wiki/vendor/oojs/oojs-ui/i18n/hu.json
new file mode 100644
index 00000000..fc96cc45
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/hu.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dj",
+ "Einstein2",
+ "Misibacsi",
+ "ViDam",
+ "Tacsipacsi",
+ "Csega",
+ "Kishajnalka",
+ "Rodrigo"
+ ]
+ },
+ "ooui-outline-control-move-down": "Elem mozgatása lefelé",
+ "ooui-outline-control-move-up": "Elem mozgatása felfelé",
+ "ooui-outline-control-remove": "Elem eltávolítása",
+ "ooui-toolbar-more": "Több",
+ "ooui-toolgroup-expand": "Több",
+ "ooui-toolgroup-collapse": "Kevesebb",
+ "ooui-item-remove": "Eltávolítás",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Mégse",
+ "ooui-dialog-process-error": "Valami elromlott",
+ "ooui-dialog-process-dismiss": "Elrejt",
+ "ooui-dialog-process-retry": "Próbáld újra",
+ "ooui-dialog-process-continue": "Folytatás",
+ "ooui-selectfile-button-select": "Fájl kiválasztása",
+ "ooui-selectfile-not-supported": "A fájl kiválasztása nincs támogatva",
+ "ooui-selectfile-placeholder": "Nincs fájl kiválasztva",
+ "ooui-selectfile-dragdrop-placeholder": "Dobd ide a fájlt"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/hy.json b/www/wiki/vendor/oojs/oojs-ui/i18n/hy.json
new file mode 100644
index 00000000..598fee35
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/hy.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Vacio",
+ "Xelgen",
+ "Դավիթ Սարոյան",
+ "Vahe Gharakhanyan",
+ "Kareyac"
+ ]
+ },
+ "ooui-outline-control-move-down": "Իջեցնել ներքև",
+ "ooui-outline-control-move-up": "Բարձրացնել կետը",
+ "ooui-outline-control-remove": "Հեռացնել տարրը",
+ "ooui-toolbar-more": "Ավելին",
+ "ooui-toolgroup-expand": "Ավելին",
+ "ooui-toolgroup-collapse": "Պակաս",
+ "ooui-item-remove": "Հեռացնել",
+ "ooui-dialog-message-accept": "Լավ",
+ "ooui-dialog-message-reject": "Չեղարկել",
+ "ooui-dialog-process-error": "Ինչ-որ սխալ է տեղի ունեցել",
+ "ooui-dialog-process-dismiss": "Փակել",
+ "ooui-dialog-process-retry": "Կրկին փորձել",
+ "ooui-dialog-process-continue": "Շարունակել",
+ "ooui-selectfile-button-select": "Ընտրել նիշք",
+ "ooui-selectfile-not-supported": "Ֆայլի ընտրությունը չի պաշտպանվում",
+ "ooui-selectfile-placeholder": "Ֆայլն ընտրված չէ",
+ "ooui-selectfile-dragdrop-placeholder": "Ֆայլը գցել այստե"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ia.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ia.json
new file mode 100644
index 00000000..8b3bcd80
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ia.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "McDutchie"
+ ]
+ },
+ "ooui-outline-control-move-down": "Displaciar elemento in basso",
+ "ooui-outline-control-move-up": "Displaciar elemento in alto",
+ "ooui-outline-control-remove": "Remover elemento",
+ "ooui-toolbar-more": "Plus",
+ "ooui-toolgroup-expand": "Plus",
+ "ooui-toolgroup-collapse": "Minus",
+ "ooui-item-remove": "Remover",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancellar",
+ "ooui-dialog-process-error": "Qualcosa ha vadite mal",
+ "ooui-dialog-process-dismiss": "Clauder",
+ "ooui-dialog-process-retry": "Reprobar",
+ "ooui-dialog-process-continue": "Continuar",
+ "ooui-selectfile-button-select": "Selige un file",
+ "ooui-selectfile-not-supported": "Le selection de files non es supportate",
+ "ooui-selectfile-placeholder": "Nulle file es seligite",
+ "ooui-selectfile-dragdrop-placeholder": "Depone file hic"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/id.json b/www/wiki/vendor/oojs/oojs-ui/i18n/id.json
new file mode 100644
index 00000000..10c7e22d
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/id.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Farras",
+ "Ilham151096",
+ "Iwan Novirion",
+ "Iyan",
+ "Kenrick95",
+ "McDutchie",
+ "Rv77ax",
+ "William Surya Permana",
+ "Rachmat.Wahidi",
+ "Rachmat04",
+ "Gombang"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pindahkan butir ke bawah",
+ "ooui-outline-control-move-up": "Pindahkan butir ke atas",
+ "ooui-outline-control-remove": "Hapus butir",
+ "ooui-toolbar-more": "Lainnya",
+ "ooui-toolgroup-expand": "Selengkapnya",
+ "ooui-toolgroup-collapse": "Secukupnya",
+ "ooui-item-remove": "Hapus",
+ "ooui-dialog-message-accept": "Oke",
+ "ooui-dialog-message-reject": "Batal",
+ "ooui-dialog-process-error": "Ada yang tidak beres",
+ "ooui-dialog-process-dismiss": "Tutup",
+ "ooui-dialog-process-retry": "Coba lagi",
+ "ooui-dialog-process-continue": "Lanjutkan",
+ "ooui-selectfile-button-select": "Pilih berkas",
+ "ooui-selectfile-not-supported": "Peilihan berkas tidak didukung",
+ "ooui-selectfile-placeholder": "Tidak ada berkas yang terpilih",
+ "ooui-selectfile-dragdrop-placeholder": "Letakkan berkas di sini"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ie.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ie.json
new file mode 100644
index 00000000..241cc331
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ie.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Makuba"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mover element a infra",
+ "ooui-outline-control-move-up": "Mover element a supra",
+ "ooui-toolbar-more": "Plu"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ilo.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ilo.json
new file mode 100644
index 00000000..287c86d6
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ilo.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lam-ang"
+ ]
+ },
+ "ooui-outline-control-move-down": "Ipababa ti banag",
+ "ooui-outline-control-move-up": "Ipangato ti banag",
+ "ooui-outline-control-remove": "Ikkaten ti banag",
+ "ooui-toolbar-more": "Adu pay",
+ "ooui-toolgroup-expand": "Adu pay",
+ "ooui-toolgroup-collapse": "Basbassit",
+ "ooui-dialog-message-accept": "Sige",
+ "ooui-dialog-message-reject": "Ukasen",
+ "ooui-dialog-process-error": "Adda madi a napasamak",
+ "ooui-dialog-process-dismiss": "Pugsayen",
+ "ooui-dialog-process-retry": "Padasen manen",
+ "ooui-dialog-process-continue": "Agtuloy",
+ "ooui-selectfile-not-supported": "Saan a masuportaran ti panagpili ti papeles",
+ "ooui-selectfile-placeholder": "Awan ti napili a papeles"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/inh.json b/www/wiki/vendor/oojs/oojs-ui/i18n/inh.json
new file mode 100644
index 00000000..a897ed58
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/inh.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Adam-Yourist",
+ "ElizaMag"
+ ]
+ },
+ "ooui-outline-control-move-down": "Элемент Iолохеяккха",
+ "ooui-outline-control-move-up": "Элемент Iолакхеяккха",
+ "ooui-outline-control-remove": "ДIаяккха пункт",
+ "ooui-toolbar-more": "Кхы а",
+ "ooui-toolgroup-expand": "Дукха",
+ "ooui-toolgroup-collapse": "КӀезига",
+ "ooui-dialog-message-accept": "ОК",
+ "ooui-dialog-message-reject": "Эшац",
+ "ooui-dialog-process-error": "Харцахь хилар цхьа хIама",
+ "ooui-dialog-process-dismiss": "ДIакъовла",
+ "ooui-dialog-process-retry": "Кхы цкъа де гIорта",
+ "ooui-dialog-process-continue": "ДIаьхде",
+ "ooui-selectfile-button-select": "Файл хьахаржа",
+ "ooui-selectfile-not-supported": "Файл харжа вIаштаь дац",
+ "ooui-selectfile-placeholder": "Файл хержа яц",
+ "ooui-selectfile-dragdrop-placeholder": "Хьадехьаяккха файл укхаз"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/io.json b/www/wiki/vendor/oojs/oojs-ui/i18n/io.json
new file mode 100644
index 00000000..dafb3905
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/io.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Idojc",
+ "Joao Xavier"
+ ]
+ },
+ "ooui-outline-control-move-down": "Movar elemento adsube",
+ "ooui-outline-control-move-up": "Movar elemento adsupere",
+ "ooui-outline-control-remove": "Forigar elemento",
+ "ooui-toolbar-more": "Plu multa",
+ "ooui-toolgroup-expand": "Plu multa",
+ "ooui-toolgroup-collapse": "Min multa",
+ "ooui-item-remove": "Eliminar",
+ "ooui-dialog-message-accept": "Aplikar",
+ "ooui-dialog-message-reject": "Anular",
+ "ooui-dialog-process-error": "Ulo faliis",
+ "ooui-dialog-process-dismiss": "Celar",
+ "ooui-dialog-process-retry": "Riprobar",
+ "ooui-dialog-process-continue": "Durar",
+ "ooui-selectfile-button-select": "Selektar dokumento",
+ "ooui-selectfile-not-supported": "Dokumento-selekto ne esas suportata",
+ "ooui-selectfile-placeholder": "Nula dokumento selektesis",
+ "ooui-selectfile-dragdrop-placeholder": "Pozar dokumento hike"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/is.json b/www/wiki/vendor/oojs/oojs-ui/i18n/is.json
new file mode 100644
index 00000000..3814ba2e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/is.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Maxí",
+ "Snævar",
+ "Sveinn í Felli"
+ ]
+ },
+ "ooui-outline-control-move-down": "Færa atriði niður",
+ "ooui-outline-control-move-up": "Færa atriði upp",
+ "ooui-outline-control-remove": "Fjarlægja atriði",
+ "ooui-toolbar-more": "Fleira",
+ "ooui-toolgroup-expand": "Fleira",
+ "ooui-toolgroup-collapse": "Færra",
+ "ooui-item-remove": "Fjarlægja",
+ "ooui-dialog-message-accept": "Í lagi",
+ "ooui-dialog-message-reject": "Hætta við",
+ "ooui-dialog-process-error": "Eitthvað mistókst",
+ "ooui-dialog-process-dismiss": "Loka",
+ "ooui-dialog-process-retry": "Reyna aftur",
+ "ooui-dialog-process-continue": "Halda áfram",
+ "ooui-selectfile-button-select": "Velja skrá",
+ "ooui-selectfile-not-supported": "Skráar val er ekki stutt.",
+ "ooui-selectfile-placeholder": "Engin skrá er valin",
+ "ooui-selectfile-dragdrop-placeholder": "Slepptu skránni hérna"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/it.json b/www/wiki/vendor/oojs/oojs-ui/i18n/it.json
new file mode 100644
index 00000000..a301b663
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/it.json
@@ -0,0 +1,39 @@
+{
+ "@metadata": {
+ "authors": [
+ "Beta16",
+ "Darth Kule",
+ "Doc.mari",
+ "Eleonora negri",
+ "Elitre",
+ "F. Cosoleto",
+ "FRacco",
+ "Gianfranco",
+ "Minerva Titani",
+ "Raoli",
+ "Una giornata uggiosa '94",
+ "Ontsed",
+ "Alexmar983",
+ "Nemo bis",
+ "Jdforrester",
+ "Fringio"
+ ]
+ },
+ "ooui-outline-control-move-down": "Sposta in basso",
+ "ooui-outline-control-move-up": "Sposta in alto",
+ "ooui-outline-control-remove": "Rimuovi elemento",
+ "ooui-toolbar-more": "Altro",
+ "ooui-toolgroup-expand": "Altro",
+ "ooui-toolgroup-collapse": "Meno",
+ "ooui-item-remove": "Rimuovi",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Annulla",
+ "ooui-dialog-process-error": "Qualcosa è andato storto",
+ "ooui-dialog-process-dismiss": "Nascondi",
+ "ooui-dialog-process-retry": "Riprova",
+ "ooui-dialog-process-continue": "Continua",
+ "ooui-selectfile-button-select": "Seleziona un file",
+ "ooui-selectfile-not-supported": "La selezione del file non è supportata",
+ "ooui-selectfile-placeholder": "Nessun file è selezionato",
+ "ooui-selectfile-dragdrop-placeholder": "Posiziona i file qui"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ja.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ja.json
new file mode 100644
index 00000000..1c3f9c31
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ja.json
@@ -0,0 +1,33 @@
+{
+ "@metadata": {
+ "authors": [
+ "Fryed-peach",
+ "Miya",
+ "Penn Station",
+ "Shirayuki",
+ "Takot",
+ "Los688",
+ "Sujiniku",
+ "Translatealcd",
+ "Otokoume",
+ "Rxy"
+ ]
+ },
+ "ooui-outline-control-move-down": "項目を下に移動させる",
+ "ooui-outline-control-move-up": "項目を上に移動させる",
+ "ooui-outline-control-remove": "項目を除去",
+ "ooui-toolbar-more": "その他",
+ "ooui-toolgroup-expand": "続き",
+ "ooui-toolgroup-collapse": "折り畳む",
+ "ooui-item-remove": "削除",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "キャンセル",
+ "ooui-dialog-process-error": "エラーが発生しました…",
+ "ooui-dialog-process-dismiss": "閉じる",
+ "ooui-dialog-process-retry": "もう一度お試しください",
+ "ooui-dialog-process-continue": "続行",
+ "ooui-selectfile-button-select": "ファイルを選択",
+ "ooui-selectfile-not-supported": "ファイルの選択はサポートされていません",
+ "ooui-selectfile-placeholder": "ファイルが選択されていません",
+ "ooui-selectfile-dragdrop-placeholder": "ファイルをここにドロップ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/jv.json b/www/wiki/vendor/oojs/oojs-ui/i18n/jv.json
new file mode 100644
index 00000000..5ade0156
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/jv.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gleki",
+ "NoiX180",
+ "Pras",
+ "Jadinegara",
+ "Meursault2004"
+ ]
+ },
+ "ooui-outline-control-move-down": "Lih barang mangisor",
+ "ooui-outline-control-move-up": "Lih barang mandhuwur",
+ "ooui-outline-control-remove": "Buwang barang",
+ "ooui-toolbar-more": "Liyané",
+ "ooui-toolgroup-expand": "Liyané",
+ "ooui-toolgroup-collapse": "Sacukupé",
+ "ooui-dialog-message-accept": "Oké",
+ "ooui-dialog-message-reject": "Wurung",
+ "ooui-dialog-process-error": "Ana sing salah",
+ "ooui-dialog-process-dismiss": "Tutup",
+ "ooui-dialog-process-retry": "Jajalen manèh",
+ "ooui-dialog-process-continue": "Bacutaké",
+ "ooui-selectfile-button-select": "Pilih barkas",
+ "ooui-selectfile-not-supported": "Ora bisa milih barkas",
+ "ooui-selectfile-placeholder": "Ora ana barkas sing dipilih",
+ "ooui-selectfile-dragdrop-placeholder": "Dèkèk barkas ing kéné"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ka.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ka.json
new file mode 100644
index 00000000..c6d55873
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ka.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "BRUTE",
+ "David1010",
+ "Gleki",
+ "ITshnik",
+ "MIKHEIL",
+ "NoiX180",
+ "Pras",
+ "Tokoko",
+ "Kintrbr"
+ ]
+ },
+ "ooui-outline-control-move-down": "ელემენტის ქვემოთ გადატანა",
+ "ooui-outline-control-move-up": "ელემენტის ზემოთ გადატანა",
+ "ooui-outline-control-remove": "წაშლა",
+ "ooui-toolbar-more": "მეტი",
+ "ooui-toolgroup-expand": "მეტი",
+ "ooui-toolgroup-collapse": "რამდენიმე",
+ "ooui-item-remove": "წაშლა",
+ "ooui-dialog-message-accept": "კარგი",
+ "ooui-dialog-message-reject": "გაუქმება",
+ "ooui-dialog-process-error": "მოხდა რაღაც შეცდომა",
+ "ooui-dialog-process-dismiss": "დამალვა",
+ "ooui-dialog-process-retry": "კიდევ სცადეთ",
+ "ooui-dialog-process-continue": "გაგრძელება",
+ "ooui-selectfile-button-select": "აირჩიეთ ფაილი",
+ "ooui-selectfile-not-supported": "ფაილის არჩევა არ არის მხარდაჭერილი",
+ "ooui-selectfile-placeholder": "ფაილი არ არის არჩეული",
+ "ooui-selectfile-dragdrop-placeholder": "ჩააგდეთ ფაილი აქ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/kab.json b/www/wiki/vendor/oojs/oojs-ui/i18n/kab.json
new file mode 100644
index 00000000..55016b22
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/kab.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Belkacem77"
+ ]
+ },
+ "ooui-outline-control-move-down": "Awi aferdi d akesser",
+ "ooui-outline-control-move-up": "Awi aferdis d asawen",
+ "ooui-outline-control-remove": "Kkes aferdis",
+ "ooui-toolbar-more": "Ugar",
+ "ooui-toolgroup-expand": "Ugar",
+ "ooui-toolgroup-collapse": "Drus",
+ "ooui-item-remove": "Kkes",
+ "ooui-dialog-message-accept": "IH",
+ "ooui-dialog-message-reject": "Sefsex",
+ "ooui-dialog-process-error": "Yella wayen yeḍran",
+ "ooui-dialog-process-dismiss": "Mdel",
+ "ooui-dialog-process-retry": "Ɛreḍ tikelt-nniden",
+ "ooui-dialog-process-continue": "Kemmel",
+ "ooui-selectfile-button-select": "Fren afaylu",
+ "ooui-selectfile-not-supported": "Afran n ufaylu ur yettusefrak ara",
+ "ooui-selectfile-placeholder": "Ulac afaylu yettwafernen",
+ "ooui-selectfile-dragdrop-placeholder": "Sers afaylu dagi"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/khw.json b/www/wiki/vendor/oojs/oojs-ui/i18n/khw.json
new file mode 100644
index 00000000..f0ce2073
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/khw.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Rachitrali"
+ ]
+ },
+ "ooui-toolbar-more": "مزید",
+ "ooui-toolgroup-expand": "مزید",
+ "ooui-toolgroup-collapse": "ای کما",
+ "ooui-dialog-message-accept": "ٹھیک شیر",
+ "ooui-dialog-message-reject": "کھینسل"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/kk-cyrl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/kk-cyrl.json
new file mode 100644
index 00000000..779ba7b9
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/kk-cyrl.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arystanbek"
+ ]
+ },
+ "ooui-outline-control-move-down": "Элементті төмен жылжыту",
+ "ooui-outline-control-move-up": "Элементті жоғары жылжыту",
+ "ooui-outline-control-remove": "Элементті алып тастау",
+ "ooui-toolbar-more": "толығырақ",
+ "ooui-toolgroup-expand": "Тағы",
+ "ooui-toolgroup-collapse": "Азырақ",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Қажет емес",
+ "ooui-dialog-process-error": "Бірдеңеден қате кетті",
+ "ooui-dialog-process-dismiss": "Тоқтату",
+ "ooui-dialog-process-retry": "Қайта байқап көріңіз",
+ "ooui-dialog-process-continue": "Жалғастыру",
+ "ooui-selectfile-button-select": "Файлды таңдау",
+ "ooui-selectfile-not-supported": "Файл таңдауды қолдамайды",
+ "ooui-selectfile-placeholder": "Файл таңдалмады",
+ "ooui-selectfile-dragdrop-placeholder": "Файлды мында жылжыту"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/km.json b/www/wiki/vendor/oojs/oojs-ui/i18n/km.json
new file mode 100644
index 00000000..0f924e40
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/km.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sovichet",
+ "គីមស៊្រុន"
+ ]
+ },
+ "ooui-outline-control-move-down": "រុញ​ធាតុទៅ​ក្រោម",
+ "ooui-outline-control-move-up": "រុញធាតុទៅ​លើ",
+ "ooui-outline-control-remove": "ដកធាតុចេញ",
+ "ooui-toolbar-more": "បន្ថែមទៀត",
+ "ooui-toolgroup-expand": "មើលច្រើន",
+ "ooui-toolgroup-collapse": "មើលតិច",
+ "ooui-item-remove": "ដកចេញ",
+ "ooui-dialog-message-accept": "យល់ព្រម",
+ "ooui-dialog-message-reject": "បោះបង់",
+ "ooui-dialog-process-error": "មានបញ្ហាអ្វីមួយ",
+ "ooui-dialog-process-dismiss": "បិទ",
+ "ooui-dialog-process-retry": "ព្យាយាមម្ដងទៀត",
+ "ooui-dialog-process-continue": "បន្ត",
+ "ooui-selectfile-button-select": "ជ្រើសរើសឯកសារ",
+ "ooui-selectfile-not-supported": "ការជ្រើសរើសឯកសារមិនអាចប្រើបានទេ",
+ "ooui-selectfile-placeholder": "គ្មានឯកសារណាមួយត្រូវបានជ្រើសរើស",
+ "ooui-selectfile-dragdrop-placeholder": "ទម្លាក់ឯកសារនៅទីនេះ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/kn.json b/www/wiki/vendor/oojs/oojs-ui/i18n/kn.json
new file mode 100644
index 00000000..741cfb33
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/kn.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Vikassy",
+ "Nayvik",
+ "Omshivaprakash",
+ "Pavanaja",
+ "Yogesh"
+ ]
+ },
+ "ooui-outline-control-move-down": "ವಸ್ತುವನ್ನು ಕೆಳಗೆ ಸರಿಸು",
+ "ooui-outline-control-move-up": "ವಸ್ತುವನ್ನು ಮೇಲೆ ಸರಿಸು",
+ "ooui-outline-control-remove": "ವಸ್ತುವನ್ನು ತೆಗೆ",
+ "ooui-toolbar-more": "ಇನ್ನಷ್ಟು",
+ "ooui-toolgroup-expand": "ಇನ್ನಷ್ಟು",
+ "ooui-toolgroup-collapse": "ಕೆಲವೇ ಕೆಲವು",
+ "ooui-dialog-message-accept": "ಸರಿ",
+ "ooui-dialog-message-reject": "ರದ್ದುಮಾಡು",
+ "ooui-dialog-process-error": "ಏನೋ ಎಡವಟ್ಟಾಗಿದೆ....",
+ "ooui-dialog-process-dismiss": "ತೆಗೆದುಹಾಕು",
+ "ooui-dialog-process-retry": "ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ",
+ "ooui-dialog-process-continue": "ಮುಂದುವರೆಸು",
+ "ooui-selectfile-button-select": "ಕಡತವನ್ನು ಆಯ್ಕೆಮಾಡಿ",
+ "ooui-selectfile-placeholder": "ಕಡತವು ಆಯ್ಕೆಯಾಗಿಲ್ಲ",
+ "ooui-selectfile-dragdrop-placeholder": "ಇಲ್ಲಿ ಕಡತವನ್ನು ಬಿಡಿ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ko.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ko.json
new file mode 100644
index 00000000..dc3c84a7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ko.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Freebiekr",
+ "Hym411",
+ "Kwj2772",
+ "LFM",
+ "아라",
+ "고기랑",
+ "Ryuch",
+ "Revi",
+ "Infinity",
+ "Hwangjy9",
+ "Ykhwong"
+ ]
+ },
+ "ooui-outline-control-move-down": "항목을 아래로 이동",
+ "ooui-outline-control-move-up": "항목을 위로 이동",
+ "ooui-outline-control-remove": "항목 제거",
+ "ooui-toolbar-more": "더 보기",
+ "ooui-toolgroup-expand": "더 보기",
+ "ooui-toolgroup-collapse": "덜 보기",
+ "ooui-item-remove": "제거",
+ "ooui-dialog-message-accept": "확인",
+ "ooui-dialog-message-reject": "취소",
+ "ooui-dialog-process-error": "무언가가 잘못되었습니다",
+ "ooui-dialog-process-dismiss": "숨기기",
+ "ooui-dialog-process-retry": "다시 시도하세요",
+ "ooui-dialog-process-continue": "계속",
+ "ooui-selectfile-button-select": "파일을 선택하세요",
+ "ooui-selectfile-not-supported": "파일 선택은 지원하지 않습니다",
+ "ooui-selectfile-placeholder": "선택한 파일 없음",
+ "ooui-selectfile-dragdrop-placeholder": "여기에 파일을 놓으세요"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/krc.json b/www/wiki/vendor/oojs/oojs-ui/i18n/krc.json
new file mode 100644
index 00000000..6f17b346
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/krc.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Iltever",
+ "Ernác"
+ ]
+ },
+ "ooui-outline-control-move-down": "Элементни тюбюне кёчюр",
+ "ooui-outline-control-move-up": "Элементни башына кёчюр",
+ "ooui-outline-control-remove": "Пунктну кетер",
+ "ooui-toolbar-more": "Энтда",
+ "ooui-toolgroup-expand": "Энтда",
+ "ooui-toolgroup-collapse": "Артха",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Ызына ал",
+ "ooui-dialog-process-error": "Не эсе да табсыз кетди",
+ "ooui-dialog-process-dismiss": "Джаб",
+ "ooui-dialog-process-retry": "Энтда сынаб кёр",
+ "ooui-dialog-process-continue": "Бардыр",
+ "ooui-selectfile-not-supported": "Файл сайлау тутулмайды",
+ "ooui-selectfile-placeholder": "Бир файл да сайланмагъанды"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/krl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/krl.json
new file mode 100644
index 00000000..6ff25ebe
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/krl.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mashoi7"
+ ]
+ },
+ "ooui-toolbar-more": "Enämpi",
+ "ooui-toolgroup-expand": "Enämpi",
+ "ooui-toolgroup-collapse": "Vähempi"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ksh.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ksh.json
new file mode 100644
index 00000000..f99c29fd
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ksh.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Purodha"
+ ]
+ },
+ "ooui-outline-control-move-down": "Öm eine Plaz noh onge schiehbe",
+ "ooui-outline-control-move-up": "Öm eine Plaz noh bovve schiehbe",
+ "ooui-outline-control-remove": "Dä Plaz läddesch maache → fott domet!",
+ "ooui-toolbar-more": "Mih",
+ "ooui-toolgroup-expand": "Mih",
+ "ooui-toolgroup-collapse": "Winnijer",
+ "ooui-dialog-message-accept": "Lohß Jonn!",
+ "ooui-dialog-message-reject": "Ophühre",
+ "ooui-dialog-process-error": "Öhnsjädd es scheif jejange",
+ "ooui-dialog-process-dismiss": "Maach fott, ha_sch jelässe",
+ "ooui-dialog-process-retry": "Norr_ens versöhke",
+ "ooui-dialog-process-continue": "Wigger maache",
+ "ooui-selectfile-button-select": "Söhg en Dattei uß",
+ "ooui-selectfile-not-supported": "Mer ogerschtözze et Datteij_Ußwähle nit.",
+ "ooui-selectfile-placeholder": "Kein Dattei es ußjewählt"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ku-latn.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ku-latn.json
new file mode 100644
index 00000000..99547449
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ku-latn.json
@@ -0,0 +1,17 @@
+{
+ "@metadata": {
+ "authors": [
+ "George Animal",
+ "Bikarhêner"
+ ]
+ },
+ "ooui-toolbar-more": "Bêhtir",
+ "ooui-toolgroup-expand": "Bêhtir",
+ "ooui-toolgroup-collapse": "Kêmtir",
+ "ooui-dialog-message-accept": "Baş e",
+ "ooui-dialog-message-reject": "Betal bike",
+ "ooui-dialog-process-retry": "Dîsa hewl bide",
+ "ooui-dialog-process-continue": "Bidomîne",
+ "ooui-selectfile-button-select": "Dosyeyekê hilbijêre",
+ "ooui-selectfile-placeholder": "Ti dosye nehatiye hilbijartin"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/kw.json b/www/wiki/vendor/oojs/oojs-ui/i18n/kw.json
new file mode 100644
index 00000000..a6c6d8ab
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/kw.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "George Animal",
+ "Nrowe",
+ "Purodha"
+ ]
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ky.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ky.json
new file mode 100644
index 00000000..e2b8ab7a
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ky.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chorobek",
+ "George Animal",
+ "Nrowe",
+ "Tynchtyk Chorotegin",
+ "Викиней"
+ ]
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/la.json b/www/wiki/vendor/oojs/oojs-ui/i18n/la.json
new file mode 100644
index 00000000..7a9b2d23
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/la.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jdforrester"
+ ]
+ },
+ "ooui-toolbar-more": "Plus",
+ "ooui-toolgroup-expand": "Plus",
+ "ooui-toolgroup-collapse": "Paucior",
+ "ooui-dialog-message-accept": "Assentior",
+ "ooui-dialog-message-reject": "Dimittere",
+ "ooui-dialog-process-dismiss": "Dimittere",
+ "ooui-dialog-process-retry": "Retemptare",
+ "ooui-dialog-process-continue": "Pergere"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/lb.json b/www/wiki/vendor/oojs/oojs-ui/i18n/lb.json
new file mode 100644
index 00000000..3deee0d6
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/lb.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Autokrator",
+ "Chorobek",
+ "Robby",
+ "Soued031",
+ "Tynchtyk Chorotegin",
+ "UV",
+ "Викиней"
+ ]
+ },
+ "ooui-outline-control-move-down": "Element erof réckelen",
+ "ooui-outline-control-move-up": "Element erop réckelen",
+ "ooui-outline-control-remove": "Element ewechhuelen",
+ "ooui-toolbar-more": "Méi",
+ "ooui-toolgroup-expand": "Méi",
+ "ooui-toolgroup-collapse": "Manner",
+ "ooui-item-remove": "Ewechhuelen",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Ofbriechen",
+ "ooui-dialog-process-error": "Et ass eppes schif gaang",
+ "ooui-dialog-process-dismiss": "Verwerfen",
+ "ooui-dialog-process-retry": "Nach eng Kéier probéieren",
+ "ooui-dialog-process-continue": "Virufueren",
+ "ooui-selectfile-button-select": "E Fichier eraussichen",
+ "ooui-selectfile-not-supported": "D'Eraussiche vu Fichiere gëtt net ënnerstëtzt.",
+ "ooui-selectfile-placeholder": "Et ass kee Fichier erausgesicht",
+ "ooui-selectfile-dragdrop-placeholder": "Fichier hei ofleeën"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/li.json b/www/wiki/vendor/oojs/oojs-ui/i18n/li.json
new file mode 100644
index 00000000..0012c9cd
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/li.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Pahles",
+ "Ooswesthoesbes"
+ ]
+ },
+ "ooui-outline-control-move-down": "Item nao ónger verplaatse",
+ "ooui-outline-control-move-up": "Item nao bove verplaetse",
+ "ooui-outline-control-remove": "Item ewegsjaffe",
+ "ooui-toolbar-more": "Mieë",
+ "ooui-toolgroup-expand": "Mieë",
+ "ooui-toolgroup-collapse": "Minder",
+ "ooui-dialog-message-accept": "Ok",
+ "ooui-dialog-message-reject": "Aafbraeke",
+ "ooui-dialog-process-error": "Dao is get misgegange",
+ "ooui-dialog-process-dismiss": "Sjlete",
+ "ooui-dialog-process-retry": "Perbeer obbenuujts",
+ "ooui-dialog-process-continue": "Doorgaon",
+ "ooui-selectfile-button-select": "Kees e bestandj",
+ "ooui-selectfile-not-supported": "Selektie van 'n besjtandj waert neet óngersteund",
+ "ooui-selectfile-placeholder": "Dao is gein besjtandj geselekteerd",
+ "ooui-selectfile-dragdrop-placeholder": "Sleip e bestandj hieroppes"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/lki.json b/www/wiki/vendor/oojs/oojs-ui/i18n/lki.json
new file mode 100644
index 00000000..ab6db143
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/lki.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hosseinblue",
+ "Arash71"
+ ]
+ },
+ "ooui-outline-control-move-down": "جاوواز کردن ئإ هووار",
+ "ooui-outline-control-move-up": "جاوواز کردن ئإ بِلِنگ",
+ "ooui-outline-control-remove": "حذف مورد",
+ "ooui-toolbar-more": "ویشتر/فرۀتر",
+ "ooui-toolgroup-expand": "ویشتر/فرۀتر",
+ "ooui-toolgroup-collapse": "کۀمتر",
+ "ooui-dialog-message-accept": "خوو/ باشد",
+ "ooui-dialog-message-reject": "ئآهووسانن/لغو",
+ "ooui-dialog-process-error": "مشکلی هۀس",
+ "ooui-dialog-process-dismiss": "رد کردن",
+ "ooui-dialog-process-retry": "دووآرۀ تلاش کۀ",
+ "ooui-dialog-process-continue": "ادامه-دؤم گرتن",
+ "ooui-selectfile-button-select": "فایلئ انتخاب کۀ",
+ "ooui-selectfile-not-supported": "انتخاب پرونده پشتیبانی نمی‌شود",
+ "ooui-selectfile-placeholder": "هیچ پرونده‌ای انتخاب نشده است",
+ "ooui-selectfile-dragdrop-placeholder": "فایل را اینجا رها کنید"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/lmo.json b/www/wiki/vendor/oojs/oojs-ui/i18n/lmo.json
new file mode 100644
index 00000000..87309db0
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/lmo.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ninonino"
+ ]
+ },
+ "ooui-outline-control-move-down": "Spòsta 'n zó",
+ "ooui-outline-control-move-up": "Spòsta 'n sö",
+ "ooui-toolbar-more": "Amò"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/lt.json b/www/wiki/vendor/oojs/oojs-ui/i18n/lt.json
new file mode 100644
index 00000000..ea134067
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/lt.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Audriusa",
+ "Eitvys200",
+ "Mantak111",
+ "Albertas",
+ "Manvydasz"
+ ]
+ },
+ "ooui-outline-control-move-down": "Perkelti elementą žemyn",
+ "ooui-outline-control-move-up": "Perkelti elementą aukštyn",
+ "ooui-outline-control-remove": "Šalinti įrašą",
+ "ooui-toolbar-more": "Daugiau",
+ "ooui-toolgroup-expand": "Daugiau",
+ "ooui-toolgroup-collapse": "Mažiau",
+ "ooui-item-remove": "Pašalinti",
+ "ooui-dialog-message-accept": "Gerai",
+ "ooui-dialog-message-reject": "Atšaukti",
+ "ooui-dialog-process-error": "Kažkas nutiko ne taip",
+ "ooui-dialog-process-dismiss": "Paslėpti",
+ "ooui-dialog-process-retry": "Bandykite dar kartą",
+ "ooui-dialog-process-continue": "Tęsti",
+ "ooui-selectfile-button-select": "Pasirinkti failą",
+ "ooui-selectfile-not-supported": "Failų pasirinkimas nepalaikomas",
+ "ooui-selectfile-placeholder": "Nėra pasirinktų failų",
+ "ooui-selectfile-dragdrop-placeholder": "Atitempkite failą čia"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/luz.json b/www/wiki/vendor/oojs/oojs-ui/i18n/luz.json
new file mode 100644
index 00000000..d48a9dfa
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/luz.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "علی ساکی لرستانی"
+ ]
+ },
+ "ooui-outline-control-move-down": "انتقال مورد وه دومن",
+ "ooui-outline-control-move-up": "انتقال مورد وه بالا",
+ "ooui-outline-control-remove": "حذف مورد",
+ "ooui-toolbar-more": "هنی",
+ "ooui-toolgroup-expand": "هنی",
+ "ooui-toolgroup-collapse": "کم تر",
+ "ooui-dialog-message-accept": "خووه",
+ "ooui-dialog-message-reject": "لغو",
+ "ooui-dialog-process-error": "یه چیایی اشتباه ویده",
+ "ooui-dialog-process-dismiss": "منفصل کردن",
+ "ooui-dialog-process-retry": "دوباره تلاش کردن",
+ "ooui-dialog-process-continue": "ادامه دائن",
+ "ooui-selectfile-not-supported": "فایل انتخابی پشتیبانی نوابیه",
+ "ooui-selectfile-placeholder": "فایلی انتخاب نوابیه"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/lv.json b/www/wiki/vendor/oojs/oojs-ui/i18n/lv.json
new file mode 100644
index 00000000..6423c751
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/lv.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Admresdeserv.",
+ "Audriusa",
+ "Eitvys200",
+ "Papuass",
+ "PeterisP"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pārvietot vienumu uz leju",
+ "ooui-outline-control-move-up": "Pārvietot vienumu uz augšu",
+ "ooui-outline-control-remove": "Noņemt vienumu",
+ "ooui-toolbar-more": "Vairāk",
+ "ooui-toolgroup-expand": "Vairāk",
+ "ooui-toolgroup-collapse": "Mazāk",
+ "ooui-item-remove": "Noņemt",
+ "ooui-dialog-message-accept": "Labi",
+ "ooui-dialog-message-reject": "Atcelt",
+ "ooui-dialog-process-error": "Kaut kas nogāja greizi",
+ "ooui-dialog-process-dismiss": "Paslēpt",
+ "ooui-dialog-process-retry": "Mēģināt vēlreiz",
+ "ooui-dialog-process-continue": "Turpināt",
+ "ooui-selectfile-button-select": "Izvēlies failu",
+ "ooui-selectfile-not-supported": "Failu izvēle nav atbalstīta",
+ "ooui-selectfile-placeholder": "Nav izvēlēts neviens fails",
+ "ooui-selectfile-dragdrop-placeholder": "Nomet failu šeit"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/lzh.json b/www/wiki/vendor/oojs/oojs-ui/i18n/lzh.json
new file mode 100644
index 00000000..d0f1bd2a
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/lzh.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joe young yu",
+ "Itsmine",
+ "SolidBlock"
+ ]
+ },
+ "ooui-outline-control-move-down": "遷下",
+ "ooui-outline-control-move-up": "遷上",
+ "ooui-outline-control-remove": "去物",
+ "ooui-toolbar-more": "餘",
+ "ooui-dialog-message-accept": "可"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/mg.json b/www/wiki/vendor/oojs/oojs-ui/i18n/mg.json
new file mode 100644
index 00000000..722b3e29
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/mg.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jagwar"
+ ]
+ },
+ "ooui-outline-control-move-down": "Hampidina ilay zavatra",
+ "ooui-outline-control-move-up": "Hampiakatra ilay zavatra",
+ "ooui-outline-control-remove": "Hanala iay zavatra",
+ "ooui-toolbar-more": "Be kokoa",
+ "ooui-toolgroup-expand": "Be kokoa",
+ "ooui-toolgroup-collapse": "Kely kokoa",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Avela",
+ "ooui-dialog-process-error": "Nisy hadisoana nitranga",
+ "ooui-dialog-process-dismiss": "Esorina",
+ "ooui-dialog-process-retry": "Andramana indray",
+ "ooui-dialog-process-continue": "Tohizana",
+ "ooui-selectfile-button-select": "Misafidia rakitra iray",
+ "ooui-selectfile-not-supported": "Tsy zaka ny fisafidiana rakitra",
+ "ooui-selectfile-placeholder": "Tsy misy rakitra voafidy",
+ "ooui-selectfile-dragdrop-placeholder": "Hametraka rakitra eto"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/min.json b/www/wiki/vendor/oojs/oojs-ui/i18n/min.json
new file mode 100644
index 00000000..b8790d31
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/min.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Iwan Novirion",
+ "Jagwar"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pindahan ko ka bawah",
+ "ooui-outline-control-move-up": "Pindahan ko ka ateh",
+ "ooui-outline-control-remove": "Hapuih ko",
+ "ooui-toolbar-more": "Lainnyo",
+ "ooui-dialog-message-accept": "Yo",
+ "ooui-dialog-message-reject": "Batal"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/mk.json b/www/wiki/vendor/oojs/oojs-ui/i18n/mk.json
new file mode 100644
index 00000000..23d07760
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/mk.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bjankuloski06",
+ "Brest",
+ "Iwan Novirion"
+ ]
+ },
+ "ooui-outline-control-move-down": "Помести надолу",
+ "ooui-outline-control-move-up": "Помести нагоре",
+ "ooui-outline-control-remove": "Отстрани ставка",
+ "ooui-toolbar-more": "Повеќе",
+ "ooui-toolgroup-expand": "Повеќе",
+ "ooui-toolgroup-collapse": "Помалку",
+ "ooui-item-remove": "Отстрани",
+ "ooui-dialog-message-accept": "ОК",
+ "ooui-dialog-message-reject": "Откажи",
+ "ooui-dialog-process-error": "Нешто не е во ред",
+ "ooui-dialog-process-dismiss": "Тргни",
+ "ooui-dialog-process-retry": "Обиди се пак",
+ "ooui-dialog-process-continue": "Продолжи",
+ "ooui-selectfile-button-select": "Одберете податотека",
+ "ooui-selectfile-not-supported": "Изборот на податотеки не е поддржан",
+ "ooui-selectfile-placeholder": "Немате одбрано податотека",
+ "ooui-selectfile-dragdrop-placeholder": "Тука пуштете ја податотеката"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ml.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ml.json
new file mode 100644
index 00000000..9649b2eb
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ml.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kavya Manohar",
+ "Praveenp",
+ "Santhosh.thottingal",
+ "Vssun",
+ "Ranjithsiji"
+ ]
+ },
+ "ooui-outline-control-move-down": "ഇനം താഴേയ്ക്ക് മാറ്റുക",
+ "ooui-outline-control-move-up": "ഇനം മുകളിലേയ്ക്ക് മാറ്റുക",
+ "ooui-outline-control-remove": "ഇനം നീക്കംചെയ്യുക",
+ "ooui-toolbar-more": "കൂടുതൽ",
+ "ooui-toolgroup-expand": "കൂടുതൽ",
+ "ooui-toolgroup-collapse": "കുറച്ച്",
+ "ooui-dialog-message-accept": "ശരി",
+ "ooui-dialog-message-reject": "റദ്ദാക്കുക",
+ "ooui-dialog-process-error": "എന്തോ പ്രശ്നമുണ്ടായി",
+ "ooui-dialog-process-dismiss": "ഒഴിവാക്കുക",
+ "ooui-dialog-process-retry": "വീണ്ടും ശ്രമിക്കുക",
+ "ooui-dialog-process-continue": "തുടരുക",
+ "ooui-selectfile-button-select": "പ്രമാണം തിരഞ്ഞെടുക്കുക",
+ "ooui-selectfile-not-supported": "പ്രമാണം തിരഞ്ഞെടുക്കൽ പിന്തുണയ്ക്കുന്നില്ല",
+ "ooui-selectfile-placeholder": "പ്രമാണങ്ങൾ ഒന്നും തിരഞ്ഞെടുത്തിട്ടില്ല",
+ "ooui-selectfile-dragdrop-placeholder": "പ്രമാണം ഇവിടെ ഇടുക"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/mn.json b/www/wiki/vendor/oojs/oojs-ui/i18n/mn.json
new file mode 100644
index 00000000..500aca78
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/mn.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Munkhzaya.E"
+ ]
+ },
+ "ooui-toolbar-more": "Илүү",
+ "ooui-toolgroup-expand": "Илүү",
+ "ooui-toolgroup-collapse": "Цөөн",
+ "ooui-dialog-message-accept": "За",
+ "ooui-dialog-message-reject": "Цуцлах",
+ "ooui-dialog-process-error": "Ямар нэг алдаа гарсан",
+ "ooui-dialog-process-dismiss": "Нуух",
+ "ooui-dialog-process-retry": "Дахин оролдох",
+ "ooui-dialog-process-continue": "Цааш явах",
+ "ooui-selectfile-button-select": "Файлаа сонгох",
+ "ooui-selectfile-not-supported": "Сонгосол файл нь дэмжигдэхгүй байна",
+ "ooui-selectfile-placeholder": "Файл сонгоогүй байна",
+ "ooui-selectfile-dragdrop-placeholder": "Файлаа энд хадгалах"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/mr.json b/www/wiki/vendor/oojs/oojs-ui/i18n/mr.json
new file mode 100644
index 00000000..e4a6bd16
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/mr.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kaajawa",
+ "Mahitgar",
+ "Praju23",
+ "V.narsikar",
+ "Ydyashad",
+ "संतोष दहिवळ",
+ "NehalDaveND",
+ "Sau6402",
+ "Sureshkhole"
+ ]
+ },
+ "ooui-outline-control-move-down": "घटक (आयटम) खाली सरकवा",
+ "ooui-outline-control-move-up": "घटक (आयटम) वर सरकवा",
+ "ooui-outline-control-remove": "बाब हटवा",
+ "ooui-toolbar-more": "अधिक",
+ "ooui-toolgroup-expand": "अधिक",
+ "ooui-toolgroup-collapse": "कमी",
+ "ooui-item-remove": "हटवा",
+ "ooui-dialog-message-accept": "ठिक आहे",
+ "ooui-dialog-message-reject": "रद्द करा",
+ "ooui-dialog-process-error": "काहीतरी गडबड झाली",
+ "ooui-dialog-process-dismiss": "रद्द करा",
+ "ooui-dialog-process-retry": "पुन्हा प्रयत्न करा",
+ "ooui-dialog-process-continue": "चालू ठेवा",
+ "ooui-selectfile-button-select": "संचिका निवडा",
+ "ooui-selectfile-not-supported": "संचिका निवडणे साहाय्यीकृत नाही",
+ "ooui-selectfile-placeholder": "संचिका निवडल्या गेली नाही",
+ "ooui-selectfile-dragdrop-placeholder": "संचिका येथे टाका"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ms.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ms.json
new file mode 100644
index 00000000..45894579
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ms.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia",
+ "Aurora",
+ "Pizza1016",
+ "Karmadunya9-"
+ ]
+ },
+ "ooui-outline-control-move-down": "Alihkan perkara ke bawah",
+ "ooui-outline-control-move-up": "Alihkan perkara ke atas",
+ "ooui-outline-control-remove": "Buang perkara",
+ "ooui-toolbar-more": "Selebihnya",
+ "ooui-toolgroup-expand": "Selengkapnya",
+ "ooui-toolgroup-collapse": "Secukupnya",
+ "ooui-item-remove": "Buang",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Batal",
+ "ooui-dialog-process-error": "Ada masalah",
+ "ooui-dialog-process-dismiss": "Singkir",
+ "ooui-dialog-process-retry": "Cuba lagi",
+ "ooui-dialog-process-continue": "Teruskan",
+ "ooui-selectfile-button-select": "Pilih fail",
+ "ooui-selectfile-not-supported": "Pilihan fail tidak disokong",
+ "ooui-selectfile-placeholder": "Tiada fail yang dipilih",
+ "ooui-selectfile-dragdrop-placeholder": "Letakkan fail di sini"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/myv.json b/www/wiki/vendor/oojs/oojs-ui/i18n/myv.json
new file mode 100644
index 00000000..faf1db70
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/myv.json
@@ -0,0 +1,17 @@
+{
+ "@metadata": {
+ "authors": [
+ "Rueter"
+ ]
+ },
+ "ooui-toolbar-more": "Седе ламо",
+ "ooui-toolgroup-expand": "Седе ламо",
+ "ooui-toolgroup-collapse": "Седе аламо",
+ "ooui-item-remove": "Нардамс",
+ "ooui-dialog-message-accept": "Маштови",
+ "ooui-dialog-message-reject": "Саемс мекев",
+ "ooui-dialog-process-error": "Мезе-бути аволь истя",
+ "ooui-dialog-process-retry": "Варчамс одов",
+ "ooui-dialog-process-continue": "Поладомс",
+ "ooui-selectfile-button-select": "Кочкамс файла"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/nan.json b/www/wiki/vendor/oojs/oojs-ui/i18n/nan.json
new file mode 100644
index 00000000..d94118d7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/nan.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Luuva"
+ ]
+ },
+ "ooui-outline-control-move-down": "Hāng-bo̍k sóa ē-té",
+ "ooui-outline-control-move-up": "Hāng-bo̍k sóa téng-bīn",
+ "ooui-outline-control-remove": "Sóa cháu hāng-bo̍k",
+ "ooui-toolbar-more": "Khah chē",
+ "ooui-toolgroup-expand": "Khah chē",
+ "ooui-toolgroup-collapse": "Khah kiám",
+ "ooui-dialog-message-accept": "Liáu-kái",
+ "ooui-dialog-message-reject": "Chhú-siau",
+ "ooui-dialog-process-error": "Ū mi̍h bô hó-sè",
+ "ooui-dialog-process-dismiss": "Koaiⁿ tiāu",
+ "ooui-dialog-process-retry": "Koh chhì khòaⁿ-māi",
+ "ooui-dialog-process-continue": "Kè-sio̍k",
+ "ooui-selectfile-button-select": "Soán-tek 1-ê tóng-àn",
+ "ooui-selectfile-not-supported": "Só͘ soán ê tóng-àn bô siū chi-chhî",
+ "ooui-selectfile-placeholder": "Iáu-bē soán tóng-àn",
+ "ooui-selectfile-dragdrop-placeholder": "Kā tóng-àn tàn chia"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/nap.json b/www/wiki/vendor/oojs/oojs-ui/i18n/nap.json
new file mode 100644
index 00000000..b7e37b49
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/nap.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chelin",
+ "Chrisportelli",
+ "PiRSquared17",
+ "C.R.",
+ "Candalua"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mòve abbascio",
+ "ooui-outline-control-move-up": "Mòve ncoppa",
+ "ooui-outline-control-remove": "Leva elemento",
+ "ooui-toolbar-more": "Atro",
+ "ooui-toolgroup-expand": "Cchiù",
+ "ooui-toolgroup-collapse": "Meno",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Scancella",
+ "ooui-dialog-process-error": "Cocchosa è ghiuta malamente",
+ "ooui-dialog-process-dismiss": "Passa 'a vacca",
+ "ooui-dialog-process-retry": "Prova n'ata vota",
+ "ooui-dialog-process-continue": "Continua",
+ "ooui-selectfile-button-select": "Sceglie nu file",
+ "ooui-selectfile-not-supported": "Filtro 'e selezione nun suppurtato",
+ "ooui-selectfile-placeholder": "Nun s'è scigliuto nisciuno file",
+ "ooui-selectfile-dragdrop-placeholder": "Lassa 'o file ccà"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/nb.json b/www/wiki/vendor/oojs/oojs-ui/i18n/nb.json
new file mode 100644
index 00000000..9c20ba31
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/nb.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Danmichaelo",
+ "Event",
+ "Jeblad",
+ "Laaknor",
+ "Njardarlogar",
+ "Jdforrester",
+ "Apple farmer",
+ "Jon Harald Søby"
+ ]
+ },
+ "ooui-outline-control-move-down": "Flytt ned",
+ "ooui-outline-control-move-up": "Flytt opp",
+ "ooui-outline-control-remove": "Fjern element",
+ "ooui-toolbar-more": "Mer",
+ "ooui-toolgroup-expand": "Mer",
+ "ooui-toolgroup-collapse": "Færre",
+ "ooui-item-remove": "Fjern",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Avbryt",
+ "ooui-dialog-process-error": "Noe gikk galt",
+ "ooui-dialog-process-dismiss": "Lukk",
+ "ooui-dialog-process-retry": "Prøv igjen",
+ "ooui-dialog-process-continue": "Fortsett",
+ "ooui-selectfile-button-select": "Velg en fil",
+ "ooui-selectfile-not-supported": "Filvalg er ikke støttet",
+ "ooui-selectfile-placeholder": "Ingen fil er valgt",
+ "ooui-selectfile-dragdrop-placeholder": "Slipp fil her"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/nds-nl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/nds-nl.json
new file mode 100644
index 00000000..d3db318b
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/nds-nl.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "Servien"
+ ]
+ },
+ "ooui-outline-control-move-down": "Onderwarp ummeneer zetten",
+ "ooui-outline-control-move-up": "Onderwarp umhoge zetten",
+ "ooui-outline-control-remove": "Element vortdoon",
+ "ooui-toolbar-more": "Meer",
+ "ooui-toolgroup-expand": "Meer",
+ "ooui-toolgroup-collapse": "Minder",
+ "ooui-dialog-message-accept": "Okee",
+ "ooui-dialog-message-reject": "Aofbreken",
+ "ooui-dialog-process-error": "Der gung iets fout",
+ "ooui-dialog-process-dismiss": "Sluten",
+ "ooui-dialog-process-retry": "Opniej proberen",
+ "ooui-dialog-process-continue": "Deurgaon"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/nds.json b/www/wiki/vendor/oojs/oojs-ui/i18n/nds.json
new file mode 100644
index 00000000..9dee2f55
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/nds.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Zylbath",
+ "Joachim Mos"
+ ]
+ },
+ "ooui-outline-control-move-down": "Element na ünnen schuven",
+ "ooui-outline-control-move-up": "Element na baven schuven",
+ "ooui-toolbar-more": "Mehr",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Afbreken",
+ "ooui-dialog-process-error": "Do is wat in'e Büx goan",
+ "ooui-dialog-process-continue": "Wiedermaken",
+ "ooui-selectfile-button-select": "En Datei utwählen"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ne.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ne.json
new file mode 100644
index 00000000..c7d28613
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ne.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "RajeshPandey",
+ "सरोज कुमार ढकाल",
+ "Ganesh Paudel",
+ "Nirajan pant"
+ ]
+ },
+ "ooui-outline-control-move-down": "वस्तुलाई तल सार्ने",
+ "ooui-outline-control-move-up": "वस्तुलाई माथि सार्ने",
+ "ooui-outline-control-remove": "वस्तुलाई हटाउने",
+ "ooui-toolbar-more": "थप",
+ "ooui-toolgroup-expand": "थप",
+ "ooui-toolgroup-collapse": "कम",
+ "ooui-item-remove": "हटाउनुहोस्",
+ "ooui-dialog-message-accept": "हुन्छ",
+ "ooui-dialog-message-reject": "रद्द गर्ने",
+ "ooui-dialog-process-dismiss": "खारेज गर्ने",
+ "ooui-dialog-process-retry": "पुन प्रयास गर्नुहोस",
+ "ooui-dialog-process-continue": "जारी राख्ने"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/nl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/nl.json
new file mode 100644
index 00000000..694eb3c2
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/nl.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bluyten",
+ "Breghtje",
+ "Catrope",
+ "Flightmare",
+ "Hansmuller",
+ "Jdforrester",
+ "Keegan",
+ "Konovalov",
+ "RajeshPandey",
+ "Romaine",
+ "SPQRobin",
+ "Saruman",
+ "Siebrand",
+ "Southparkfan",
+ "सरोज कुमार ढकाल",
+ "Sjoerddebruin",
+ "Gloria sah",
+ "Mainframe98"
+ ]
+ },
+ "ooui-outline-control-move-down": "Item omlaag verplaatsen",
+ "ooui-outline-control-move-up": "Item omhoog verplaatsen",
+ "ooui-outline-control-remove": "Item verwijderen",
+ "ooui-toolbar-more": "Meer",
+ "ooui-toolgroup-expand": "Meer",
+ "ooui-toolgroup-collapse": "Minder",
+ "ooui-item-remove": "Verwijderen",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Annuleren",
+ "ooui-dialog-process-error": "Er is iets misgegaan",
+ "ooui-dialog-process-dismiss": "Sluiten",
+ "ooui-dialog-process-retry": "Opnieuw proberen",
+ "ooui-dialog-process-continue": "Doorgaan",
+ "ooui-selectfile-button-select": "Selecteer een bestand",
+ "ooui-selectfile-not-supported": "Selectie van een bestand wordt niet ondersteund",
+ "ooui-selectfile-placeholder": "Er is geen bestand geselecteerd",
+ "ooui-selectfile-dragdrop-placeholder": "Sleep hier een bestand heen"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/nn.json b/www/wiki/vendor/oojs/oojs-ui/i18n/nn.json
new file mode 100644
index 00000000..a32e7a41
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/nn.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jeblad",
+ "Njardarlogar"
+ ]
+ },
+ "ooui-outline-control-move-down": "Flytt element ned",
+ "ooui-outline-control-move-up": "Flytt element opp",
+ "ooui-toolbar-more": "Meir",
+ "ooui-toolgroup-expand": "Meir",
+ "ooui-toolgroup-collapse": "Færre",
+ "ooui-dialog-message-reject": "Bryt av",
+ "ooui-dialog-process-error": "Noko gjekk gale",
+ "ooui-dialog-process-dismiss": "Lat att",
+ "ooui-dialog-process-continue": "Hald fram",
+ "ooui-selectfile-button-select": "Vel ei fil",
+ "ooui-selectfile-placeholder": "Inga fil er vald",
+ "ooui-selectfile-dragdrop-placeholder": "Slepp fil her"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/oc.json b/www/wiki/vendor/oojs/oojs-ui/i18n/oc.json
new file mode 100644
index 00000000..24a5966f
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/oc.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cedric31",
+ "Gloria sah"
+ ]
+ },
+ "ooui-outline-control-move-down": "Far davalar l’element",
+ "ooui-outline-control-move-up": "Far montar l’element",
+ "ooui-outline-control-remove": "Suprimir l’element",
+ "ooui-toolbar-more": "Mai",
+ "ooui-toolgroup-expand": "Mai",
+ "ooui-toolgroup-collapse": "Mens",
+ "ooui-dialog-message-accept": "D'acòrdi",
+ "ooui-dialog-message-reject": "Anullar",
+ "ooui-dialog-process-error": "Quicòm a trucat",
+ "ooui-dialog-process-dismiss": "Regetar",
+ "ooui-dialog-process-retry": "Ensajatz tornamai",
+ "ooui-dialog-process-continue": "Contunhar",
+ "ooui-selectfile-button-select": "Seleccionar un fichièr",
+ "ooui-selectfile-not-supported": "Lo tipe de fichièr es pas compatible",
+ "ooui-selectfile-placeholder": "Cap de fichièr pas seleccionat",
+ "ooui-selectfile-dragdrop-placeholder": "Depausar lo fichièr aicí"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/olo.json b/www/wiki/vendor/oojs/oojs-ui/i18n/olo.json
new file mode 100644
index 00000000..1dc994eb
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/olo.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mashoi7"
+ ]
+ },
+ "ooui-outline-control-move-down": "Siirrä kohteh alah",
+ "ooui-outline-control-move-up": "Siirrä kohteh yläh",
+ "ooui-outline-control-remove": "Ota kohteh iäre",
+ "ooui-toolbar-more": "Enämbi",
+ "ooui-toolgroup-expand": "Enämbi",
+ "ooui-toolgroup-collapse": "Vähembi",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Hylgiä",
+ "ooui-dialog-process-error": "Mitah haireh rodih",
+ "ooui-dialog-process-dismiss": "Hylgiä",
+ "ooui-dialog-process-retry": "Opi vie",
+ "ooui-dialog-process-continue": "Jatka",
+ "ooui-selectfile-button-select": "Valliče failu",
+ "ooui-selectfile-not-supported": "Failan valličendua ei tuveta",
+ "ooui-selectfile-placeholder": "Failua ei ole vallittu",
+ "ooui-selectfile-dragdrop-placeholder": "Kirvota failu täh"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/om.json b/www/wiki/vendor/oojs/oojs-ui/i18n/om.json
new file mode 100644
index 00000000..31344be7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/om.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cedric31",
+ "Tumsaa"
+ ]
+ },
+ "ooui-outline-control-move-down": "Gad buusi",
+ "ooui-outline-control-move-up": "Ol baasi",
+ "ooui-outline-control-remove": "Balleessi",
+ "ooui-toolbar-more": "Dabalata",
+ "ooui-toolgroup-expand": "Dabalata",
+ "ooui-toolgroup-collapse": "Xiqqaa",
+ "ooui-dialog-message-accept": "Tole",
+ "ooui-dialog-message-reject": "Dhiisi",
+ "ooui-dialog-process-error": "Dogoggorri wayii ummameera",
+ "ooui-dialog-process-dismiss": "Didi",
+ "ooui-dialog-process-retry": "Itti deebi'ii yaali",
+ "ooui-dialog-process-continue": "Itti fufi",
+ "ooui-selectfile-button-select": "Faayilii filadhu",
+ "ooui-selectfile-not-supported": "Faayilii filachuun hin danda'amu.",
+ "ooui-selectfile-placeholder": "Faayiliin wayiiyyuu hin filatamne",
+ "ooui-selectfile-dragdrop-placeholder": "Faayilii as kaa'i"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/or.json b/www/wiki/vendor/oojs/oojs-ui/i18n/or.json
new file mode 100644
index 00000000..7d96dcb7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/or.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Odisha1",
+ "Psubhashish",
+ "ଶିତିକଣ୍ଠ ଦାଶ",
+ "Jnanaranjan Sahu"
+ ]
+ },
+ "ooui-outline-control-move-down": "ବସ୍ତୁଟିକୁ ତଳକୁ ଘୁଞ୍ଚାନ୍ତୁ",
+ "ooui-outline-control-move-up": "ବସ୍ତୁଟିକୁ ଉପରକୁ ଘୁଞ୍ଚାନ୍ତୁ",
+ "ooui-outline-control-remove": "ବସ୍ତୁଟିକୁ ଲିଭାନ୍ତୁ",
+ "ooui-toolbar-more": "ଅଧିକ",
+ "ooui-toolgroup-expand": "ଅଧିକ",
+ "ooui-toolgroup-collapse": "ଅଳ୍ପ",
+ "ooui-dialog-message-accept": "ହେଉ",
+ "ooui-dialog-message-reject": "ନାକଚ",
+ "ooui-dialog-process-error": "ଅସୁବିଧାଟିଏ ଘଟିଲା",
+ "ooui-dialog-process-dismiss": "ଖାରଜ",
+ "ooui-dialog-process-retry": "ଆଉ ଥରେ ଚେଷ୍ଟା କରନ୍ତୁ",
+ "ooui-dialog-process-continue": "ଚାଲୁରଖିବେ",
+ "ooui-selectfile-not-supported": "ଫାଇଲ ବାଛିବା ସୁବିଧା ନାହିଁ",
+ "ooui-selectfile-placeholder": "କୌଣସି ଫାଇଲ ବଛାଯାଇନାହିଁ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/pa.json b/www/wiki/vendor/oojs/oojs-ui/i18n/pa.json
new file mode 100644
index 00000000..a69d76f9
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/pa.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amikeco",
+ "Babanwalia",
+ "Bouron",
+ "Nasir8891",
+ "Satdeep gill"
+ ]
+ },
+ "ooui-outline-control-move-down": "ਨੀਚੇ ਲੈਕੇ ਜਾਓ",
+ "ooui-outline-control-move-up": "ਉੱਤੇ ਲੈਕੇ ਜਾਓ",
+ "ooui-outline-control-remove": "ਆਈਟਮ ਹਟਾਓ",
+ "ooui-toolbar-more": "ਹੋਰ",
+ "ooui-toolgroup-expand": "ਹੋਰ",
+ "ooui-toolgroup-collapse": "ਥੋੜ੍ਹੇ",
+ "ooui-dialog-message-accept": "ਠੀਕ ਹੈ",
+ "ooui-dialog-message-reject": "ਰੱਦ ਕਰੋ",
+ "ooui-dialog-process-error": "ਕੁਝ ਗਲਤ ਹੋ ਗਿਆ",
+ "ooui-dialog-process-dismiss": "ਰੱਦ ਕਰੋ",
+ "ooui-dialog-process-retry": "ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ",
+ "ooui-dialog-process-continue": "ਜਾਰੀ ਰੱਖੋ",
+ "ooui-selectfile-button-select": "ਫ਼ਾਈਲ ਚੁਣੋ",
+ "ooui-selectfile-not-supported": "ਚੁਣੀ ਗਈ ਫ਼ਾਈਲ ਖੋਲੀ ਨਹੀਂ ਜਾ ਸਕਦੀ",
+ "ooui-selectfile-placeholder": "ਕੋਈ ਫ਼ਾਈਲ ਚੁਣੀ ਨਹੀਂ ਗਈ",
+ "ooui-selectfile-dragdrop-placeholder": "ਫ਼ਾਈਲ ਇੱਥੇ ਸਿੱਟੋ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/pfl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/pfl.json
new file mode 100644
index 00000000..02d08426
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/pfl.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Manuae"
+ ]
+ },
+ "ooui-outline-control-move-down": "Bweeschs nunna",
+ "ooui-outline-control-move-up": "Bweeschs nuff",
+ "ooui-outline-control-remove": "Leschs",
+ "ooui-toolbar-more": "Mea",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Abbresche"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/pl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/pl.json
new file mode 100644
index 00000000..eaf0b1a8
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/pl.json
@@ -0,0 +1,40 @@
+{
+ "@metadata": {
+ "authors": [
+ "Babanwalia",
+ "Chrumps",
+ "Matma Rex",
+ "Mikołka",
+ "Nasir8891",
+ "Odie2",
+ "Rzuwig",
+ "Tar Lócesilion",
+ "Ty221",
+ "WTM",
+ "Woytecr",
+ "Wpedzich",
+ "Jacenty359",
+ "Matik7",
+ "Gloria sah",
+ "Andrzej aa",
+ "The Polish"
+ ]
+ },
+ "ooui-outline-control-move-down": "Przesuń w dół",
+ "ooui-outline-control-move-up": "Przesuń w górę",
+ "ooui-outline-control-remove": "Usuń element",
+ "ooui-toolbar-more": "Więcej",
+ "ooui-toolgroup-expand": "Więcej",
+ "ooui-toolgroup-collapse": "Mniej",
+ "ooui-item-remove": "Usuń",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Anuluj",
+ "ooui-dialog-process-error": "Coś poszło nie tak",
+ "ooui-dialog-process-dismiss": "Powrót",
+ "ooui-dialog-process-retry": "Spróbuj ponownie",
+ "ooui-dialog-process-continue": "Kontynuuj",
+ "ooui-selectfile-button-select": "Wybierz plik",
+ "ooui-selectfile-not-supported": "Wybór pliku nie jest obsługiwany",
+ "ooui-selectfile-placeholder": "Nie wybrano pliku",
+ "ooui-selectfile-dragdrop-placeholder": "Upuść plik tutaj"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/pms.json b/www/wiki/vendor/oojs/oojs-ui/i18n/pms.json
new file mode 100644
index 00000000..c8b5bc7e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/pms.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Borichèt",
+ "Dragonòt",
+ "පසිඳු කාවින්ද"
+ ]
+ },
+ "ooui-outline-control-move-down": "Fé calé giù l'element",
+ "ooui-outline-control-move-up": "Fé monté l'element",
+ "ooui-outline-control-remove": "Gavé j'element",
+ "ooui-toolbar-more": "Ëd pi",
+ "ooui-toolgroup-expand": "Pi",
+ "ooui-toolgroup-collapse": "Men",
+ "ooui-dialog-message-accept": "Va bin",
+ "ooui-dialog-message-reject": "Scancelé",
+ "ooui-dialog-process-error": "Quaicòs a l'é andà mal",
+ "ooui-dialog-process-dismiss": "Stërmé",
+ "ooui-dialog-process-retry": "Preuva torna",
+ "ooui-dialog-process-continue": "Continua",
+ "ooui-selectfile-not-supported": "La selession d'archivi a l'é nen mantnùa",
+ "ooui-selectfile-placeholder": "Gnun archivi selessionà"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/pnb.json b/www/wiki/vendor/oojs/oojs-ui/i18n/pnb.json
new file mode 100644
index 00000000..386871c1
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/pnb.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saanvel",
+ "Abbas dhothar"
+ ]
+ },
+ "ooui-outline-control-move-down": "شیہ تھلے کرو",
+ "ooui-outline-control-move-up": "شیہ اتے کرو",
+ "ooui-outline-control-remove": "شیہ مٹاؤ",
+ "ooui-toolbar-more": "ہور",
+ "ooui-toolgroup-expand": "ہور",
+ "ooui-toolgroup-collapse": "گھٹ",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "مکاؤ",
+ "ooui-dialog-process-error": "کوئی رپھڑ پے گیا اے۔",
+ "ooui-dialog-process-dismiss": "مکاؤ",
+ "ooui-dialog-process-retry": "فیر کرو",
+ "ooui-dialog-process-continue": "چلاؤ",
+ "ooui-selectfile-button-select": "فائل چنو",
+ "ooui-selectfile-placeholder": "کوئی فائل نئی چنی ہوئی",
+ "ooui-selectfile-dragdrop-placeholder": "فائل ایتھے پاؤ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ps.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ps.json
new file mode 100644
index 00000000..579740fb
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ps.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ahmed-Najib-Biabani-Ibrahimkhel"
+ ]
+ },
+ "ooui-outline-control-move-down": "توکی ښکته راوړل",
+ "ooui-outline-control-move-up": "توکی پورته راوړل",
+ "ooui-outline-control-remove": "توکی غورځول",
+ "ooui-toolbar-more": "نور",
+ "ooui-toolgroup-expand": "نور",
+ "ooui-toolgroup-collapse": "لږ تر لږ",
+ "ooui-dialog-message-accept": "ښه",
+ "ooui-dialog-message-reject": "ناگارل",
+ "ooui-dialog-process-error": "يوه ستونزه رامنځ ته شوه",
+ "ooui-dialog-process-dismiss": "تړل",
+ "ooui-dialog-process-retry": "بيا هڅه",
+ "ooui-dialog-process-continue": "پرله پورې",
+ "ooui-selectfile-button-select": "يوه دوتنه وټاکئ",
+ "ooui-selectfile-not-supported": "د دوتنې د ټاکنې ملاتړ نه دی شوی",
+ "ooui-selectfile-placeholder": "کومه دوتنه نه ده ټاکل شوې",
+ "ooui-selectfile-dragdrop-placeholder": "دوتنه مو دلته خوشې کړئ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/pt-br.json b/www/wiki/vendor/oojs/oojs-ui/i18n/pt-br.json
new file mode 100644
index 00000000..aa8904ec
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/pt-br.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cainamarques",
+ "Dianakc",
+ "Fúlvio",
+ "Helder.wiki",
+ "HenriqueCrang",
+ "Jaideraf",
+ "Luckas",
+ "OTAVIO1981",
+ 555,
+ "TheEduGobi",
+ "TheGabrielZaum",
+ "Felipe L. Ewald",
+ "Eduardo Addad de Oliveira"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mover item para baixo",
+ "ooui-outline-control-move-up": "Mover item para cima",
+ "ooui-outline-control-remove": "Remover item",
+ "ooui-toolbar-more": "Mais",
+ "ooui-toolgroup-expand": "Mais",
+ "ooui-toolgroup-collapse": "Menos",
+ "ooui-item-remove": "Remover",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancelar",
+ "ooui-dialog-process-error": "Algo deu errado",
+ "ooui-dialog-process-dismiss": "Dispensar",
+ "ooui-dialog-process-retry": "Tente novamente",
+ "ooui-dialog-process-continue": "Continuar",
+ "ooui-selectfile-button-select": "Selecionar um arquivo",
+ "ooui-selectfile-not-supported": "O selecionamento de arquivos não é suportado",
+ "ooui-selectfile-placeholder": "Nenhum arquivo selecionado",
+ "ooui-selectfile-dragdrop-placeholder": "Arraste o arquivo para cá"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/pt.json b/www/wiki/vendor/oojs/oojs-ui/i18n/pt.json
new file mode 100644
index 00000000..246d9c2c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/pt.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cainamarques",
+ "Fúlvio",
+ "GoEThe",
+ "Hamilton Abreu",
+ "Helder.wiki",
+ "Jaideraf",
+ "Jdforrester",
+ "Luckas",
+ "Vitorvicentevalente",
+ "SandroHc",
+ "Jkb8"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mover item para baixo",
+ "ooui-outline-control-move-up": "Mover item para cima",
+ "ooui-outline-control-remove": "Remover elemento",
+ "ooui-toolbar-more": "Mais",
+ "ooui-toolgroup-expand": "Mais",
+ "ooui-toolgroup-collapse": "Menos",
+ "ooui-item-remove": "Remover",
+ "ooui-dialog-message-accept": "Aceitar",
+ "ooui-dialog-message-reject": "Cancelar",
+ "ooui-dialog-process-error": "Algo correu mal",
+ "ooui-dialog-process-dismiss": "Ignorar",
+ "ooui-dialog-process-retry": "Tentar novamente",
+ "ooui-dialog-process-continue": "Continuar",
+ "ooui-selectfile-button-select": "Selecionar ficheiro",
+ "ooui-selectfile-not-supported": "A seleção de ficheiros não é suportada",
+ "ooui-selectfile-placeholder": "Nenhum ficheiro selecionado",
+ "ooui-selectfile-dragdrop-placeholder": "Soltar ficheiro aqui"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/qqq.json b/www/wiki/vendor/oojs/oojs-ui/i18n/qqq.json
new file mode 100644
index 00000000..8ca3afc7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/qqq.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Beta16",
+ "Erik Moeller",
+ "Jdforrester",
+ "Lloffiwr",
+ "Mooeypoo",
+ "Mormegil",
+ "Nike",
+ "PoLuX124",
+ "Purodha",
+ "Raymond",
+ "Sagan",
+ "Sayak Sarkar",
+ "Shirayuki",
+ "Siebrand",
+ "Trevor Parscal",
+ "Liuxinyu970226",
+ "Robby"
+ ]
+ },
+ "ooui-outline-control-move-down": "Tool tip for a button that moves items in a list down one place",
+ "ooui-outline-control-move-up": "Tool tip for a button that moves items in a list up one place",
+ "ooui-outline-control-remove": "Tool tip for a button that removes items from a list.\n{{Identical|Remove item}}",
+ "ooui-toolbar-more": "Label for the toolbar group that contains a list of all other available tools.\n{{Identical|More}}",
+ "ooui-toolgroup-expand": "Label for the fake tool that expands the full list of tools in a toolbar group.\n\nSee also:\n* {{msg-mw|Ooui-toolgroup-collapse}}\n{{Identical|More}}",
+ "ooui-toolgroup-collapse": "Label for the fake tool that collapses the full list of tools in a toolbar group.\n\nSee also:\n* {{msg-mw|Ooui-toolgroup-expand}}\n{{Identical|Fewer}}",
+ "ooui-item-remove": "Text for the action of removing an item\n{{Identical|Remove}}",
+ "ooui-dialog-message-accept": "Default label for the accept button of a message dialog\n{{Identical|OK}}",
+ "ooui-dialog-message-reject": "Default label for the reject button of a message dialog\n{{Identical|Cancel}}",
+ "ooui-dialog-process-error": "Title for process dialog error description",
+ "ooui-dialog-process-dismiss": "Label for process dialog dismiss error button, visible when describing errors\n{{Identical|Dismiss}}",
+ "ooui-dialog-process-retry": "Label for process dialog retry action button, visible when describing recoverable errors\n{{Identical|Try again}}",
+ "ooui-dialog-process-continue": "Label for process dialog retry action button, visible when describing only warnings\n{{Identical|Continue}}",
+ "ooui-selectfile-button-select": "Label for the file selection widget's select file button",
+ "ooui-selectfile-not-supported": "Label for the file selection widget if file selection is not supported",
+ "ooui-selectfile-placeholder": "Label for the file selection widget when no file is currently selected",
+ "ooui-selectfile-dragdrop-placeholder": "Label for the file selection widget's drop target"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/qu.json b/www/wiki/vendor/oojs/oojs-ui/i18n/qu.json
new file mode 100644
index 00000000..cb0b2c33
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/qu.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "AlimanRuna",
+ "Jduranboger"
+ ]
+ },
+ "ooui-outline-control-move-down": "Qallawata uraykuchiy",
+ "ooui-outline-control-move-up": "Qallawata huqariy",
+ "ooui-outline-control-remove": "P'anqa sutikunata qichuy",
+ "ooui-toolbar-more": "Aswan"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ro.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ro.json
new file mode 100644
index 00000000..69daa180
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ro.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "AlimanRuna",
+ "Firilacroco",
+ "Minisarm",
+ "Stelistcristi",
+ "Gloria sah"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mută elementul mai jos",
+ "ooui-outline-control-move-up": "Mută elementul mai sus",
+ "ooui-outline-control-remove": "Elimină elementul",
+ "ooui-toolbar-more": "Mai mult",
+ "ooui-toolgroup-expand": "Mai multe",
+ "ooui-toolgroup-collapse": "Mai puține",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Revocare",
+ "ooui-dialog-process-error": "Ceva nu a funcționat",
+ "ooui-dialog-process-dismiss": "Renunțare",
+ "ooui-dialog-process-retry": "Reîncearcă",
+ "ooui-dialog-process-continue": "Continuă",
+ "ooui-selectfile-button-select": "Alege un fișier",
+ "ooui-selectfile-not-supported": "Selecția de fișiere nu este acceptată",
+ "ooui-selectfile-placeholder": "Niciun fișier selectat",
+ "ooui-selectfile-dragdrop-placeholder": "Trageți fișierul aici"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/roa-tara.json b/www/wiki/vendor/oojs/oojs-ui/i18n/roa-tara.json
new file mode 100644
index 00000000..eac47ec4
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/roa-tara.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joetaras"
+ ]
+ },
+ "ooui-outline-control-move-down": "Spuèste 'a vôsce sotte",
+ "ooui-outline-control-move-up": "Spuèste 'a vôsce sus",
+ "ooui-outline-control-remove": "Live 'a vôsce",
+ "ooui-toolbar-more": "De cchiù",
+ "ooui-toolgroup-expand": "De cchiù",
+ "ooui-toolgroup-collapse": "De mene",
+ "ooui-item-remove": "Live",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Annulle",
+ "ooui-dialog-process-error": "Quacche cose ha sciute stuèrte",
+ "ooui-dialog-process-dismiss": "Scitte",
+ "ooui-dialog-process-retry": "Pruève arrete",
+ "ooui-dialog-process-continue": "Condinue",
+ "ooui-selectfile-button-select": "Scacchie 'nu file",
+ "ooui-selectfile-not-supported": "'U scacchiamende d'u file non g'è supportate",
+ "ooui-selectfile-placeholder": "Nisciune file scacchiate",
+ "ooui-selectfile-dragdrop-placeholder": "Scitte 'u file aqquà"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ru.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ru.json
new file mode 100644
index 00000000..6b22fd88
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ru.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "DR",
+ "Eugrus",
+ "Iluvatar",
+ "KPu3uC B Poccuu",
+ "Kalan",
+ "MaxBioHazard",
+ "NBS",
+ "Niklem",
+ "Okras",
+ "Ole Yves",
+ "Putnik",
+ "Sunpriat",
+ "Yury Katkov",
+ "Умар",
+ "Камалист",
+ "Meshkov.a",
+ "Mailman"
+ ]
+ },
+ "ooui-outline-control-move-down": "Переместить элемент вниз",
+ "ooui-outline-control-move-up": "Переместить элемент вверх",
+ "ooui-outline-control-remove": "Удалить пункт",
+ "ooui-toolbar-more": "Ещё",
+ "ooui-toolgroup-expand": "Больше",
+ "ooui-toolgroup-collapse": "Меньше",
+ "ooui-item-remove": "Удалить",
+ "ooui-dialog-message-accept": "ОК",
+ "ooui-dialog-message-reject": "Отмена",
+ "ooui-dialog-process-error": "Что-то пошло не так",
+ "ooui-dialog-process-dismiss": "Закрыть",
+ "ooui-dialog-process-retry": "Попробовать ещё раз",
+ "ooui-dialog-process-continue": "Продолжить",
+ "ooui-selectfile-button-select": "Выберите файл",
+ "ooui-selectfile-not-supported": "Выбор файла не поддерживается",
+ "ooui-selectfile-placeholder": "Не выбран файл",
+ "ooui-selectfile-dragdrop-placeholder": "Перетащите файл сюда"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sa.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sa.json
new file mode 100644
index 00000000..49f038c7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sa.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "NehalDaveND"
+ ]
+ },
+ "ooui-outline-control-remove": "वस्तु निष्कास्यताम्",
+ "ooui-toolbar-more": "अधिकम्",
+ "ooui-toolgroup-expand": "अधिकम्",
+ "ooui-dialog-message-accept": "अस्तु",
+ "ooui-dialog-message-reject": "निरस्यताम्",
+ "ooui-dialog-process-retry": "पुनः चेष्ट्यताम्",
+ "ooui-dialog-process-continue": "निरन्तरम्"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sah.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sah.json
new file mode 100644
index 00000000..1e4bb555
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sah.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gazeb",
+ "HalanTul"
+ ]
+ },
+ "ooui-outline-control-move-down": "Аллара түһэрэн биэр",
+ "ooui-outline-control-move-up": "Үөһэ таһааран биэр",
+ "ooui-outline-control-remove": "Сот",
+ "ooui-toolbar-more": "Эбии",
+ "ooui-toolgroup-expand": "Эбии",
+ "ooui-toolgroup-collapse": "Кыччат",
+ "ooui-dialog-message-accept": "Сөп",
+ "ooui-dialog-message-reject": "Салҕаама",
+ "ooui-dialog-process-error": "Туга эрэ сатаммата",
+ "ooui-dialog-process-dismiss": "Сап",
+ "ooui-dialog-process-retry": "Хатылаан көр",
+ "ooui-dialog-process-continue": "Салгыы",
+ "ooui-selectfile-button-select": "Билэни тал",
+ "ooui-selectfile-not-supported": "Билэни талыы өйөммөт",
+ "ooui-selectfile-placeholder": "Биир да билэ талыллыбатах",
+ "ooui-selectfile-dragdrop-placeholder": "Билэни манна сыҕарыт"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/scn.json b/www/wiki/vendor/oojs/oojs-ui/i18n/scn.json
new file mode 100644
index 00000000..22a212f9
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/scn.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gazeb",
+ "Gmelfi",
+ "HalanTul",
+ "Gloria sah"
+ ]
+ },
+ "ooui-outline-control-move-down": "Sposta di sutta",
+ "ooui-outline-control-move-up": "Sposta di supra",
+ "ooui-toolbar-more": "Àutri cosi"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sco.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sco.json
new file mode 100644
index 00000000..794d71f7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sco.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "John Reid",
+ "Foxj"
+ ]
+ },
+ "ooui-outline-control-move-down": "Muiv eetem doon",
+ "ooui-outline-control-move-up": "Muiv eetem up",
+ "ooui-outline-control-remove": "Remuiv eetem",
+ "ooui-toolbar-more": "Mair",
+ "ooui-toolgroup-expand": "Mair",
+ "ooui-toolgroup-collapse": "Less",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancel",
+ "ooui-dialog-process-error": "Sommit went wrang",
+ "ooui-dialog-process-dismiss": "Close",
+ "ooui-dialog-process-retry": "Hae aniter gae",
+ "ooui-dialog-process-continue": "Conteena",
+ "ooui-selectfile-not-supported": "Cannae pick ony files",
+ "ooui-selectfile-placeholder": "Nae file selectit"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sd.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sd.json
new file mode 100644
index 00000000..dc14339c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sd.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mehtab ahmed"
+ ]
+ },
+ "ooui-outline-control-move-down": "شيءِ کي هيٺ چوريو",
+ "ooui-outline-control-move-up": "شيءِ کي مٿي چوريو",
+ "ooui-outline-control-remove": "شيءِ هٽايو",
+ "ooui-toolbar-more": "وڌيڪ",
+ "ooui-toolgroup-expand": "وڌيڪ",
+ "ooui-toolgroup-collapse": "گھٽ تر",
+ "ooui-dialog-message-accept": "ٺيڪ",
+ "ooui-dialog-message-reject": "رد",
+ "ooui-dialog-process-error": "ڪا غلطي ٿي",
+ "ooui-dialog-process-dismiss": "برخاست ڪريو",
+ "ooui-dialog-process-retry": "ٻيهر ڪوشش ڪريو",
+ "ooui-dialog-process-continue": "جاري رکو",
+ "ooui-selectfile-button-select": "ڪو فائيل چونڊِو",
+ "ooui-selectfile-not-supported": "فائيل جي چونڊ سپورٽ نٿي ڪئي وڃي",
+ "ooui-selectfile-placeholder": "ڪوبه فائيل چونڊيو نه ويو آهي",
+ "ooui-selectfile-dragdrop-placeholder": "فائيل کي هتي ڪيرايو"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sh.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sh.json
new file mode 100644
index 00000000..532ba3f7
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sh.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "OC Ripper",
+ "Sf"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pomakni stavku dolje",
+ "ooui-outline-control-move-up": "Premjesti stavku gore",
+ "ooui-outline-control-remove": "Ukloni stavku",
+ "ooui-toolbar-more": "Više",
+ "ooui-toolgroup-expand": "Više",
+ "ooui-toolgroup-collapse": "Manje",
+ "ooui-dialog-message-accept": "U redu",
+ "ooui-dialog-message-reject": "Otkaži",
+ "ooui-dialog-process-error": "Nešto je pošlo naopako",
+ "ooui-dialog-process-dismiss": "Odbaci",
+ "ooui-dialog-process-retry": "Pokušajte ponovo",
+ "ooui-dialog-process-continue": "Nastavi",
+ "ooui-selectfile-button-select": "Izaberi datoteku",
+ "ooui-selectfile-not-supported": "Izbor datoteke nije podržan",
+ "ooui-selectfile-placeholder": "Nijedna datoteka nije odabrana",
+ "ooui-selectfile-dragdrop-placeholder": "Prevuci datoteku ovdje"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/shn.json b/www/wiki/vendor/oojs/oojs-ui/i18n/shn.json
new file mode 100644
index 00000000..a93e616a
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/shn.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saimawnkham"
+ ]
+ },
+ "ooui-outline-control-move-down": "ၶၢႆႉလူင်းၽၢႆႇတႂ်ႈ",
+ "ooui-outline-control-move-up": "ၶၢႆႉၶိုၼ်ႈၽၢႆႇၼိူဝ်",
+ "ooui-outline-control-remove": "ထွၼ်ပႅတ်ႈ ဢၼ်ၶဝ်ႈပႃး",
+ "ooui-toolbar-more": "ၼမ်ႉလိူဝ်",
+ "ooui-toolgroup-expand": "ၼမ်လိူဝ်",
+ "ooui-toolgroup-collapse": "ဢေႇလိူဝ်",
+ "ooui-dialog-message-accept": "ဢူဝ်ႇၶေႇ",
+ "ooui-dialog-message-reject": "ဢမ်ႇႁဵတ်း",
+ "ooui-dialog-process-error": "သေဢၼ်ဢၼ်ၽိတ်းပိူင်ႈဝႆႉ",
+ "ooui-dialog-process-dismiss": "လူတ်းၵၢၼ်",
+ "ooui-dialog-process-retry": "ၶတ်းၸႂ်ထႅင်ႈ",
+ "ooui-dialog-process-continue": "သိုပ်ႇၼႃႈ",
+ "ooui-selectfile-button-select": "လိူၵ်ႈၾၢႆႇ",
+ "ooui-selectfile-not-supported": "လွင်ႈလိူၵ်ႈၽၢႆႇၼႆႉ ဢမ်ႇၵမ်ႉထႅမ်ဝႆႉပၼ်",
+ "ooui-selectfile-placeholder": "ဢမ်ႇလႆႈလိူၵ်ႈ ၾၢႆႇသင်ဝႆႉ",
+ "ooui-selectfile-dragdrop-placeholder": "ဢဝ်ၾၢႆႇ သႂ်ႇတီႈၼႆႉ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/si.json b/www/wiki/vendor/oojs/oojs-ui/i18n/si.json
new file mode 100644
index 00000000..5988773b
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/si.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Singhalawap",
+ "පසිඳු කාවින්ද",
+ "ශ්වෙත"
+ ]
+ },
+ "ooui-outline-control-move-down": "අයිතමය පහලටදමන්න",
+ "ooui-outline-control-move-up": "අයිතමය ඉහලටදමන්න"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sk.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sk.json
new file mode 100644
index 00000000..8deb4774
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sk.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mimarik",
+ "Teslaton",
+ "Kusavica",
+ "TomášPolonec"
+ ]
+ },
+ "ooui-outline-control-move-down": "Posunúť položku nadol",
+ "ooui-outline-control-move-up": "Posunúť položku nahor",
+ "ooui-outline-control-remove": "Odstrániť položku",
+ "ooui-toolbar-more": "Viac",
+ "ooui-toolgroup-expand": "Viac",
+ "ooui-toolgroup-collapse": "Menej",
+ "ooui-item-remove": "Odstrániť",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Zrušiť",
+ "ooui-dialog-process-error": "Niečo sa pokazilo",
+ "ooui-dialog-process-dismiss": "Zrušiť",
+ "ooui-dialog-process-retry": "Skúsiť znova",
+ "ooui-dialog-process-continue": "Pokračovať",
+ "ooui-selectfile-button-select": "Vybrať súbor",
+ "ooui-selectfile-not-supported": "Výber súboru nie je podporovaný",
+ "ooui-selectfile-placeholder": "Nie je vybraný žiadny súbor",
+ "ooui-selectfile-dragdrop-placeholder": "Sem umiestni súbor"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/skr-arab.json b/www/wiki/vendor/oojs/oojs-ui/i18n/skr-arab.json
new file mode 100644
index 00000000..1a2af2b0
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/skr-arab.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saraiki"
+ ]
+ },
+ "ooui-toolbar-more": "ٻئے",
+ "ooui-toolgroup-expand": "ٻئے",
+ "ooui-toolgroup-collapse": "گھٹ",
+ "ooui-item-remove": "ہٹاؤ",
+ "ooui-dialog-message-accept": "ٹھیک ہے",
+ "ooui-dialog-message-reject": "منسوخ",
+ "ooui-dialog-process-error": "کجھ خراب تھی ڳئے",
+ "ooui-dialog-process-dismiss": "مکاؤ",
+ "ooui-dialog-process-retry": "ولدا کوشش کرو",
+ "ooui-dialog-process-continue": "جاری رکھو",
+ "ooui-selectfile-button-select": "فائل چݨو",
+ "ooui-selectfile-placeholder": "کوئی فائل کائنی چُݨی"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sl.json
new file mode 100644
index 00000000..8e79e941
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sl.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dbc334",
+ "Eleassar",
+ "Pinky sl",
+ "Yerpo"
+ ]
+ },
+ "ooui-outline-control-move-down": "Prestavi predmet nižje",
+ "ooui-outline-control-move-up": "Prestavi predmet višje",
+ "ooui-outline-control-remove": "Odstrani vnos",
+ "ooui-toolbar-more": "Več",
+ "ooui-toolgroup-expand": "Več",
+ "ooui-toolgroup-collapse": "Manj",
+ "ooui-item-remove": "Odstrani",
+ "ooui-dialog-message-accept": "V redu",
+ "ooui-dialog-message-reject": "Prekliči",
+ "ooui-dialog-process-error": "Nekaj je šlo narobe",
+ "ooui-dialog-process-dismiss": "Skrij",
+ "ooui-dialog-process-retry": "Poskusi znova",
+ "ooui-dialog-process-continue": "Nadaljuj",
+ "ooui-selectfile-button-select": "Izberite datoteko",
+ "ooui-selectfile-not-supported": "Izbira datoteke ni podprta",
+ "ooui-selectfile-placeholder": "Nobena datoteka ni izbrana",
+ "ooui-selectfile-dragdrop-placeholder": "Tukaj spustite datoteko"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sq.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sq.json
new file mode 100644
index 00000000..679f1a6f
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sq.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Euriditi",
+ "Kushtrim",
+ "Elioqoshi",
+ "GretaDoci",
+ "Gertakapllani",
+ "Techlik",
+ "Liridon"
+ ]
+ },
+ "ooui-outline-control-move-down": "Zhvendose artikullin më poshtë",
+ "ooui-outline-control-move-up": "Zhvendose artikullin më lart",
+ "ooui-outline-control-remove": "Hiq artikullin",
+ "ooui-toolbar-more": "Më tepër...",
+ "ooui-toolgroup-expand": "Më tepër...",
+ "ooui-toolgroup-collapse": "Më pak",
+ "ooui-dialog-message-accept": "Në rregull",
+ "ooui-dialog-message-reject": "Anullo",
+ "ooui-dialog-process-error": "Diçka shkoi keq",
+ "ooui-dialog-process-dismiss": "Largoje",
+ "ooui-dialog-process-retry": "Provo përsëri",
+ "ooui-dialog-process-continue": "Vazhdo",
+ "ooui-selectfile-button-select": "Përzgjidhni një skedë",
+ "ooui-selectfile-not-supported": "Skedari i përzgjedhur nuk përkrahet",
+ "ooui-selectfile-placeholder": "Nuk është zgjedhur asnjë skedar",
+ "ooui-selectfile-dragdrop-placeholder": "Vendose skedën këtu"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sr-ec.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sr-ec.json
new file mode 100644
index 00000000..de1ee47f
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sr-ec.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Milicevic01",
+ "Nikola Smolenski",
+ "Милан Јелисавчић",
+ "Zoranzoki21",
+ "Obsuser",
+ "Prevodim"
+ ]
+ },
+ "ooui-outline-control-move-down": "Премести ставку надоле",
+ "ooui-outline-control-move-up": "Премести ставку нагоре",
+ "ooui-outline-control-remove": "Уклони ставку",
+ "ooui-toolbar-more": "Више",
+ "ooui-toolgroup-expand": "Више",
+ "ooui-toolgroup-collapse": "Мање",
+ "ooui-item-remove": "Уклони",
+ "ooui-dialog-message-accept": "У реду",
+ "ooui-dialog-message-reject": "Откажи",
+ "ooui-dialog-process-error": "Нешто је пошло наопако",
+ "ooui-dialog-process-dismiss": "Одбаци",
+ "ooui-dialog-process-retry": "Покушај поново",
+ "ooui-dialog-process-continue": "Настави",
+ "ooui-selectfile-button-select": "Изабери датотеку",
+ "ooui-selectfile-not-supported": "Избор датотеке није подржан",
+ "ooui-selectfile-placeholder": "Није изабрана ниједна датотека",
+ "ooui-selectfile-dragdrop-placeholder": "Превуците датотеку овде"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sr-el.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sr-el.json
new file mode 100644
index 00000000..cd286e80
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sr-el.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Milicevic01",
+ "Prevodim"
+ ]
+ },
+ "ooui-outline-control-move-down": "Premesti stavku na dole",
+ "ooui-outline-control-move-up": "Premesti stavku na gore",
+ "ooui-outline-control-remove": "Ukloni stavku",
+ "ooui-toolbar-more": "Više",
+ "ooui-toolgroup-expand": "Više",
+ "ooui-toolgroup-collapse": "Manje",
+ "ooui-item-remove": "Ukloni",
+ "ooui-dialog-message-accept": "U redu",
+ "ooui-dialog-message-reject": "Otkaži",
+ "ooui-dialog-process-error": "Nešto je pošlo naopako",
+ "ooui-dialog-process-dismiss": "Odbaci",
+ "ooui-dialog-process-retry": "Pokušaj ponovo",
+ "ooui-dialog-process-continue": "Nastavi",
+ "ooui-selectfile-button-select": "Izaberi datoteku",
+ "ooui-selectfile-not-supported": "Odabir datoteke nije podržan",
+ "ooui-selectfile-placeholder": "Nije izabrana nijedna datoteka",
+ "ooui-selectfile-dragdrop-placeholder": "Prevuci datoteku ovde"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/su.json b/www/wiki/vendor/oojs/oojs-ui/i18n/su.json
new file mode 100644
index 00000000..2824d5bd
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/su.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kandar",
+ "Uchup19"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pindahkeun ka handap",
+ "ooui-outline-control-move-up": "Pindahkeun ka luhur",
+ "ooui-outline-control-remove": "Hapus",
+ "ooui-toolbar-more": "Lobaan",
+ "ooui-toolgroup-expand": "Lobaan",
+ "ooui-toolgroup-collapse": "Saeutikan",
+ "ooui-item-remove": "Pupus",
+ "ooui-dialog-message-accept": "Heug",
+ "ooui-dialog-message-reject": "Bolay",
+ "ooui-dialog-process-error": "Aya nu teu bener",
+ "ooui-dialog-process-dismiss": "Tutup",
+ "ooui-dialog-process-retry": "Cobaan deui",
+ "ooui-dialog-process-continue": "Teruskeun",
+ "ooui-selectfile-button-select": "Pilih berkas",
+ "ooui-selectfile-not-supported": "Pamilihan berkas teu dirojong",
+ "ooui-selectfile-placeholder": "Taya berkas anu dipilih",
+ "ooui-selectfile-dragdrop-placeholder": "Leupaskeun berkas di dieu"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sv.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sv.json
new file mode 100644
index 00000000..9ac281ea
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sv.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ainali",
+ "Haxpett",
+ "Jopparn",
+ "Knuckles",
+ "Magol",
+ "Milicevic01",
+ "Per",
+ "Sendelbach",
+ "Skalman",
+ "WikiPhoenix",
+ "Lokal Profil",
+ "Warrakkk",
+ "Bengtsson96"
+ ]
+ },
+ "ooui-outline-control-move-down": "Flytta ned objekt",
+ "ooui-outline-control-move-up": "Flytta upp objekt",
+ "ooui-outline-control-remove": "Ta bort objekt",
+ "ooui-toolbar-more": "Mer",
+ "ooui-toolgroup-expand": "Fler",
+ "ooui-toolgroup-collapse": "Färre",
+ "ooui-item-remove": "Ta bort",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Avbryt",
+ "ooui-dialog-process-error": "Något gick fel",
+ "ooui-dialog-process-dismiss": "Stäng",
+ "ooui-dialog-process-retry": "Försök igen",
+ "ooui-dialog-process-continue": "Fortsätt",
+ "ooui-selectfile-button-select": "Välj en fil",
+ "ooui-selectfile-not-supported": "Filval stöds inte",
+ "ooui-selectfile-placeholder": "Ingen fil är vald",
+ "ooui-selectfile-dragdrop-placeholder": "Släpp filen här"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/sw.json b/www/wiki/vendor/oojs/oojs-ui/i18n/sw.json
new file mode 100644
index 00000000..598acbcd
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/sw.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lloffiwr",
+ "Muddyb Blast Producer",
+ "Muddyb"
+ ]
+ },
+ "ooui-outline-control-move-down": "Sogeza kipengee chini",
+ "ooui-outline-control-move-up": "Sogeza kipengee juu",
+ "ooui-outline-control-remove": "Toa kitu",
+ "ooui-toolbar-more": "Zaidi",
+ "ooui-dialog-message-accept": "Sawa",
+ "ooui-dialog-message-reject": "Batilisha",
+ "ooui-dialog-process-retry": "Jaribu tena"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ta.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ta.json
new file mode 100644
index 00000000..6e7b2494
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ta.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jayarathina",
+ "Sank",
+ "Shanmugamp7",
+ "மதனாஹரன்",
+ "ElangoRamanujam",
+ "Info-farmer"
+ ]
+ },
+ "ooui-outline-control-move-down": "உருப்படியை கீழிடு",
+ "ooui-outline-control-move-up": "உருப்படியை மேலிடு",
+ "ooui-outline-control-remove": "உருப்படியை நீக்கு",
+ "ooui-toolbar-more": "மேலும்",
+ "ooui-toolgroup-expand": "மேலும்",
+ "ooui-toolgroup-collapse": "குறைவாக",
+ "ooui-dialog-message-accept": "சரி",
+ "ooui-dialog-message-reject": "கைவிடுக",
+ "ooui-dialog-process-error": "ஏதோ தவறாகியுள்ளது",
+ "ooui-dialog-process-dismiss": "அகற்று",
+ "ooui-dialog-process-retry": "மீண்டும் முயல்க",
+ "ooui-dialog-process-continue": "தொடரவும்",
+ "ooui-selectfile-not-supported": "கோப்புத்தேர்வு ஆதரவாக இல்லை",
+ "ooui-selectfile-placeholder": "எக்கோப்பும் தெரிவாகவில்லை"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/tay.json b/www/wiki/vendor/oojs/oojs-ui/i18n/tay.json
new file mode 100644
index 00000000..12a6f957
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/tay.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hitaypayan",
+ "Translatealcd"
+ ]
+ },
+ "ooui-outline-control-move-down": "Hz’aniy tay mkyahu’ quw binkgan lmlamu’",
+ "ooui-outline-control-move-up": "Hz’aniy tay mkraya’ quw binkgan lmlamu’",
+ "ooui-outline-control-remove": "Laxiy quw pin’ubuy binkgan lmlamu",
+ "ooui-toolbar-more": "Pzyux na’",
+ "ooui-toolgroup-collapse": "Cikuy hazi’",
+ "ooui-item-remove": "Laxan",
+ "ooui-dialog-message-accept": "Wal balay",
+ "ooui-dialog-message-reject": "Laxan",
+ "ooui-dialog-process-dismiss": "Ql’iy",
+ "ooui-dialog-process-retry": "Tlamiy lawziy",
+ "ooui-dialog-process-continue": "Siy lhingiy",
+ "ooui-selectfile-placeholder": "Ini’ wzyagiy na’ Tang’an"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/te.json b/www/wiki/vendor/oojs/oojs-ui/i18n/te.json
new file mode 100644
index 00000000..3e88da53
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/te.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arjunaraoc",
+ "Jayarathina",
+ "Sank",
+ "Shanmugamp7",
+ "Veeven",
+ "Visdaviva",
+ "மதனாஹரன்",
+ "రహ్మానుద్దీన్"
+ ]
+ },
+ "ooui-outline-control-move-down": "అంశాన్ని కిందికి కదుపు",
+ "ooui-outline-control-move-up": "అంశాన్ని పైకి కదుపు",
+ "ooui-outline-control-remove": "అంశాన్ని తీసివేయి",
+ "ooui-toolbar-more": "మరిన్ని",
+ "ooui-toolgroup-expand": "మరిన్ని",
+ "ooui-toolgroup-collapse": "కొన్ని",
+ "ooui-item-remove": "తొలగించు",
+ "ooui-dialog-message-accept": "సరే",
+ "ooui-dialog-message-reject": "రద్దుచేయి",
+ "ooui-dialog-process-error": "ఏదో పొరపాటు జరిగింది",
+ "ooui-dialog-process-dismiss": "రద్దుచేయి",
+ "ooui-dialog-process-retry": "మళ్ళీ ప్రయత్నించు",
+ "ooui-dialog-process-continue": "కొనసాగించు",
+ "ooui-selectfile-button-select": "దస్త్రాన్ని ఎంచుకో",
+ "ooui-selectfile-not-supported": "దస్త్రపు ఎంపిక అందుబాటులో లేదు",
+ "ooui-selectfile-placeholder": "ఏ దస్త్రము ఎంపిక చేయలేదు",
+ "ooui-selectfile-dragdrop-placeholder": "దస్త్రాన్ని ఇక్కడ పడేయండి"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/tg-cyrl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/tg-cyrl.json
new file mode 100644
index 00000000..1429bedd
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/tg-cyrl.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ibrahim"
+ ]
+ },
+ "ooui-outline-control-move-down": "Ҳаракати мавод ба поён",
+ "ooui-outline-control-move-up": "Ҳаракати мавод ба боло",
+ "ooui-outline-control-remove": "Ҳазви мавод",
+ "ooui-toolbar-more": "Бештар"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/th.json b/www/wiki/vendor/oojs/oojs-ui/i18n/th.json
new file mode 100644
index 00000000..94527935
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/th.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Supasate",
+ "Taweetham"
+ ]
+ },
+ "ooui-outline-control-move-down": "เลื่อนรายการลง",
+ "ooui-outline-control-move-up": "ย้ายรายการขึ้น"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/tl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/tl.json
new file mode 100644
index 00000000..c0dbd5fd
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/tl.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "AnakngAraw",
+ "Sky Harbor",
+ "Jewel457"
+ ]
+ },
+ "ooui-outline-control-move-down": "Ilipat ang aytem pababa",
+ "ooui-outline-control-move-up": "Ilipat ang aytem pataas",
+ "ooui-outline-control-remove": "Tanggalin ang aytem",
+ "ooui-toolbar-more": "Marami pa",
+ "ooui-toolgroup-expand": "Maraming iba pa",
+ "ooui-toolgroup-collapse": "Kakaunti",
+ "ooui-dialog-message-accept": "Sige",
+ "ooui-dialog-message-reject": "Huwag ituloy",
+ "ooui-dialog-process-error": "May pagkakamali",
+ "ooui-dialog-process-dismiss": "Isa-isantabi",
+ "ooui-dialog-process-retry": "Subuking muli",
+ "ooui-dialog-process-continue": "Magpatuloy",
+ "ooui-selectfile-not-supported": "Ang pagpili ng file ay hindi kinakatigan",
+ "ooui-selectfile-placeholder": "Walang piniling file"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/tr.json b/www/wiki/vendor/oojs/oojs-ui/i18n/tr.json
new file mode 100644
index 00000000..9b88695a
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/tr.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Emperyan",
+ "Incelemeelemani",
+ "LuCKY",
+ "Maidis",
+ "Rapsar",
+ "Talha Samil Cakir",
+ "TurkishStyles",
+ "Sayginer",
+ "Meelo",
+ "McAang",
+ "Uğurkent",
+ "1917 Ekim Devrimi"
+ ]
+ },
+ "ooui-outline-control-move-down": "Ögeyi aşağı taşı",
+ "ooui-outline-control-move-up": "Ögeyi yukarı taşı",
+ "ooui-outline-control-remove": "Ögeyi kaldır",
+ "ooui-toolbar-more": "Dahası",
+ "ooui-toolgroup-expand": "Dahası",
+ "ooui-toolgroup-collapse": "Daha az",
+ "ooui-dialog-message-accept": "Tamam",
+ "ooui-dialog-message-reject": "İptal",
+ "ooui-dialog-process-error": "Bir şeyler yanlış gitti",
+ "ooui-dialog-process-dismiss": "Kapat",
+ "ooui-dialog-process-retry": "Tekrar dene",
+ "ooui-dialog-process-continue": "Devam et",
+ "ooui-selectfile-button-select": "Dosya seç",
+ "ooui-selectfile-not-supported": "Dosya seçimi desteklenmiyor",
+ "ooui-selectfile-placeholder": "Herhangi bir dosya seçilmedi",
+ "ooui-selectfile-dragdrop-placeholder": "Dosyayı buraya aç"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/tt-cyrl.json b/www/wiki/vendor/oojs/oojs-ui/i18n/tt-cyrl.json
new file mode 100644
index 00000000..335e509e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/tt-cyrl.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ajdar",
+ "Ильнар"
+ ]
+ },
+ "ooui-outline-control-move-down": "Элементны аска күчерү",
+ "ooui-outline-control-move-up": "Элементны өскә күчерү",
+ "ooui-outline-control-remove": "Пунктны бетерү",
+ "ooui-toolbar-more": "Тагын",
+ "ooui-toolgroup-expand": "Күбрәк",
+ "ooui-toolgroup-collapse": "Азрак",
+ "ooui-dialog-message-accept": "ОК",
+ "ooui-dialog-message-reject": "Баш тарту",
+ "ooui-dialog-process-error": "Нәрсәдер килеп чыкмады",
+ "ooui-dialog-process-dismiss": "Ябу",
+ "ooui-dialog-process-retry": "Кабатлау",
+ "ooui-dialog-process-continue": "Дәвам итү",
+ "ooui-selectfile-button-select": "Файлны сайлагыз",
+ "ooui-selectfile-not-supported": "Файл сайлау хупланмый",
+ "ooui-selectfile-placeholder": "Файл сайланмаган",
+ "ooui-selectfile-dragdrop-placeholder": "Файлны монда куегыз"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ug-arab.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ug-arab.json
new file mode 100644
index 00000000..b19dd0d3
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ug-arab.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sahran",
+ "Tel'et",
+ "Tifinaghes"
+ ]
+ },
+ "ooui-outline-control-move-down": "تۆۋەنگە يۆتكە",
+ "ooui-outline-control-move-up": "يۇقۇرىغا يۆتكە",
+ "ooui-outline-control-remove": "ئۆچۈر",
+ "ooui-toolbar-more": "تېخىمۇ كۆپ",
+ "ooui-toolgroup-expand": "تېخىمۇ كۆپ",
+ "ooui-toolgroup-collapse": "ئاز",
+ "ooui-item-remove": "چىقىرىۋەت",
+ "ooui-dialog-message-accept": "تامام",
+ "ooui-dialog-message-reject": "ۋاز كەچ",
+ "ooui-dialog-process-error": "نامەلۇم خاتالىق كۆرۈلدى",
+ "ooui-dialog-process-dismiss": "چىقىرىۋەت",
+ "ooui-dialog-process-retry": "قايتا سىنا",
+ "ooui-dialog-process-continue": "داۋاملاشتۇر",
+ "ooui-selectfile-button-select": "بىر ھۆججەت تاللا",
+ "ooui-selectfile-not-supported": "تاللانغان ھۆججەتتە مەسىلە بار",
+ "ooui-selectfile-placeholder": "ھۆججەت تاللانمىدى",
+ "ooui-selectfile-dragdrop-placeholder": "ھۆججەتنى بۇ يەرگە تاشلاڭ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/uk.json b/www/wiki/vendor/oojs/oojs-ui/i18n/uk.json
new file mode 100644
index 00000000..55fec13a
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/uk.json
@@ -0,0 +1,40 @@
+{
+ "@metadata": {
+ "authors": [
+ "AS",
+ "Aced",
+ "Ahonc",
+ "Andriykopanytsia",
+ "Base",
+ "Perohanych",
+ "RLuts",
+ "Sahran",
+ "Sergento",
+ "Steve.rusyn",
+ "SteveR",
+ "Tel'et",
+ "Tifinaghes",
+ "Ата",
+ "Piramidion",
+ "A1",
+ "Dars"
+ ]
+ },
+ "ooui-outline-control-move-down": "Перемістити елемент униз",
+ "ooui-outline-control-move-up": "Перемістити елемент вгору",
+ "ooui-outline-control-remove": "Видалити елемент",
+ "ooui-toolbar-more": "Більше",
+ "ooui-toolgroup-expand": "Більше",
+ "ooui-toolgroup-collapse": "Менше",
+ "ooui-item-remove": "Вилучити",
+ "ooui-dialog-message-accept": "Готово",
+ "ooui-dialog-message-reject": "Скасувати",
+ "ooui-dialog-process-error": "Щось пішло не так",
+ "ooui-dialog-process-dismiss": "Приховати",
+ "ooui-dialog-process-retry": "Спробуйте ще раз",
+ "ooui-dialog-process-continue": "Продовжити",
+ "ooui-selectfile-button-select": "Оберіть файл",
+ "ooui-selectfile-not-supported": "Вибір файлу не підтримується",
+ "ooui-selectfile-placeholder": "Жодного файлу не вибрано",
+ "ooui-selectfile-dragdrop-placeholder": "Помістіть файл сюди"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/ur.json b/www/wiki/vendor/oojs/oojs-ui/i18n/ur.json
new file mode 100644
index 00000000..fcf9b1f4
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/ur.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Muhammad Shuaib",
+ "Zainab Meher",
+ "BukhariSaeed"
+ ]
+ },
+ "ooui-outline-control-move-down": "مد نیچے کھسکائیں",
+ "ooui-outline-control-move-up": " مداوپرلےجائیں",
+ "ooui-outline-control-remove": " مدحذف کریں",
+ "ooui-toolbar-more": "مزید",
+ "ooui-toolgroup-expand": "مزید",
+ "ooui-toolgroup-collapse": "کم کریں",
+ "ooui-item-remove": "ھٹادیں",
+ "ooui-dialog-message-accept": "ٹھیک",
+ "ooui-dialog-message-reject": "منسوخ کریں",
+ "ooui-dialog-process-error": "کچھ غلط ہو گیا ہے",
+ "ooui-dialog-process-dismiss": "موقوف کریں",
+ "ooui-dialog-process-retry": "دوبارہ کوشش کریں",
+ "ooui-dialog-process-continue": "جاری رکھیں",
+ "ooui-selectfile-button-select": "فائل منتخب کریں",
+ "ooui-selectfile-not-supported": "فائل کا انتخاب معاونت شدہ نہیں",
+ "ooui-selectfile-placeholder": "کوئی فائل منتخب نہیں کی گئ",
+ "ooui-selectfile-dragdrop-placeholder": "فائل یہاں چھوڑیں"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/uz.json b/www/wiki/vendor/oojs/oojs-ui/i18n/uz.json
new file mode 100644
index 00000000..7c6263e4
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/uz.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "CoderSI",
+ "Noor2020",
+ "Sociologist",
+ "පසිඳු කාවින්ද"
+ ]
+ },
+ "ooui-outline-control-move-down": "Elementni pastga koʻchirish",
+ "ooui-outline-control-move-up": "Elementni yuqoriga koʻchirish",
+ "ooui-toolbar-more": "Yana"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/vec.json b/www/wiki/vendor/oojs/oojs-ui/i18n/vec.json
new file mode 100644
index 00000000..ddd27c5e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/vec.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Candalua",
+ "GatoSelvadego",
+ "Gloria sah"
+ ]
+ },
+ "ooui-outline-control-move-down": "Sposta in baso",
+ "ooui-outline-control-move-up": "Sposta in sima",
+ "ooui-toolbar-more": "Altro",
+ "ooui-toolgroup-expand": "Piassè",
+ "ooui-toolgroup-collapse": "Manco",
+ "ooui-dialog-message-accept": "Va ben",
+ "ooui-dialog-message-reject": "Fa gnente",
+ "ooui-dialog-process-error": "Xe 'ndà storto calcossa",
+ "ooui-dialog-process-dismiss": "Scondi",
+ "ooui-dialog-process-retry": "Proa da novo",
+ "ooui-dialog-process-continue": "Và vanti",
+ "ooui-selectfile-button-select": "Siegli un file",
+ "ooui-selectfile-dragdrop-placeholder": "Mola zo el file chì rento"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/vep.json b/www/wiki/vendor/oojs/oojs-ui/i18n/vep.json
new file mode 100644
index 00000000..b6ad0929
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/vep.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sebranik"
+ ]
+ },
+ "ooui-toolgroup-expand": "Enamba"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/vi.json b/www/wiki/vendor/oojs/oojs-ui/i18n/vi.json
new file mode 100644
index 00000000..b2714034
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/vi.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cheers!",
+ "Jdforrester",
+ "Minh Nguyen",
+ "Max20091",
+ "Anh88"
+ ]
+ },
+ "ooui-outline-control-move-down": "Chuyển mục xuống",
+ "ooui-outline-control-move-up": "Chuyển mục lên",
+ "ooui-outline-control-remove": "Xóa mục",
+ "ooui-toolbar-more": "Thêm",
+ "ooui-toolgroup-expand": "Mở rộng",
+ "ooui-toolgroup-collapse": "Rút gọn",
+ "ooui-item-remove": "Loại bỏ",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Hủy bỏ",
+ "ooui-dialog-process-error": "Có thứ gì đó bị lỗi",
+ "ooui-dialog-process-dismiss": "Bỏ qua",
+ "ooui-dialog-process-retry": "Thử lại",
+ "ooui-dialog-process-continue": "Tiếp tục",
+ "ooui-selectfile-button-select": "Chọn tập tin",
+ "ooui-selectfile-not-supported": "Không hỗ trợ việc chọn tập tin",
+ "ooui-selectfile-placeholder": "Không có tập tin nào được chọn",
+ "ooui-selectfile-dragdrop-placeholder": "Thả tập tin vào đây"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/vo.json b/www/wiki/vendor/oojs/oojs-ui/i18n/vo.json
new file mode 100644
index 00000000..3510ca93
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/vo.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Malafaya"
+ ]
+ },
+ "ooui-toolbar-more": "Pluikos"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/war.json b/www/wiki/vendor/oojs/oojs-ui/i18n/war.json
new file mode 100644
index 00000000..b0ea30ca
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/war.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "JinJian"
+ ]
+ },
+ "ooui-outline-control-move-down": "Ibalhin paubos",
+ "ooui-outline-control-move-up": "Ibalhin paigbaw",
+ "ooui-outline-control-remove": "Tanggala",
+ "ooui-toolbar-more": "Damo pa",
+ "ooui-toolgroup-expand": "Damo pa",
+ "ooui-toolgroup-collapse": "Guruguti",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Igpabaliwaray",
+ "ooui-dialog-process-error": "Mayda sayop nga nahitabo",
+ "ooui-dialog-process-retry": "Utroha",
+ "ooui-dialog-process-continue": "Padayon",
+ "ooui-selectfile-button-select": "Pagpili hin file"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/wuu.json b/www/wiki/vendor/oojs/oojs-ui/i18n/wuu.json
new file mode 100644
index 00000000..64816249
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/wuu.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Malafaya",
+ "十弌",
+ "飞舞回堂前"
+ ]
+ },
+ "ooui-toolbar-more": "更多"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/xmf.json b/www/wiki/vendor/oojs/oojs-ui/i18n/xmf.json
new file mode 100644
index 00000000..4109c36e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/xmf.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "David1010",
+ "Silovan"
+ ]
+ },
+ "ooui-outline-control-move-down": "ელემენტის ქვემოთ გადატანა",
+ "ooui-outline-control-move-up": "ელემენტის ზემოთ გადატანა",
+ "ooui-outline-control-remove": "ელემენტის წაშლა",
+ "ooui-toolbar-more": "უმოსი",
+ "ooui-toolgroup-expand": "უმოსი",
+ "ooui-toolgroup-collapse": "რამდენიმე",
+ "ooui-dialog-message-accept": "ჯგირი",
+ "ooui-dialog-message-reject": "გოუქვაფა",
+ "ooui-dialog-process-error": "მოხდა რაღაც შეცდომა",
+ "ooui-dialog-process-dismiss": "დამალვა",
+ "ooui-dialog-process-retry": "კიდევ სცადეთ",
+ "ooui-dialog-process-continue": "გაგრძელება",
+ "ooui-selectfile-button-select": "გეგშაგორით ფაილი",
+ "ooui-selectfile-not-supported": "ფაილიშ აშაგორუა ვა რე ხენწყილი",
+ "ooui-selectfile-placeholder": "ფაილი ვა რე გიშაგორილი",
+ "ooui-selectfile-dragdrop-placeholder": "ქინაჸათით ფაილი ათაქ"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/yi.json b/www/wiki/vendor/oojs/oojs-ui/i18n/yi.json
new file mode 100644
index 00000000..84048e7c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/yi.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Malafaya",
+ "פוילישער",
+ "十弌"
+ ]
+ },
+ "ooui-outline-control-move-down": "רוקן עלעמענט אראפ",
+ "ooui-outline-control-move-up": "רוקן עלעמענט ארויף",
+ "ooui-outline-control-remove": "אַראָפנעמען איינס",
+ "ooui-toolbar-more": "נאך",
+ "ooui-toolgroup-expand": "נאך",
+ "ooui-toolgroup-collapse": "ווייניגער",
+ "ooui-dialog-message-accept": "יאָ",
+ "ooui-dialog-message-reject": "אַנולירן",
+ "ooui-dialog-process-error": "עפעס איז דורכגעפאלן",
+ "ooui-dialog-process-dismiss": "צומאַכן",
+ "ooui-dialog-process-retry": "פרובירט נאכאמאל",
+ "ooui-dialog-process-continue": "פֿארזעצן",
+ "ooui-selectfile-button-select": "קלויבט א טעקע",
+ "ooui-selectfile-not-supported": "טעקע אויסווייל נישט געשטיצט",
+ "ooui-selectfile-placeholder": "קיין טעקע נישט אויסגעוויילט"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/yo.json b/www/wiki/vendor/oojs/oojs-ui/i18n/yo.json
new file mode 100644
index 00000000..d979fc13
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/yo.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Demmy"
+ ]
+ },
+ "ooui-outline-control-move-down": "Sún onítòún sí sàlẹ̀",
+ "ooui-outline-control-move-up": "Sún onítòún s'ókè",
+ "ooui-toolbar-more": "Míràn"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/yue.json b/www/wiki/vendor/oojs/oojs-ui/i18n/yue.json
new file mode 100644
index 00000000..6a9e902b
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/yue.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Deryck Chan",
+ "William915",
+ "Shinjiman",
+ "Ktchankt",
+ "Hello903hello"
+ ]
+ },
+ "ooui-outline-control-move-down": "向下搬",
+ "ooui-outline-control-move-up": "向上搬",
+ "ooui-outline-control-remove": "拎走",
+ "ooui-toolbar-more": "更多",
+ "ooui-toolgroup-expand": "更多",
+ "ooui-toolgroup-collapse": "少啲",
+ "ooui-dialog-message-accept": "好",
+ "ooui-dialog-message-reject": "取消",
+ "ooui-dialog-process-error": "唔對路",
+ "ooui-dialog-process-dismiss": "閂咗佢",
+ "ooui-dialog-process-retry": "再試過",
+ "ooui-dialog-process-continue": "繼續",
+ "ooui-selectfile-button-select": "揀檔案",
+ "ooui-selectfile-not-supported": "未有文件選擇功能",
+ "ooui-selectfile-placeholder": "無揀到文件",
+ "ooui-selectfile-dragdrop-placeholder": "放檔案響度"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/zh-hans.json b/www/wiki/vendor/oojs/oojs-ui/i18n/zh-hans.json
new file mode 100644
index 00000000..a3e637d6
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/zh-hans.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia",
+ "Bencmq",
+ "Demmy",
+ "Hydra",
+ "Hzy980512",
+ "Liangent",
+ "Liuxinyu970226",
+ "Qiyue2001",
+ "Shirayuki",
+ "Shizhao",
+ "TianyinLee",
+ "Xiaomingyan",
+ "Yfdyh000",
+ "Zhangjintao",
+ "乌拉跨氪",
+ "Great Brightstar",
+ "Nbdd0121",
+ "Yejianfei"
+ ]
+ },
+ "ooui-outline-control-move-down": "向下移动一项",
+ "ooui-outline-control-move-up": "向上移动一项",
+ "ooui-outline-control-remove": "移除项目",
+ "ooui-toolbar-more": "更多",
+ "ooui-toolgroup-expand": "更多",
+ "ooui-toolgroup-collapse": "更少",
+ "ooui-item-remove": "移除",
+ "ooui-dialog-message-accept": "确定",
+ "ooui-dialog-message-reject": "取消",
+ "ooui-dialog-process-error": "发生了一些错误",
+ "ooui-dialog-process-dismiss": "关闭",
+ "ooui-dialog-process-retry": "重试",
+ "ooui-dialog-process-continue": "继续",
+ "ooui-selectfile-button-select": "选择一个文件",
+ "ooui-selectfile-not-supported": "不支持文件选择器",
+ "ooui-selectfile-placeholder": "没有选定文件",
+ "ooui-selectfile-dragdrop-placeholder": "将文件拖动至此"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/i18n/zh-hant.json b/www/wiki/vendor/oojs/oojs-ui/i18n/zh-hant.json
new file mode 100644
index 00000000..127f483f
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/i18n/zh-hant.json
@@ -0,0 +1,39 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia",
+ "Ch.Andrew",
+ "Hydra",
+ "Justincheng12345",
+ "Liflon",
+ "Liuxinyu970226",
+ "Qiyue2001",
+ "Radish10cm",
+ "Shirayuki",
+ "Simon Shek",
+ "Spring Roll Conan",
+ "Waihorace",
+ "Cwlin0416",
+ "LNDDYL",
+ "Shangkuanlc",
+ "A2093064"
+ ]
+ },
+ "ooui-outline-control-move-down": "項目下移",
+ "ooui-outline-control-move-up": "項目上移",
+ "ooui-outline-control-remove": "移除項目",
+ "ooui-toolbar-more": "更多",
+ "ooui-toolgroup-expand": "更多",
+ "ooui-toolgroup-collapse": "更少",
+ "ooui-item-remove": "移除",
+ "ooui-dialog-message-accept": "確定",
+ "ooui-dialog-message-reject": "取消",
+ "ooui-dialog-process-error": "發生不明錯誤",
+ "ooui-dialog-process-dismiss": "關閉",
+ "ooui-dialog-process-retry": "再試一次",
+ "ooui-dialog-process-continue": "繼續",
+ "ooui-selectfile-button-select": "選擇一個檔案",
+ "ooui-selectfile-not-supported": "無法支援所選擇的檔案",
+ "ooui-selectfile-placeholder": "尚未選擇檔案",
+ "ooui-selectfile-dragdrop-placeholder": "拖曳檔案到此處"
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/Element.php b/www/wiki/vendor/oojs/oojs-ui/php/Element.php
new file mode 100644
index 00000000..c46861f5
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/Element.php
@@ -0,0 +1,304 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * DOM element abstraction.
+ *
+ * @abstract
+ */
+class Element extends Tag {
+
+ /* Static Properties */
+
+ /**
+ * HTML tag name.
+ *
+ * This may be ignored if getTagName() is overridden.
+ *
+ * @var string
+ */
+ public static $tagName = 'div';
+
+ /**
+ * Default text direction, used for some layout calculations. Use setDefaultDir() to change.
+ *
+ * Currently only per-document directionality is supported.
+ *
+ * @var string
+ */
+ public static $defaultDir = 'ltr';
+
+ /* Properties */
+
+ /**
+ * Element data.
+ *
+ * @var mixed
+ */
+ protected $data = null;
+
+ /**
+ * Strings of the CSS classes explicitly configured for this element (as opposed to #$classes,
+ * which contains all classes for this element).
+ *
+ * @var array
+ */
+ protected $ownClasses = [];
+
+ /**
+ * @var callable[]
+ */
+ protected $configCallbacks = [];
+
+ /* Static methods */
+
+ /**
+ * Emits a deprecation warning with provided message.
+ *
+ * @param string $message Message about the deprecation
+ */
+ public static function warnDeprecation( $message = '' ) {
+ trigger_error( $message, E_USER_DEPRECATED );
+ }
+
+ /* Methods */
+
+ /**
+ * @param array $config Configuration options
+ * @param string[] $config['classes'] CSS class names to add
+ * @param string $config['id'] HTML id attribute
+ * @param string $config['text'] Text to insert
+ * @param array $config['content'] Content to append (after text), strings
+ * or Element objects. Strings will be HTML-escaped for output, use an
+ * HtmlSnippet instance to prevent that.
+ * @param mixed $config['data'] Element data
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $this->getTagName() );
+
+ // Initialization
+ if ( isset( $config['infusable'] ) && is_bool( $config['infusable'] ) ) {
+ $this->setInfusable( $config['infusable'] );
+ }
+ if ( isset( $config['data'] ) ) {
+ $this->setData( $config['data'] );
+ }
+ if ( isset( $config['classes'] ) && is_array( $config['classes'] ) ) {
+ $this->ownClasses = $config['classes'];
+ $this->addClasses( $this->ownClasses );
+ }
+ if ( isset( $config['id'] ) ) {
+ $this->setAttributes( [ 'id' => $config['id'] ] );
+ }
+ if ( isset( $config['text'] ) ) {
+ // JS compatibility
+ $this->appendContent( $config['text'] );
+ }
+ if ( isset( $config['content'] ) ) {
+ $this->appendContent( $config['content'] );
+ }
+ }
+
+ /**
+ * Get the HTML tag name.
+ *
+ * Override this method to base the result on instance information.
+ *
+ * @return string HTML tag name
+ */
+ public function getTagName() {
+ return $this::$tagName;
+ }
+
+ /**
+ * Get element data.
+ *
+ * @return mixed Element data
+ */
+ public function getData() {
+ return $this->data;
+ }
+
+ /**
+ * Set element data.
+ *
+ * @param mixed $data Element data
+ * @return $this
+ */
+ public function setData( $data ) {
+ $this->data = $data;
+ return $this;
+ }
+
+ /**
+ * Check if element supports one or more methods.
+ *
+ * @param string|string[] $methods Method or list of methods to check
+ * @return bool All methods are supported
+ */
+ public function supports( $methods ) {
+ $support = 0;
+ $methods = (array)$methods;
+
+ foreach ( $methods as $method ) {
+ if ( method_exists( $this, $method ) ) {
+ $support++;
+ continue;
+ }
+ }
+
+ return count( $methods ) === $support;
+ }
+
+ /**
+ * Register an additional function to call when building the config. See ::getConfig().
+ *
+ * @param callable $func The function. Parameters and return value are the same as ::getConfig().
+ */
+ public function registerConfigCallback( callable $func ) {
+ $this->configCallbacks[] = $func;
+ }
+
+ /**
+ * Add the necessary properties to the given `$config` array to allow
+ * reconstruction of this widget via its constructor.
+ * @param array &$config An array which will be mutated to add the necessary configuration
+ * properties. Unless you are implementing a subclass, you should
+ * always pass a new empty array `[]`.
+ * @return array A configuration array which can be passed to this object's
+ * constructor to recreate it. This is a return value to allow
+ * the safe use of copy-by-value functions like `array_merge` in
+ * the implementation.
+ */
+ public function getConfig( &$config ) {
+ // If there are traits, add their config
+ foreach ( $this->configCallbacks as $func ) {
+ call_user_func_array( $func, [ &$config ] );
+ }
+
+ if ( $this->data !== null ) {
+ $config['data'] = $this->data;
+ }
+ if ( $this->ownClasses !== [] ) {
+ $config['classes'] = $this->ownClasses;
+ }
+ return $config;
+ }
+
+ /**
+ * Create a modified version of the configuration array suitable for
+ * JSON serialization by replacing `Tag` references and
+ * `HtmlSnippet`s.
+ *
+ * @return array A serialized configuration array.
+ */
+ private function getSerializedConfig() {
+ // Ensure that '_' comes first in the output.
+ $config = [ '_' => true ];
+ $config = $this->getConfig( $config );
+ // Post-process config array to turn Tag references into ID references
+ // and HtmlSnippet references into a { html: 'string' } JSON form.
+ $replaceElements = function ( &$item ) {
+ if ( $item instanceof Tag ) {
+ $item->ensureInfusableId();
+ $item = [ 'tag' => $item->getAttribute( 'id' ) ];
+ } elseif ( $item instanceof HtmlSnippet ) {
+ $item = [ 'html' => (string)$item ];
+ }
+ };
+ array_walk_recursive( $config, $replaceElements );
+ // Set '_' last to ensure that subclasses can't accidentally step on it.
+ $config['_'] = $this->getJavaScriptClassName();
+ return $config;
+ }
+
+ /**
+ * The class name of the JavaScript version of this widget
+ * @return string
+ */
+ protected function getJavaScriptClassName() {
+ return str_replace( 'OOUI\\', 'OO.ui.', get_class( $this ) );
+ }
+
+ protected function getGeneratedAttributes() {
+ $attributesArray = parent::getGeneratedAttributes();
+ // Add `data-ooui` attribute from serialized config array.
+ if ( $this->infusable ) {
+ $serialized = $this->getSerializedConfig();
+ $attributesArray['data-ooui'] = json_encode( $serialized );
+ }
+ return $attributesArray;
+ }
+
+ /**
+ * Render element into HTML.
+ *
+ * @return string HTML serialization
+ */
+ public function toString() {
+ Theme::singleton()->updateElementClasses( $this );
+ if ( $this->isInfusable() ) {
+ $this->ensureInfusableId();
+ }
+ return parent::toString();
+ }
+
+ /**
+ * Get the direction of the user interface for a given element.
+ *
+ * Currently only per-document directionality is supported.
+ *
+ * @param Tag $element Element to check
+ * @return string Text direction, either 'ltr' or 'rtl'
+ */
+ public static function getDir( Tag $element ) {
+ return self::$defaultDir;
+ }
+
+ /**
+ * Set the default direction of the user interface.
+ *
+ * @param string $dir Text direction, either 'ltr' or 'rtl'
+ */
+ public static function setDefaultDir( $dir ) {
+ self::$defaultDir = $dir === 'rtl' ? 'rtl' : 'ltr';
+ }
+
+ /**
+ * A helper method to massage an array of HTML attributes into a format that is more likely to
+ * work with an OOUI PHP element, camel-casing attribute names and setting values of boolean
+ * ones to true. Intended as a convenience to be used when refactoring legacy systems using HTML
+ * to use OOUI.
+ *
+ * @param array $attrs HTML attributes, e.g. `[ 'disabled' => '', 'accesskey' => 'k' ]`
+ * @return array OOUI PHP element config, e.g. `[ 'disabled' => true, 'accessKey' => 'k' ]`
+ */
+ public static function configFromHtmlAttributes( array $attrs ) {
+ $booleanAttrs = [
+ 'disabled' => true,
+ 'required' => true,
+ 'autofocus' => true,
+ 'multiple' => true,
+ 'readonly' => true,
+ ];
+ $attributeToConfig = [
+ 'maxlength' => 'maxLength',
+ 'readonly' => 'readOnly',
+ 'tabindex' => 'tabIndex',
+ 'accesskey' => 'accessKey',
+ ];
+ $config = [];
+ foreach ( $attrs as $key => $value ) {
+ if ( isset( $booleanAttrs[$key] ) && $value !== false && $value !== null ) {
+ $value = true;
+ }
+ if ( isset( $attributeToConfig[$key] ) ) {
+ $key = $attributeToConfig[$key];
+ }
+ $config[$key] = $value;
+ }
+ return $config;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/Exception.php b/www/wiki/vendor/oojs/oojs-ui/php/Exception.php
new file mode 100644
index 00000000..2f5ba1b4
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/Exception.php
@@ -0,0 +1,6 @@
+<?php
+
+namespace OOUI;
+
+class Exception extends \Exception {
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/HtmlSnippet.php b/www/wiki/vendor/oojs/oojs-ui/php/HtmlSnippet.php
new file mode 100644
index 00000000..e6091d1d
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/HtmlSnippet.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Wraps a HTML snippet for use with Tag::appendContent() and Tag::prependContent().
+ */
+class HtmlSnippet {
+
+ /* Properties */
+
+ /**
+ * HTML snippet this instance represents.
+ *
+ * @var string
+ */
+ protected $content;
+
+ /* Methods */
+
+ /**
+ * @param string $content HTML snippet
+ */
+ public function __construct( $content ) {
+ if ( !is_string( $content ) ) {
+ throw new Exception( 'Content passed to HtmlSnippet must be a string' );
+ }
+ $this->content = $content;
+ }
+
+ /**
+ * Render into HTML.
+ *
+ * @return string Unchanged HTML snippet
+ */
+ public function __toString() {
+ return $this->content;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/Layout.php b/www/wiki/vendor/oojs/oojs-ui/php/Layout.php
new file mode 100644
index 00000000..0d7013ec
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/Layout.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Container for elements.
+ *
+ * @abstract
+ */
+class Layout extends Element {
+ /**
+ * @param array $config Configuration options
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-layout' ] );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/Tag.php b/www/wiki/vendor/oojs/oojs-ui/php/Tag.php
new file mode 100644
index 00000000..9f39861e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/Tag.php
@@ -0,0 +1,470 @@
+<?php
+
+namespace OOUI;
+
+class Tag {
+
+ /* Properties */
+
+ /**
+ * Tag name for this instance.
+ *
+ * @var string HTML tag name
+ */
+ protected $tag = '';
+
+ /**
+ * Attributes.
+ *
+ * @var array HTML attributes
+ */
+ protected $attributes = [];
+
+ /**
+ * Classes.
+ *
+ * @var array CSS classes
+ */
+ protected $classes = [];
+
+ /**
+ * Content.
+ *
+ * @var array Content text and elements
+ */
+ protected $content = [];
+
+ /**
+ * Group.
+ *
+ * @var GroupElement|null Group element is in
+ */
+ protected $elementGroup = null;
+
+ /**
+ * Infusion support.
+ *
+ * @var boolean Whether to serialize tag/element/widget state for client-side use.
+ */
+ protected $infusable = false;
+
+ /* Methods */
+
+ /**
+ * Create element.
+ *
+ * @param string $tag HTML tag name
+ */
+ public function __construct( $tag = 'div' ) {
+ $this->tag = $tag;
+ }
+
+ /**
+ * Check for CSS class.
+ *
+ * @param string $class CSS class name
+ * @return bool
+ */
+ public function hasClass( $class ) {
+ return in_array( $class, $this->classes );
+ }
+
+ /**
+ * Add CSS classes.
+ *
+ * @param array $classes List of classes to add
+ * @return $this
+ */
+ public function addClasses( array $classes ) {
+ $this->classes = array_merge( $this->classes, $classes );
+ return $this;
+ }
+
+ /**
+ * Remove CSS classes.
+ *
+ * @param array $classes List of classes to remove
+ * @return $this
+ */
+ public function removeClasses( array $classes ) {
+ $this->classes = array_diff( $this->classes, $classes );
+ return $this;
+ }
+
+ /**
+ * Toggle CSS classes.
+ *
+ * @param array $classes List of classes to add
+ * @param bool $toggle Add classes
+ * @return $this
+ */
+ public function toggleClasses( array $classes, $toggle = null ) {
+ if ( $toggle === null ) {
+ $this->classes = array_diff(
+ array_merge( $this->classes, $classes ),
+ array_intersect( $this->classes, $classes )
+ );
+ } elseif ( $toggle ) {
+ $this->classes = array_merge( $this->classes, $classes );
+ } else {
+ $this->classes = array_diff( $this->classes, $classes );
+ }
+ return $this;
+ }
+
+ public function getTag() {
+ return $this->tag;
+ }
+
+ /**
+ * Get HTML attribute value.
+ *
+ * @param string $key HTML attribute name
+ * @return string|null
+ */
+ public function getAttribute( $key ) {
+ return isset( $this->attributes[$key] ) ? $this->attributes[$key] : null;
+ }
+
+ /**
+ * Add HTML attributes.
+ *
+ * @param array $attributes List of attribute key/value pairs to add
+ * @return $this
+ */
+ public function setAttributes( array $attributes ) {
+ foreach ( $attributes as $key => $value ) {
+ $this->attributes[$key] = $value;
+ }
+ return $this;
+ }
+
+ /**
+ * Set value of input element ('value' attribute for most, element content for textarea).
+ *
+ * @param string $value Value to set
+ * @return $this
+ */
+ public function setValue( $value ) {
+ if ( strtolower( $this->tag ) === 'textarea' ) {
+ $this->clearContent();
+ $this->appendContent( $value );
+ } else {
+ $this->setAttributes( [ 'value' => $value ] );
+ }
+ return $this;
+ }
+
+ /**
+ * Remove HTML attributes.
+ *
+ * @param array $keys List of attribute keys to remove
+ * @return $this
+ */
+ public function removeAttributes( array $keys ) {
+ foreach ( $keys as $key ) {
+ unset( $this->attributes[$key] );
+ }
+ return $this;
+ }
+
+ /**
+ * Add content to the end.
+ *
+ * Accepts either variadic arguments (the $content argument can be repeated any number of times)
+ * or an array of arguments.
+ *
+ * For example, these uses are valid:
+ * * $tag->appendContent( [ $element1, $element2 ] );
+ * * $tag->appendContent( $element1, $element2 );
+ * This, however, is not acceptable
+ * * $tag->appendContent( [ $element1, $element2 ], $element3 );
+ *
+ * @param string|Tag|HtmlSnippet $content Content to append. Strings will be HTML-escaped
+ * for output, use a HtmlSnippet instance to prevent that.
+ * @return $this
+ */
+ public function appendContent( /* $content... */ ) {
+ $contents = func_get_args();
+ if ( is_array( $contents[ 0 ] ) ) {
+ $this->content = array_merge( $this->content, $contents[ 0 ] );
+ } else {
+ $this->content = array_merge( $this->content, $contents );
+ }
+ return $this;
+ }
+
+ /**
+ * Add content to the beginning.
+ *
+ * Accepts either variadic arguments (the $content argument can be repeated any number of times)
+ * or an array of arguments.
+ *
+ * For example, these uses are valid:
+ * * $tag->prependContent( [ $element1, $element2 ] );
+ * * $tag->prependContent( $element1, $element2 );
+ * This, however, is not acceptable
+ * * $tag->prependContent( [ $element1, $element2 ], $element3 );
+ *
+ * @param string|Tag|HtmlSnippet $content Content to prepend. Strings will be HTML-escaped
+ * for output, use a HtmlSnippet instance to prevent that.
+ * @return $this
+ */
+ public function prependContent( /* $content... */ ) {
+ $contents = func_get_args();
+ if ( is_array( $contents[ 0 ] ) ) {
+ array_splice( $this->content, 0, 0, $contents[ 0 ] );
+ } else {
+ array_splice( $this->content, 0, 0, $contents );
+ }
+ return $this;
+ }
+
+ /**
+ * Remove all content.
+ *
+ * @return $this
+ */
+ public function clearContent() {
+ $this->content = [];
+ return $this;
+ }
+
+ /**
+ * Get group element is in.
+ *
+ * @return GroupElement|null Group element, null if none
+ */
+ public function getElementGroup() {
+ return $this->elementGroup;
+ }
+
+ /**
+ * Set group element is in.
+ *
+ * @param GroupElement|null $group Group element, null if none
+ * @return $this
+ */
+ public function setElementGroup( $group ) {
+ $this->elementGroup = $group;
+ return $this;
+ }
+
+ /**
+ * Enable widget for client-side infusion.
+ *
+ * @param bool $infusable True to allow tag/element/widget to be referenced client-side.
+ * @return $this
+ */
+ public function setInfusable( $infusable ) {
+ $this->infusable = $infusable;
+ return $this;
+ }
+
+ /**
+ * Get client-side infusability.
+ *
+ * @return bool If this tag/element/widget can be referenced client-side.
+ */
+ public function isInfusable() {
+ return $this->infusable;
+ }
+
+ private static $elementId = 0;
+
+ /**
+ * Generate a unique ID for element
+ *
+ * @return string ID
+ */
+ public static function generateElementId() {
+ self::$elementId++;
+ return 'ooui-php-' . self::$elementId;
+ }
+
+ /**
+ * Ensure that this given Tag is infusable and has a unique `id`
+ * attribute.
+ * @return $this
+ */
+ public function ensureInfusableId() {
+ $this->setInfusable( true );
+ if ( $this->getAttribute( 'id' ) === null ) {
+ $this->setAttributes( [ 'id' => self::generateElementId() ] );
+ }
+ return $this;
+ }
+
+ /**
+ * Return an augmented `attributes` array, including synthetic attributes
+ * which are created from other properties (like the `classes` array)
+ * but which shouldn't be retained in the user-visible `attributes`.
+ * @return array An attributes array.
+ */
+ protected function getGeneratedAttributes() {
+ // Copy attributes, add `class` attribute from `$this->classes` array.
+ $attributesArray = $this->attributes;
+ if ( $this->classes ) {
+ $attributesArray['class'] = implode( ' ', array_unique( $this->classes ) );
+ }
+ if ( $this->infusable ) {
+ // Indicate that this is "just" a tag (not a widget)
+ $attributesArray['data-ooui'] = json_encode( [ '_' => 'Tag' ] );
+ }
+ return $attributesArray;
+ }
+
+ /**
+ * Check whether the string $haystack begins with the string $needle.
+ *
+ * @param string $haystack
+ * @param string $needle
+ * @return bool True if $haystack begins with $needle, false otherwise.
+ */
+ private static function stringStartsWith( $haystack, $needle ) {
+ return strncmp( $haystack, $needle, strlen( $needle ) ) === 0;
+ }
+
+ /**
+ * Check whether user-supplied URL is safe, that is, whether outputting it will not result in XSS
+ * vulnerability. (Note that URLs must be HTML-escaped regardless of this check.)
+ *
+ * The point is to disallow 'javascript:' URLs (there are no good reasons to ever use them
+ * anyway), but there's no good way to blacklist them because of very lax parsing in browsers.
+ *
+ * An URL is safe if:
+ *
+ * - it is empty, or
+ * - it starts with a whitelisted protocol, followed by a colon (absolute URL), or
+ * - it starts with two slashes `//` (protocol-relative URL), or
+ * - it starts with a single slash `/`, or dot and slash `./` (relative URL), or
+ * - it starts with a question mark `?` (replace query part in current URL), or
+ * - it starts with a pound sign `#` (replace fragment part in current URL)
+ *
+ * Plain relative URLs (like `index.php`) are not allowed, since it's pretty much impossible to
+ * distinguish them from malformed absolute ones (again, very lax rules for parsing protocols).
+ *
+ * @param string $url URL
+ * @return bool [description]
+ */
+ public static function isSafeUrl( $url ) {
+ // Keep this function in sync with OO.ui.isSafeUrl
+ $protocolWhitelist = [
+ // Sourced from MediaWiki's $wgUrlProtocols
+ 'bitcoin', 'ftp', 'ftps', 'geo', 'git', 'gopher', 'http', 'https', 'irc', 'ircs',
+ 'magnet', 'mailto', 'mms', 'news', 'nntp', 'redis', 'sftp', 'sip', 'sips', 'sms', 'ssh',
+ 'svn', 'tel', 'telnet', 'urn', 'worldwind', 'xmpp',
+ ];
+
+ if ( $url === '' ) {
+ return true;
+ }
+
+ foreach ( $protocolWhitelist as $protocol ) {
+ if ( self::stringStartsWith( $url, $protocol . ':' ) ) {
+ return true;
+ }
+ }
+
+ // This matches '//' too
+ if ( self::stringStartsWith( $url, '/' ) || self::stringStartsWith( $url, './' ) ) {
+ return true;
+ }
+ if ( self::stringStartsWith( $url, '?' ) || self::stringStartsWith( $url, '#' ) ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Render element into HTML.
+ * @return string HTML serialization
+ * @throws Exception
+ */
+ public function toString() {
+ // List of void elements from HTML5, section 8.1.2 as of 2016-09-19
+ static $voidElements = [
+ 'area',
+ 'base',
+ 'br',
+ 'col',
+ 'embed',
+ 'hr',
+ 'img',
+ 'input',
+ 'keygen',
+ 'link',
+ 'meta',
+ 'param',
+ 'source',
+ 'track',
+ 'wbr',
+ ];
+
+ $attributes = '';
+ foreach ( $this->getGeneratedAttributes() as $key => $value ) {
+ if ( !preg_match( '/^[0-9a-zA-Z-]+$/', $key ) ) {
+ throw new Exception( 'Attribute name must consist of only ASCII letters, numbers and dash' );
+ }
+
+ // Note that this is not a complete list of HTML attributes that need this validation.
+ // We only check for the ones that are generated by built-in OOUI PHP elements.
+ if ( $key === 'href' || $key === 'action' ) {
+ if ( !self::isSafeUrl( $value ) ) {
+ // We can't tell for sure whether this URL is safe (although it might be). The only safe
+ // URLs that we can't check for is relative ones, so just prefix with './'. This should
+ // change nothing for relative URLs, and it will neutralize sneaky 'javascript:' URLs.
+ $value = './' . $value;
+ }
+ }
+
+ // Use single-quotes around the attribute value in HTML, because
+ // some of the values might be JSON strings
+ // 1. Encode both single and double quotes (and other special chars)
+ $value = htmlspecialchars( $value, ENT_QUOTES );
+ // 2. Decode double quotes, for readability.
+ $value = str_replace( '&quot;', '"', $value );
+ // 3. Wrap attribute value in single quotes in the HTML.
+ $attributes .= ' ' . $key . "='" . $value . "'";
+ }
+
+ // Content
+ $content = '';
+ foreach ( $this->content as $part ) {
+ if ( is_string( $part ) ) {
+ $content .= htmlspecialchars( $part );
+ } elseif ( $part instanceof Tag || $part instanceof HtmlSnippet ) {
+ $content .= (string)$part;
+ }
+ }
+
+ if ( !preg_match( '/^[0-9a-zA-Z]+$/', $this->tag ) ) {
+ throw new Exception( 'Tag name must consist of only ASCII letters and numbers' );
+ }
+
+ // Tag
+ if ( !$content && in_array( $this->tag, $voidElements ) ) {
+ return '<' . $this->tag . $attributes . ' />';
+ } else {
+ return '<' . $this->tag . $attributes . '>' . $content . '</' . $this->tag . '>';
+ }
+ }
+
+ /**
+ * Magic method implementation.
+ *
+ * PHP doesn't allow __toString to throw exceptions and will trigger a fatal error if it does.
+ * This is a wrapper around the real toString() to convert them to errors instead.
+ *
+ * @return string
+ */
+ public function __toString() {
+ try {
+ return $this->toString();
+ } catch ( Exception $ex ) {
+ trigger_error( (string)$ex, E_USER_ERROR );
+ return '';
+ }
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/Theme.php b/www/wiki/vendor/oojs/oojs-ui/php/Theme.php
new file mode 100644
index 00000000..4e454507
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/Theme.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Theme logic.
+ *
+ * @abstract
+ */
+abstract class Theme {
+
+ /* Properties */
+
+ private static $singleton;
+
+ /* Static Methods */
+
+ /**
+ * @param Theme|null $theme Theme to use throughout the application
+ */
+ public static function setSingleton( Theme $theme = null ) {
+ self::$singleton = $theme;
+ }
+
+ /**
+ * @return Theme
+ * @throws Exception
+ */
+ public static function singleton() {
+ if ( !self::$singleton ) {
+ throw new Exception( __METHOD__ . ' was called with no singleton theme set.' );
+ }
+
+ return self::$singleton;
+ }
+
+ /**
+ * Get a list of classes to be applied to a widget.
+ *
+ * The 'on' and 'off' lists combined MUST contain keys for all classes the theme adds or removes,
+ * otherwise state transitions will not work properly.
+ *
+ * @param Element $element Element for which to get classes
+ * @return array Categorized class names with `on` and `off` lists
+ */
+ public function getElementClasses( Element $element ) {
+ return [ 'on' => [], 'off' => [] ];
+ }
+
+ /**
+ * Update CSS classes provided by the theme.
+ *
+ * For elements with theme logic hooks, this should be called any time there's a state change.
+ *
+ * @param Element $element Element for which to update classes
+ * @return array Categorized class names with `on` and `off` lists
+ */
+ public function updateElementClasses( Element $element ) {
+ $classes = $this->getElementClasses( $element );
+
+ if ( method_exists( $element, 'getIconElement' ) ) {
+ $element->getIconElement()
+ ->removeClasses( $classes['off'] )
+ ->addClasses( $classes['on'] );
+ }
+ if ( method_exists( $element, 'getIndicatorElement' ) ) {
+ $element->getIndicatorElement()
+ ->removeClasses( $classes['off'] )
+ ->addClasses( $classes['on'] );
+ }
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/Widget.php b/www/wiki/vendor/oojs/oojs-ui/php/Widget.php
new file mode 100644
index 00000000..19364140
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/Widget.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * User interface control.
+ *
+ * @abstract
+ */
+class Widget extends Element {
+
+ /* Properties */
+
+ /**
+ * Disabled.
+ *
+ * @var boolean Widget is disabled
+ */
+ protected $disabled = false;
+
+ /* Methods */
+
+ /**
+ * @param array $config Configuration options
+ * @param bool $config['disabled'] Disable (default: false)
+ */
+ public function __construct( array $config = [] ) {
+ // Initialize config
+ $config = array_merge( [ 'disabled' => false ], $config );
+
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-widget' ] );
+ $this->setDisabled( $config['disabled'] );
+ }
+
+ /**
+ * Check if the widget is disabled.
+ *
+ * @return bool Button is disabled
+ */
+ public function isDisabled() {
+ return $this->disabled;
+ }
+
+ /**
+ * Set the disabled state of the widget.
+ *
+ * This should probably change the widgets' appearance and prevent it from being used.
+ *
+ * @param bool $disabled Disable widget
+ * @return $this
+ */
+ public function setDisabled( $disabled ) {
+ $this->disabled = !!$disabled;
+ $this->toggleClasses( [ 'oo-ui-widget-disabled' ], $this->disabled );
+ $this->toggleClasses( [ 'oo-ui-widget-enabled' ], !$this->disabled );
+ $this->setAttributes( [ 'aria-disabled' => $this->disabled ? 'true' : 'false' ] );
+
+ return $this;
+ }
+
+ /**
+ * Get an ID of a labelable node which is part of this widget, if any, to be used for
+ * `<label for>` value.
+ *
+ * @return string|null The ID of the labelable node
+ */
+ public function getInputId() {
+ return null;
+ }
+
+ public function getConfig( &$config ) {
+ if ( $this->disabled ) {
+ $config['disabled'] = $this->disabled;
+ }
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/layouts/ActionFieldLayout.php b/www/wiki/vendor/oojs/oojs-ui/php/layouts/ActionFieldLayout.php
new file mode 100644
index 00000000..294a16f0
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/layouts/ActionFieldLayout.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Layout made of a field, button and optional label.
+ */
+class ActionFieldLayout extends FieldLayout {
+
+ /**
+ * Button widget to be laid out.
+ *
+ * @var Widget
+ */
+ protected $buttonWidget;
+
+ /**
+ * @param Widget $fieldWidget Field widget
+ * @param ButtonWidget $buttonWidget Field widget
+ * @param array $config Configuration options
+ */
+ public function __construct( $fieldWidget, $buttonWidget = false, array $config = [] ) {
+ // Allow passing positional parameters inside the config array
+ if ( is_array( $fieldWidget ) && isset( $fieldWidget['fieldWidget'] ) ) {
+ $config = $fieldWidget;
+ $fieldWidget = $config['fieldWidget'];
+ $buttonWidget = $config['buttonWidget'];
+ }
+
+ // Parent constructor
+ parent::__construct( $fieldWidget, $config );
+
+ // Properties
+ $this->buttonWidget = $buttonWidget;
+ $this->button = new Tag( 'span' );
+ $this->input = $this->isFieldInline() ? new Tag( 'span' ) : new Tag( 'div' );
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-actionFieldLayout' ] );
+ $this->button
+ ->addClasses( [ 'oo-ui-actionFieldLayout-button' ] )
+ ->appendContent( $this->buttonWidget );
+ $this->input
+ ->addClasses( [ 'oo-ui-actionFieldLayout-input' ] )
+ ->appendContent( $this->fieldWidget );
+ $this->field
+ ->clearContent()
+ ->appendContent( $this->input, $this->button );
+ }
+
+ public function getConfig( &$config ) {
+ $config['buttonWidget'] = $this->buttonWidget;
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/layouts/FieldLayout.php b/www/wiki/vendor/oojs/oojs-ui/php/layouts/FieldLayout.php
new file mode 100644
index 00000000..a32c6bc5
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/layouts/FieldLayout.php
@@ -0,0 +1,253 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Layout made of a field and optional label.
+ *
+ * Available label alignment modes include:
+ * - left: Label is before the field and aligned away from it, best for when the user will be
+ * scanning for a specific label in a form with many fields
+ * - right: Label is before the field and aligned toward it, best for forms the user is very
+ * familiar with and will tab through field checking quickly to verify which field they are in
+ * - top: Label is before the field and above it, best for when the user will need to fill out all
+ * fields from top to bottom in a form with few fields
+ * - inline: Label is after the field and aligned toward it, best for small boolean fields like
+ * checkboxes or radio buttons
+ */
+class FieldLayout extends Layout {
+ use LabelElement;
+ use TitledElement;
+
+ /**
+ * Alignment.
+ *
+ * @var string
+ */
+ protected $align;
+
+ /**
+ * Field widget to be laid out.
+ *
+ * @var Widget
+ */
+ protected $fieldWidget;
+
+ /**
+ * Error messages.
+ *
+ * @var array
+ */
+ protected $errors;
+
+ /**
+ * Notice messages.
+ *
+ * @var array
+ */
+ protected $notices;
+
+ /**
+ * @var ButtonWidget|string
+ */
+ protected $help;
+
+ protected $field, $header, $body, $messages;
+
+ /**
+ * @param Widget $fieldWidget Field widget
+ * @param array $config Configuration options
+ * @param string $config['align'] Alignment mode, either 'left', 'right', 'top' or 'inline'
+ * (default: 'left')
+ * @param array $config['errors'] Error messages about the widget, as strings or HtmlSnippet
+ * instances.
+ * @param array $config['notices'] Notices about the widget, as strings or HtmlSnippet instances.
+ * @param string|HtmlSnippet $config['help'] Explanatory text shown as a '?' icon.
+ * @throws Exception An exception is thrown if no widget is specified
+ */
+ public function __construct( $fieldWidget, array $config = [] ) {
+ // Allow passing positional parameters inside the config array
+ if ( is_array( $fieldWidget ) && isset( $fieldWidget['fieldWidget'] ) ) {
+ $config = $fieldWidget;
+ $fieldWidget = $config['fieldWidget'];
+ }
+
+ // Make sure we have required constructor arguments
+ if ( $fieldWidget === null ) {
+ throw new Exception( 'Widget not found' );
+ }
+
+ // Config initialization
+ $config = array_merge( [ 'align' => 'left' ], $config );
+
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Properties
+ $this->fieldWidget = $fieldWidget;
+ $this->errors = isset( $config['errors'] ) ? $config['errors'] : [];
+ $this->notices = isset( $config['notices'] ) ? $config['notices'] : [];
+ $this->field = $this->isFieldInline() ? new Tag( 'span' ) : new Tag( 'div' );
+ $this->messages = new Tag( 'ul' );
+ $this->header = new Tag( 'span' );
+ $this->body = new Tag( 'div' );
+ if ( isset( $config['help'] ) ) {
+ $this->help = new ButtonWidget( [
+ 'classes' => [ 'oo-ui-fieldLayout-help' ],
+ 'framed' => false,
+ 'icon' => 'info',
+ 'title' => $config['help'],
+ ] );
+ } else {
+ $this->help = '';
+ }
+
+ // Traits
+ $this->initializeLabelElement( array_merge( $config, [
+ 'labelElement' => new Tag( 'label' )
+ ] ) );
+ $this->initializeTitledElement(
+ array_merge( $config, [ 'titled' => $this->label ] ) );
+
+ // Initialization
+ if ( $this->fieldWidget->getInputId() ) {
+ $this->label->setAttributes( [ 'for' => $this->fieldWidget->getInputId() ] );
+ }
+ $this
+ ->addClasses( [ 'oo-ui-fieldLayout' ] )
+ ->toggleClasses( [ 'oo-ui-fieldLayout-disabled' ], $this->fieldWidget->isDisabled() )
+ ->appendContent( $this->body );
+ if ( count( $this->errors ) || count( $this->notices ) ) {
+ $this->appendContent( $this->messages );
+ }
+ $this->body->addClasses( [ 'oo-ui-fieldLayout-body' ] );
+ $this->header->addClasses( [ 'oo-ui-fieldLayout-header' ] );
+ $this->messages->addClasses( [ 'oo-ui-fieldLayout-messages' ] );
+ $this->field
+ ->addClasses( [ 'oo-ui-fieldLayout-field' ] )
+ ->appendContent( $this->fieldWidget );
+
+ foreach ( $this->notices as $text ) {
+ $this->messages->appendContent( $this->makeMessage( 'notice', $text ) );
+ }
+ foreach ( $this->errors as $text ) {
+ $this->messages->appendContent( $this->makeMessage( 'error', $text ) );
+ }
+
+ $this->setAlignment( $config['align'] );
+ // Call this again to take into account the widget's accessKey
+ $this->updateTitle();
+ }
+
+ /**
+ * @param string $kind 'error' or 'notice'
+ * @param string|HtmlSnippet $text
+ * @return Tag
+ */
+ private function makeMessage( $kind, $text ) {
+ $listItem = new Tag( 'li' );
+ if ( $kind === 'error' ) {
+ $icon = new IconWidget( [ 'icon' => 'alert', 'flags' => [ 'warning' ] ] );
+ $listItem->setAttributes( [ 'role' => 'alert' ] );
+ } elseif ( $kind === 'notice' ) {
+ $icon = new IconWidget( [ 'icon' => 'notice' ] );
+ } else {
+ $icon = null;
+ }
+ $message = new LabelWidget( [ 'label' => $text ] );
+ $listItem
+ ->appendContent( $icon, $message )
+ ->addClasses( [ "oo-ui-fieldLayout-messages-$kind" ] );
+ return $listItem;
+ }
+
+ /**
+ * Get the field.
+ *
+ * @return Widget Field widget
+ */
+ public function getField() {
+ return $this->fieldWidget;
+ }
+
+ /**
+ * Return `true` if the given field widget can be used with `'inline'` alignment (see
+ * setAlignment()). Return `false` if it can't or if this can't be determined.
+ *
+ * @return bool
+ */
+ public function isFieldInline() {
+ // This is very simplistic, but should be good enough. It's important to avoid false positives,
+ // as that will cause the generated HTML to be invalid and go all out of whack when parsed.
+ return strtolower( $this->getField()->getTag() ) === 'span';
+ }
+
+ /**
+ * Set the field alignment mode.
+ *
+ * @param string $value Alignment mode, either 'left', 'right', 'top' or 'inline'
+ * @return $this
+ */
+ protected function setAlignment( $value ) {
+ if ( $value !== $this->align ) {
+ // Default to 'left'
+ if ( !in_array( $value, [ 'left', 'right', 'top', 'inline' ] ) ) {
+ $value = 'left';
+ }
+ // Validate
+ if ( $value === 'inline' && !$this->isFieldInline() ) {
+ $value = 'top';
+ }
+ // Reorder elements
+ $this->body->clearContent();
+ if ( $value === 'top' ) {
+ $this->header->appendContent( $this->help, $this->label );
+ $this->body->appendContent( $this->header, $this->field );
+ } elseif ( $value === 'inline' ) {
+ $this->header->appendContent( $this->help, $this->label );
+ $this->body->appendContent( $this->field, $this->header );
+ } else {
+ $this->header->appendContent( $this->label );
+ $this->body->appendContent( $this->header, $this->help, $this->field );
+ }
+ // Set classes. The following classes can be used here:
+ // * oo-ui-fieldLayout-align-left
+ // * oo-ui-fieldLayout-align-right
+ // * oo-ui-fieldLayout-align-top
+ // * oo-ui-fieldLayout-align-inline
+ if ( $this->align ) {
+ $this->removeClasses( [ 'oo-ui-fieldLayout-align-' . $this->align ] );
+ }
+ $this->addClasses( [ 'oo-ui-fieldLayout-align-' . $value ] );
+ $this->align = $value;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Include information about the widget's accessKey in our title. TitledElement calls this method.
+ * (This is a bit of a hack.)
+ *
+ * @param string $title Tooltip label for 'title' attribute
+ * @return string
+ */
+ protected function formatTitleWithAccessKey( $title ) {
+ if ( $this->fieldWidget && method_exists( $this->fieldWidget, 'formatTitleWithAccessKey' ) ) {
+ return $this->fieldWidget->formatTitleWithAccessKey( $title );
+ }
+ return $title;
+ }
+
+ public function getConfig( &$config ) {
+ $config['fieldWidget'] = $this->fieldWidget;
+ $config['align'] = $this->align;
+ $config['errors'] = $this->errors;
+ $config['notices'] = $this->notices;
+ if ( $this->help !== '' ) {
+ $config['help'] = $this->help->getTitle();
+ }
+ $config['$overlay'] = true;
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/layouts/FieldsetLayout.php b/www/wiki/vendor/oojs/oojs-ui/php/layouts/FieldsetLayout.php
new file mode 100644
index 00000000..d69d2ff0
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/layouts/FieldsetLayout.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Layout made of a fieldset and optional legend.
+ *
+ * Just add FieldLayout items.
+ */
+class FieldsetLayout extends Layout {
+ use IconElement;
+ use LabelElement;
+ use GroupElement;
+
+ /* Static Properties */
+
+ public static $tagName = 'fieldset';
+
+ protected $header;
+
+ /**
+ * @param array $config Configuration options
+ * @param FieldLayout[] $config['items'] Items to add
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Traits
+ $this->initializeIconElement( $config );
+ $this->initializeLabelElement( $config );
+ $this->initializeGroupElement( $config );
+
+ // Properties
+ $this->header = new Tag( 'legend' );
+
+ // Initialization
+ $this->header
+ ->addClasses( [ 'oo-ui-fieldsetLayout-header' ] )
+ ->appendContent( $this->icon, $this->label );
+ $this->group->addClasses( [ 'oo-ui-fieldsetLayout-group' ] );
+ $this
+ ->addClasses( [ 'oo-ui-fieldsetLayout' ] )
+ ->prependContent( $this->header, $this->group );
+ if ( isset( $config['items'] ) ) {
+ $this->addItems( $config['items'] );
+ }
+ }
+
+ public function getConfig( &$config ) {
+ $config['$overlay'] = true;
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/layouts/FormLayout.php b/www/wiki/vendor/oojs/oojs-ui/php/layouts/FormLayout.php
new file mode 100644
index 00000000..f170e420
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/layouts/FormLayout.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Layout with an HTML form.
+ */
+class FormLayout extends Layout {
+ use GroupElement;
+
+ /* Static Properties */
+
+ public static $tagName = 'form';
+
+ /**
+ * @param array $config Configuration options
+ * @param string $config['method'] HTML form `method` attribute
+ * @param string $config['action'] HTML form `action` attribute
+ * @param string $config['enctype'] HTML form `enctype` attribute
+ * @param FieldsetLayout[] $config['items'] Items to add
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Traits
+ $this->initializeGroupElement( array_merge( $config, [ 'group' => $this ] ) );
+
+ // Initialization
+ $attributeWhitelist = [ 'method', 'action', 'enctype' ];
+ $this
+ ->addClasses( [ 'oo-ui-formLayout' ] )
+ ->setAttributes( array_intersect_key( $config, array_flip( $attributeWhitelist ) ) );
+ if ( isset( $config['items'] ) ) {
+ $this->addItems( $config['items'] );
+ }
+ }
+
+ public function getConfig( &$config ) {
+ foreach ( [ 'method', 'action', 'enctype' ] as $attr ) {
+ $value = $this->getAttribute( $attr );
+ if ( $value !== null ) {
+ $config[$attr] = $value;
+ }
+ }
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/layouts/HorizontalLayout.php b/www/wiki/vendor/oojs/oojs-ui/php/layouts/HorizontalLayout.php
new file mode 100644
index 00000000..c2a18052
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/layouts/HorizontalLayout.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * HorizontalLayout arranges its contents in a single line (using `display: inline-block` for its
+ * items), with small margins between them.
+ */
+class HorizontalLayout extends Layout {
+ use GroupElement;
+
+ /**
+ * @param array $config Configuration options
+ * @param Widget[]|Layout[] $config['items'] Widgets or other layouts to add to the layout.
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Traits
+ $this->initializeGroupElement( array_merge( $config, [ 'group' => $this ] ) );
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-horizontalLayout' ] );
+ if ( isset( $config['items'] ) ) {
+ $this->addItems( $config['items'] );
+ }
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/layouts/PanelLayout.php b/www/wiki/vendor/oojs/oojs-ui/php/layouts/PanelLayout.php
new file mode 100644
index 00000000..83ad87c9
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/layouts/PanelLayout.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Layout that expands to cover the entire area of its parent, with optional scrolling and padding.
+ */
+class PanelLayout extends Layout {
+ /**
+ * @param array $config Configuration options
+ * @param bool $config['scrollable'] Allow vertical scrolling (default: false)
+ * @param bool $config['padded'] Pad the content from the edges (default: false)
+ * @param bool $config['expanded'] Expand size to fill the entire parent element
+ * (default: true)
+ * @param bool $config['framed'] Wrap in a frame to visually separate from outside content
+ * (default: false)
+ */
+ public function __construct( array $config = [] ) {
+ // Config initialization
+ $config = array_merge( [
+ 'scrollable' => false,
+ 'padded' => false,
+ 'expanded' => true,
+ 'framed' => false,
+ ], $config );
+
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-panelLayout' ] );
+ if ( $config['scrollable'] ) {
+ $this->addClasses( [ 'oo-ui-panelLayout-scrollable' ] );
+ }
+ if ( $config['padded'] ) {
+ $this->addClasses( [ 'oo-ui-panelLayout-padded' ] );
+ }
+ if ( $config['expanded'] ) {
+ $this->addClasses( [ 'oo-ui-panelLayout-expanded' ] );
+ }
+ if ( $config['framed'] ) {
+ $this->addClasses( [ 'oo-ui-panelLayout-framed' ] );
+ }
+ }
+ public function getConfig( &$config ) {
+ if ( $this->hasClass( 'oo-ui-panelLayout-scrollable' ) ) {
+ $config['scrollable'] = true;
+ }
+ if ( $this->hasClass( 'oo-ui-panelLayout-padded' ) ) {
+ $config['padded'] = true;
+ }
+ if ( !$this->hasClass( 'oo-ui-panelLayout-expanded' ) ) {
+ $config['expanded'] = false;
+ }
+ if ( $this->hasClass( 'oo-ui-panelLayout-framed' ) ) {
+ $config['framed'] = true;
+ }
+ $config['content'] = $this->content;
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/mixins/AccessKeyedElement.php b/www/wiki/vendor/oojs/oojs-ui/php/mixins/AccessKeyedElement.php
new file mode 100644
index 00000000..3f46c7c0
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/mixins/AccessKeyedElement.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Element with an accesskey.
+ *
+ * Accesskeys allow an user to go to a specific element by using
+ * a shortcut combination of a browser specific keys + the key
+ * set to the field.
+ *
+ * @abstract
+ */
+trait AccessKeyedElement {
+
+ /**
+ * Accesskey
+ *
+ * @var string
+ */
+ protected $accessKey = null;
+
+ /**
+ * @var Tag
+ */
+ protected $accessKeyed;
+
+ /**
+ * @param array $config Configuration options
+ * @param string $config['accessKey'] AccessKey. If not provided, no accesskey will be added
+ */
+ public function initializeAccessKeyedElement( array $config = [] ) {
+ // Properties
+ $this->accessKeyed = isset( $config['accessKeyed'] ) ? $config['accessKeyed'] : $element;
+
+ // Initialization
+ $this->setAccessKey(
+ isset( $config['accessKey'] ) ? $config['accessKey'] : null
+ );
+ $this->registerConfigCallback( function ( &$config ) {
+ if ( $this->accessKey !== null ) {
+ $config['accessKey'] = $this->accessKey;
+ }
+ } );
+ }
+
+ /**
+ * Set access key.
+ *
+ * @param string $accessKey Tag's access key, use empty string to remove
+ * @return $this
+ */
+ public function setAccessKey( $accessKey ) {
+ $accessKey = is_string( $accessKey ) && strlen( $accessKey ) ? $accessKey : null;
+
+ if ( $this->accessKey !== $accessKey ) {
+ if ( $accessKey !== null ) {
+ $this->accessKeyed->setAttributes( [ 'accesskey' => $accessKey ] );
+ } else {
+ $this->accessKeyed->removeAttributes( [ 'accesskey' ] );
+ }
+ $this->accessKey = $accessKey;
+
+ // Only if this is a TitledElement
+ if ( method_exists( $this, 'updateTitle' ) ) {
+ $this->updateTitle();
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get AccessKey.
+ *
+ * @return string Accesskey string
+ */
+ public function getAccessKey() {
+ return $this->accessKey;
+ }
+
+ /**
+ * Add information about the access key to the element's tooltip label.
+ * (This is only public for hacky usage in FieldLayout.)
+ *
+ * @param string $title Tooltip label for `title` attribute
+ * @return string
+ */
+ public function formatTitleWithAccessKey( $title ) {
+ $accessKey = $this->getAccessKey();
+ if ( $accessKey ) {
+ $title .= " [$accessKey]";
+ }
+ return $title;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/mixins/ButtonElement.php b/www/wiki/vendor/oojs/oojs-ui/php/mixins/ButtonElement.php
new file mode 100644
index 00000000..eaf0651c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/mixins/ButtonElement.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Element with a button.
+ *
+ * Buttons are used for controls which can be clicked. They can be configured to use tab indexing
+ * and access keys for accessibility purposes.
+ *
+ * @abstract
+ */
+trait ButtonElement {
+
+ /**
+ * Button is framed.
+ *
+ * @var boolean
+ */
+ protected $framed = false;
+
+ /**
+ * @var Tag
+ */
+ protected $button;
+
+ /**
+ * @param array $config Configuration options
+ * @param bool $config['framed'] Render button with a frame (default: true)
+ */
+ public function initializeButtonElement( array $config = [] ) {
+ // Properties
+ if ( ! $this instanceof Element ) {
+ throw new Exception( "ButtonElement trait can only be used on Element instances" );
+ }
+ $target = isset( $config['button'] ) ? $config['button'] : new Tag( 'a' );
+ $this->button = $target;
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-buttonElement' ] );
+ $this->button->addClasses( [ 'oo-ui-buttonElement-button' ] );
+ $this->toggleFramed( isset( $config['framed'] ) ? $config['framed'] : true );
+
+ // Add `role="button"` on `<a>` elements, where it's needed
+ if ( strtolower( $this->button->getTag() ) === 'a' ) {
+ $this->button->setAttributes( [
+ 'role' => 'button',
+ ] );
+ }
+
+ $this->registerConfigCallback( function ( &$config ) {
+ if ( $this->framed !== true ) {
+ $config['framed'] = $this->framed;
+ }
+ } );
+ }
+
+ /**
+ * Toggle frame.
+ *
+ * @param bool $framed Make button framed, omit to toggle
+ * @return $this
+ */
+ public function toggleFramed( $framed = null ) {
+ $this->framed = $framed !== null ? !!$framed : !$this->framed;
+ $this->toggleClasses( [ 'oo-ui-buttonElement-framed' ], $this->framed );
+ $this->toggleClasses( [ 'oo-ui-buttonElement-frameless' ], !$this->framed );
+ return $this;
+ }
+
+ /**
+ * Check if button has a frame.
+ *
+ * @return bool Button is framed
+ */
+ public function isFramed() {
+ return $this->framed;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/mixins/FlaggedElement.php b/www/wiki/vendor/oojs/oojs-ui/php/mixins/FlaggedElement.php
new file mode 100644
index 00000000..97e45b0c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/mixins/FlaggedElement.php
@@ -0,0 +1,133 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Element with named flags that can be added, removed, listed and checked.
+ *
+ * A flag, when set, adds a CSS class on the `$element` by combining `oo-ui-flaggedElement-` with
+ * the flag name. Flags are primarily useful for styling.
+ *
+ * @abstract
+ */
+trait FlaggedElement {
+ /**
+ * Flags.
+ *
+ * @var string[]
+ */
+ protected $flags = [];
+
+ /**
+ * @var Element
+ */
+ protected $flagged;
+
+ /**
+ * @param array $config Configuration options
+ * @param string|string[] $config['flags'] Flags describing importance and functionality, e.g.
+ * 'primary', 'safe', 'progressive', or 'destructive'.
+ */
+ public function initializeFlaggedElement( array $config = [] ) {
+ // Properties
+ $this->flagged = isset( $config['flagged'] ) ? $config['flagged'] : $this;
+
+ // Initialization
+ $this->setFlags( isset( $config['flags'] ) ? $config['flags'] : null );
+
+ $this->registerConfigCallback( function ( &$config ) {
+ if ( !empty( $this->flags ) ) {
+ $config['flags'] = $this->getFlags();
+ }
+ } );
+ }
+
+ /**
+ * Check if a flag is set.
+ *
+ * @param string $flag Name of flag
+ * @return bool Has flag
+ */
+ public function hasFlag( $flag ) {
+ return isset( $this->flags[$flag] );
+ }
+
+ /**
+ * Get the names of all flags set.
+ *
+ * @return string[] Flag names
+ */
+ public function getFlags() {
+ return array_keys( $this->flags );
+ }
+
+ /**
+ * Clear all flags.
+ *
+ * @return $this
+ */
+ public function clearFlags() {
+ $remove = [];
+ $classPrefix = 'oo-ui-flaggedElement-';
+
+ foreach ( $this->flags as $flag ) {
+ $remove[] = $classPrefix . $flag;
+ }
+
+ $this->flagged->removeClasses( $remove );
+ $this->flags = [];
+
+ return $this;
+ }
+
+ /**
+ * Add one or more flags.
+ *
+ * @param string|array $flags One or more flags to add, or an array keyed by flag name
+ * containing boolean set/remove instructions.
+ * @return $this
+ */
+ public function setFlags( $flags ) {
+ $add = [];
+ $remove = [];
+ $classPrefix = 'oo-ui-flaggedElement-';
+
+ if ( is_string( $flags ) ) {
+ // Set
+ if ( !isset( $this->flags[$flags] ) ) {
+ $this->flags[$flags] = true;
+ $add[] = $classPrefix . $flags;
+ }
+ } elseif ( is_array( $flags ) ) {
+ foreach ( $flags as $key => $value ) {
+ if ( is_numeric( $key ) ) {
+ // Set
+ if ( !isset( $this->flags[$value] ) ) {
+ $this->flags[$value] = true;
+ $add[] = $classPrefix . $value;
+ }
+ } else {
+ if ( $value ) {
+ // Set
+ if ( !isset( $this->flags[$key] ) ) {
+ $this->flags[$key] = true;
+ $add[] = $classPrefix . $key;
+ }
+ } else {
+ // Remove
+ if ( isset( $this->flags[$key] ) ) {
+ unset( $this->flags[$key] );
+ $remove[] = $classPrefix . $key;
+ }
+ }
+ }
+ }
+ }
+
+ $this->flagged
+ ->addClasses( $add )
+ ->removeClasses( $remove );
+
+ return $this;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/mixins/GroupElement.php b/www/wiki/vendor/oojs/oojs-ui/php/mixins/GroupElement.php
new file mode 100644
index 00000000..a6335c71
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/mixins/GroupElement.php
@@ -0,0 +1,129 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Element containing a sequence of child elements.
+ *
+ * @abstract
+ */
+trait GroupElement {
+ /**
+ * List of items in the group as Elements.
+ *
+ * @var Element[]
+ */
+ protected $items = [];
+
+ /**
+ * @var Tag
+ */
+ protected $group;
+
+ /**
+ * @param array $config Configuration options
+ */
+ public function initializeGroupElement( array $config = [] ) {
+ // Properties
+ $this->group = isset( $config['group'] ) ? $config['group'] : new Tag( 'div' );
+
+ $this->registerConfigCallback( function ( &$config ) {
+ $config['items'] = $this->items;
+ } );
+ }
+
+ /**
+ * Check if there are no items.
+ *
+ * @return bool Group is empty
+ */
+ public function isEmpty() {
+ return !count( $this->items );
+ }
+
+ /**
+ * Get items.
+ *
+ * @return Element[] Items
+ */
+ public function getItems() {
+ return $this->items;
+ }
+
+ /**
+ * Add items.
+ *
+ * Adding an existing item will move it.
+ *
+ * @param Element[] $items Items
+ * @param number $index Index to insert items at
+ * @return $this
+ */
+ public function addItems( array $items, $index = null ) {
+ foreach ( $items as $item ) {
+ // Check if item exists then remove it first, effectively "moving" it
+ $currentIndex = array_search( $item, $this->items, true );
+ if ( $currentIndex !== false ) {
+ $this->removeItems( [ $item ] );
+ // Adjust index to compensate for removal
+ if ( $currentIndex < $index ) {
+ $index--;
+ }
+ }
+ // Add the item
+ $item->setElementGroup( $this );
+ }
+
+ if ( $index === null || $index < 0 || $index >= count( $this->items ) ) {
+ $this->items = array_merge( $this->items, $items );
+ } else {
+ array_splice( $this->items, $index, 0, $items );
+ }
+
+ // Update actual target element contents to reflect our list
+ $this->group->clearContent();
+ $this->group->appendContent( $this->items );
+
+ return $this;
+ }
+
+ /**
+ * Remove items.
+ *
+ * @param Element[] $items Items to remove
+ * @return $this
+ */
+ public function removeItems( $items ) {
+ foreach ( $items as $item ) {
+ $index = array_search( $item, $this->items, true );
+ if ( $index !== false ) {
+ $item->setElementGroup( null );
+ array_splice( $this->items, $index, 1 );
+ }
+ }
+
+ // Update actual target element contents to reflect our list
+ $this->group->clearContent();
+ $this->group->appendContent( $this->items );
+
+ return $this;
+ }
+
+ /**
+ * Clear all items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @return $this
+ */
+ public function clearItems() {
+ foreach ( $this->items as $item ) {
+ $item->setElementGroup( null );
+ }
+
+ $this->items = [];
+ $this->group->clearContent();
+
+ return $this;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/mixins/IconElement.php b/www/wiki/vendor/oojs/oojs-ui/php/mixins/IconElement.php
new file mode 100644
index 00000000..4ec7d111
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/mixins/IconElement.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Element containing an icon.
+ *
+ * Icons are graphics, about the size of normal text. They can be used to aid the user in locating
+ * a control or convey information in a more space efficient way. Icons should rarely be used
+ * without labels; such as in a toolbar where space is at a premium or within a context where the
+ * meaning is very clear to the user.
+ *
+ * @abstract
+ */
+trait IconElement {
+ /**
+ * Symbolic icon name.
+ *
+ * @var string
+ */
+ protected $iconName = null;
+
+ /**
+ * @var Tag
+ */
+ protected $icon;
+
+ /**
+ * @param array $config Configuration options
+ * @param string $config['icon'] Symbolic icon name
+ */
+ public function initializeIconElement( array $config = [] ) {
+ // Properties
+ // FIXME 'iconElement' is a very stupid way to call '$icon'
+ $this->icon = isset( $config['iconElement'] ) ? $config['iconElement'] : new Tag( 'span' );
+
+ // Initialization
+ $this->icon->addClasses( [ 'oo-ui-iconElement-icon' ] );
+ $this->setIcon( isset( $config['icon'] ) ? $config['icon'] : null );
+
+ $this->registerConfigCallback( function ( &$config ) {
+ if ( $this->iconName !== null ) {
+ $config['icon'] = $this->iconName;
+ }
+ } );
+ }
+
+ /**
+ * Set icon name.
+ *
+ * @param string|null $icon Symbolic icon name
+ * @return $this
+ */
+ public function setIcon( $icon = null ) {
+ if ( $this->iconName !== null ) {
+ $this->icon->removeClasses( [ 'oo-ui-icon-' . $this->iconName ] );
+ }
+ if ( $icon !== null ) {
+ $this->icon->addClasses( [ 'oo-ui-icon-' . $icon ] );
+ }
+
+ $this->iconName = $icon;
+ $this->toggleClasses( [ 'oo-ui-iconElement' ], (bool)$this->iconName );
+
+ return $this;
+ }
+
+ /**
+ * Get icon name.
+ *
+ * @return string Icon name
+ */
+ public function getIcon() {
+ return $this->iconName;
+ }
+
+ /**
+ * Do not use outside of Theme::updateElementClasses
+ *
+ * @protected
+ * @return Tag
+ */
+ public function getIconElement() {
+ return $this->icon;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/mixins/IndicatorElement.php b/www/wiki/vendor/oojs/oojs-ui/php/mixins/IndicatorElement.php
new file mode 100644
index 00000000..61f31f72
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/mixins/IndicatorElement.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Element containing an indicator.
+ *
+ * Indicators are graphics, smaller than normal text. They can be used to describe unique status or
+ * behavior. Indicators should only be used in exceptional cases; such as a button that opens a menu
+ * instead of performing an action directly, or an item in a list which has errors that need to be
+ * resolved.
+ *
+ * @abstract
+ */
+trait IndicatorElement {
+ /**
+ * Symbolic indicator name
+ *
+ * @var string|null
+ */
+ protected $indicatorName = null;
+
+ /**
+ * @var Tag
+ */
+ protected $indicator;
+
+ /**
+ * @param array $config Configuration options
+ * @param string $config['indicator'] Symbolic indicator name
+ */
+ public function initializeIndicatorElement( array $config = [] ) {
+ // Properties
+ // FIXME 'indicatorElement' is a very stupid way to call '$indicator'
+ $this->indicator = isset( $config['indicatorElement'] )
+ ? $config['indicatorElement']
+ : new Tag( 'span' );
+
+ // Initialization
+ $this->indicator->addClasses( [ 'oo-ui-indicatorElement-indicator' ] );
+ $this->setIndicator( isset( $config['indicator'] ) ? $config['indicator'] : null );
+
+ $this->registerConfigCallback( function ( &$config ) {
+ if ( $this->indicatorName !== null ) {
+ $config['indicator'] = $this->indicatorName;
+ }
+ } );
+ }
+
+ /**
+ * Set indicator name.
+ *
+ * @param string|null $indicator Symbolic name of indicator to use or null for no indicator
+ * @return $this
+ */
+ public function setIndicator( $indicator = null ) {
+ if ( $this->indicatorName !== null ) {
+ $this->indicator->removeClasses( [ 'oo-ui-indicator-' . $this->indicatorName ] );
+ }
+ if ( $indicator !== null ) {
+ $this->indicator->addClasses( [ 'oo-ui-indicator-' . $indicator ] );
+ }
+
+ $this->indicatorName = $indicator;
+ $this->toggleClasses( [ 'oo-ui-indicatorElement' ], (bool)$this->indicatorName );
+
+ return $this;
+ }
+
+ /**
+ * Get indicator name.
+ *
+ * @return string Symbolic name of indicator
+ */
+ public function getIndicator() {
+ return $this->indicatorName;
+ }
+
+ /**
+ * Do not use outside of Theme::updateElementClasses
+ *
+ * @protected
+ * @return Tag
+ */
+ public function getIndicatorElement() {
+ return $this->indicator;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/mixins/LabelElement.php b/www/wiki/vendor/oojs/oojs-ui/php/mixins/LabelElement.php
new file mode 100644
index 00000000..d4280bdc
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/mixins/LabelElement.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Element containing a label.
+ *
+ * @abstract
+ */
+trait LabelElement {
+ /**
+ * Label value.
+ *
+ * @var string|HtmlSnippet|null
+ */
+ protected $labelValue = null;
+
+ /**
+ * @var Tag
+ */
+ protected $label;
+
+ /**
+ * @param array $config Configuration options
+ * @param string|HtmlSnippet $config['label'] Label text
+ */
+ public function initializeLabelElement( array $config = [] ) {
+ // Properties
+ // FIXME 'labelElement' is a very stupid way to call '$label'
+ $this->label = isset( $config['labelElement'] ) ? $config['labelElement'] : new Tag( 'span' );
+
+ // Initialization
+ $this->label->addClasses( [ 'oo-ui-labelElement-label' ] );
+ $this->setLabel( isset( $config['label'] ) ? $config['label'] : null );
+
+ $this->registerConfigCallback( function ( &$config ) {
+ if ( $this->labelValue !== null ) {
+ $config['label'] = $this->labelValue;
+ }
+ } );
+ }
+
+ /**
+ * Set the label.
+ *
+ * An empty string will result in the label being hidden. A string containing only whitespace will
+ * be converted to a single `&nbsp;`.
+ *
+ * @param string|HtmlSnippet|null $label Label text
+ * @return $this
+ */
+ public function setLabel( $label ) {
+ $this->labelValue = (string)$label ? $label : null;
+
+ $this->label->clearContent();
+ if ( $this->labelValue !== null ) {
+ if ( is_string( $this->labelValue ) && $this->labelValue !== ''
+ && trim( $this->labelValue ) === ''
+ ) {
+ $this->label->appendContent( new HtmlSnippet( '&nbsp;' ) );
+ } else {
+ $this->label->appendContent( $label );
+ }
+ }
+
+ $this->toggleClasses( [ 'oo-ui-labelElement' ], !!$this->labelValue );
+
+ return $this;
+ }
+
+ /**
+ * Get the label.
+ *
+ * @return string|HtmlSnippet|null Label text
+ */
+ public function getLabel() {
+ return $this->labelValue;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/mixins/TabIndexedElement.php b/www/wiki/vendor/oojs/oojs-ui/php/mixins/TabIndexedElement.php
new file mode 100644
index 00000000..398281e5
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/mixins/TabIndexedElement.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Element supporting "sequential focus navigation" using the 'tabindex' attribute.
+ *
+ * @abstract
+ */
+trait TabIndexedElement {
+ /**
+ * Tab index value.
+ *
+ * @var number|null
+ */
+ protected $tabIndex = null;
+
+ /**
+ * @var Element
+ */
+ protected $tabIndexed;
+
+ /**
+ * @param array $config Configuration options
+ * @param string|number|null $config['tabIndex'] Tab index value. Use 0 to use default ordering,
+ * use -1 to prevent tab focusing, use null to suppress the `tabindex` attribute. (default: 0)
+ */
+ public function initializeTabIndexedElement( array $config = [] ) {
+ // Properties
+ $this->tabIndexed = isset( $config['tabIndexed'] ) ? $config['tabIndexed'] : $this;
+
+ // Initialization
+ $this->setTabIndex( isset( $config['tabIndex'] ) ? $config['tabIndex'] : 0 );
+
+ $this->registerConfigCallback( function ( &$config ) {
+ if ( $this->tabIndex !== 0 ) {
+ $config['tabIndex'] = $this->tabIndex;
+ }
+ } );
+ }
+
+ /**
+ * Set tab index value.
+ *
+ * @param string|number|null $tabIndex Tab index value or null for no tab index
+ * @return $this
+ */
+ public function setTabIndex( $tabIndex ) {
+ $tabIndex = preg_match( '/^-?\d+$/', $tabIndex ) ? (int)$tabIndex : null;
+
+ if ( $this->tabIndex !== $tabIndex ) {
+ $this->tabIndex = $tabIndex;
+ $this->updateTabIndex();
+ }
+
+ return $this;
+ }
+
+ /**
+ * Update the tabIndex attribute, in case of changes to tabIndex or disabled
+ * state.
+ *
+ * @return $this
+ */
+ public function updateTabIndex() {
+ $disabled = $this->isDisabled();
+ if ( $this->tabIndex !== null ) {
+ $this->tabIndexed->setAttributes( [
+ // Do not index over disabled elements
+ 'tabindex' => $disabled ? -1 : $this->tabIndex,
+ // ChromeVox and NVDA do not seem to inherit this from parent elements
+ 'aria-disabled' => ( $disabled ? 'true' : 'false' )
+ ] );
+ } else {
+ $this->tabIndexed->removeAttributes( [ 'tabindex', 'aria-disabled' ] );
+ }
+ return $this;
+ }
+
+ /**
+ * Get tab index value.
+ *
+ * @return number|null Tab index value
+ */
+ public function getTabIndex() {
+ return $this->tabIndex;
+ }
+
+ /**
+ * Get an ID of a focusable element of this widget, if any, to be used for `<label for>` value.
+ *
+ * If the element already has an ID then that is returned, otherwise unique ID is
+ * generated, set on the element, and returned.
+ *
+ * @return string|null The ID of the focusable element
+ */
+ public function getInputId() {
+ $id = $this->tabIndexed->getAttribute( 'id' );
+
+ if ( !$this->isLabelableNode( $this->tabIndexed ) ) {
+ return null;
+ }
+
+ if ( $id === null ) {
+ $id = Tag::generateElementId();
+ $this->tabIndexed->setAttributes( [ 'id' => $id ] );
+ }
+
+ return $id;
+ }
+
+ /**
+ * Whether the node is 'labelable' according to the HTML spec
+ * (i.e., whether it can be interacted with through a `<label for="…">`).
+ * See: <https://html.spec.whatwg.org/multipage/forms.html#category-label>.
+ *
+ * @param Tag $tag
+ * @return boolean
+ */
+ private function isLabelableNode( Tag $tag ) {
+ $labelableTags = [ 'button', 'meter', 'output', 'progress', 'select', 'textarea' ];
+ $tagName = strtolower( $tag->getTag() );
+
+ if ( $tagName === 'input' && $tag->getAttribute( 'type' ) !== 'hidden' ) {
+ return true;
+ }
+ if ( in_array( $tagName, $labelableTags, true ) ) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/mixins/TitledElement.php b/www/wiki/vendor/oojs/oojs-ui/php/mixins/TitledElement.php
new file mode 100644
index 00000000..16ed98e4
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/mixins/TitledElement.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Element with a title.
+ *
+ * Titles are rendered by the browser and are made visible when hovering the element. Titles are
+ * not visible on touch devices.
+ *
+ * @abstract
+ */
+trait TitledElement {
+ /**
+ * Title text.
+ *
+ * @var string
+ */
+ protected $title = null;
+
+ /**
+ * @var Element
+ */
+ protected $titled;
+
+ /**
+ * @param array $config Configuration options
+ * @param string $config['title'] Title. If not provided, the static property 'title' is used.
+ */
+ public function initializeTitledElement( array $config = [] ) {
+ // Properties
+ $this->titled = isset( $config['titled'] ) ? $config['titled'] : $this;
+
+ // Initialization
+ $this->setTitle(
+ isset( $config['title'] ) ? $config['title'] : null
+ );
+
+ $this->registerConfigCallback( function ( &$config ) {
+ if ( $this->title !== null ) {
+ $config['title'] = $this->title;
+ }
+ } );
+ }
+
+ /**
+ * Set title.
+ *
+ * @param string|null $title Title text or null for no title
+ * @return $this
+ */
+ public function setTitle( $title ) {
+ $title = $title !== '' ? $title : null;
+
+ if ( $this->title !== $title ) {
+ $this->title = $title;
+ $this->updateTitle();
+ }
+
+ return $this;
+ }
+
+ /**
+ * Update the title attribute, in case of changes to title or accessKey.
+ *
+ * @return $this
+ */
+ protected function updateTitle() {
+ $title = $this->getTitle();
+ if ( $title !== null ) {
+ // Only if this is an AccessKeyedElement
+ if ( method_exists( $this, 'formatTitleWithAccessKey' ) ) {
+ $title = $this->formatTitleWithAccessKey( $title );
+ }
+ $this->titled->setAttributes( [ 'title' => $title ] );
+ } else {
+ $this->titled->removeAttributes( [ 'title' ] );
+ }
+ return $this;
+ }
+
+ /**
+ * Get title.
+ *
+ * @return string Title string
+ */
+ public function getTitle() {
+ return $this->title;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/themes/ApexTheme.php b/www/wiki/vendor/oojs/oojs-ui/php/themes/ApexTheme.php
new file mode 100644
index 00000000..e812736e
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/themes/ApexTheme.php
@@ -0,0 +1,6 @@
+<?php
+
+namespace OOUI;
+
+class ApexTheme extends Theme {
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/themes/BlankTheme.php b/www/wiki/vendor/oojs/oojs-ui/php/themes/BlankTheme.php
new file mode 100644
index 00000000..fa27c479
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/themes/BlankTheme.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace OOUI;
+
+class BlankTheme extends Theme {
+
+ /* Methods */
+
+ public function getElementClasses( Element $element ) {
+ // Parent method
+ $classes = parent::getElementClasses( $element );
+
+ // Add classes to $classes['on'] or $classes['off']
+
+ return $classes;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/themes/WikimediaUITheme.php b/www/wiki/vendor/oojs/oojs-ui/php/themes/WikimediaUITheme.php
new file mode 100644
index 00000000..f0219334
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/themes/WikimediaUITheme.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace OOUI;
+
+class WikimediaUITheme extends Theme {
+
+ /* Methods */
+
+ public function getElementClasses( Element $element ) {
+ $variants = [
+ 'warning' => false,
+ 'invert' => false,
+ 'progressive' => false,
+ 'destructive' => false
+ ];
+
+ // Parent method
+ $classes = parent::getElementClasses( $element );
+
+ if (
+ $element instanceof IconWidget &&
+ $element->hasClass( 'oo-ui-checkboxInputWidget-checkIcon' )
+ ) {
+ // Icon on CheckboxInputWidget
+ $variants['invert'] = true;
+ } elseif ( $element->supports( [ 'hasFlag' ] ) ) {
+ $isFramed = $element->supports( [ 'isFramed' ] ) && $element->isFramed();
+ $isActive = $element->supports( [ 'isActive' ] ) && $element->isActive();
+ if ( $isFramed && ( $isActive || $element->isDisabled() || $element->hasFlag( 'primary' ) ) ) {
+ // Button with a dark background, use white icon
+ $variants['invert'] = true;
+ } elseif ( !$isFramed && $element->isDisabled() ) {
+ // Frameless disabled button, always use black icon regardless of flags
+ $variants['invert'] = false;
+ } elseif ( !$element->isDisabled() ) {
+ // Any other kind of button, use the right colored icon if available
+ $variants['progressive'] = $element->hasFlag( 'progressive' );
+ $variants['destructive'] = $element->hasFlag( 'destructive' );
+ $variants['warning'] = $element->hasFlag( 'warning' );
+ }
+ }
+
+ foreach ( $variants as $variant => $toggle ) {
+ $classes[$toggle ? 'on' : 'off'][] = 'oo-ui-image-' . $variant;
+ }
+
+ return $classes;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonGroupWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonGroupWidget.php
new file mode 100644
index 00000000..2937705c
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonGroupWidget.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Group widget for multiple related buttons.
+ *
+ * Use together with ButtonWidget.
+ */
+class ButtonGroupWidget extends Widget {
+ use GroupElement;
+
+ /* Static Properties */
+
+ public static $tagName = 'span';
+
+ /**
+ * @param array $config Configuration options
+ * @param ButtonWidget[] $config['items'] Buttons to add
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Traits
+ $this->initializeGroupElement( array_merge( $config, [ 'group' => $this ] ) );
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-buttonGroupWidget' ] );
+ if ( isset( $config['items'] ) ) {
+ $this->addItems( $config['items'] );
+ }
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonInputWidget.php
new file mode 100644
index 00000000..b356f7cd
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonInputWidget.php
@@ -0,0 +1,123 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * A button that is an input widget. Intended to be used within a FormLayout.
+ */
+class ButtonInputWidget extends InputWidget {
+ use ButtonElement;
+ use IconElement;
+ use IndicatorElement;
+ use LabelElement {
+ LabelElement::setLabel as setLabelElementLabel;
+ }
+
+ /* Static Properties */
+
+ public static $tagName = 'span';
+
+ /* Properties */
+
+ /**
+ * Whether to use `<input>` rather than `<button>`.
+ *
+ * @var boolean
+ */
+ protected $useInputTag;
+
+ /**
+ * @param array $config Configuration options
+ * @param string $config['type'] HTML tag `type` attribute, may be 'button', 'submit' or 'reset'
+ * (default: 'button')
+ * @param bool $config['useInputTag'] Whether to use `<input>` rather than `<button>`. Only
+ * useful if you need IE 6 support in a form with multiple buttons. If you use this option,
+ * icons and indicators will not be displayed, it won't be possible to have a non-plaintext
+ * label, and it won't be possible to set a value (which will internally become identical to the
+ * label). (default: false)
+ */
+ public function __construct( array $config = [] ) {
+ // Configuration initialization
+ $config = array_merge( [ 'type' => 'button', 'useInputTag' => false ], $config );
+
+ // Properties (must be set before parent constructor, which calls setValue())
+ $this->useInputTag = $config['useInputTag'];
+
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Traits
+ $this->initializeButtonElement(
+ array_merge( $config, [ 'button' => $this->input ] ) );
+ $this->initializeIconElement( $config );
+ $this->initializeIndicatorElement( $config );
+ $this->initializeLabelElement( $config );
+ $this->initializeTitledElement(
+ array_merge( $config, [ 'titled' => $this->input ] ) );
+
+ // Initialization
+ if ( !$config['useInputTag'] ) {
+ $this->input->appendContent( $this->icon, $this->label, $this->indicator );
+ }
+
+ $this->addClasses( [ 'oo-ui-buttonInputWidget' ] );
+ }
+
+ protected function getInputElement( $config ) {
+ $type = in_array( $config['type'], [ 'button', 'submit', 'reset' ] ) ?
+ $config['type'] :
+ 'button';
+ $tag = $config['useInputTag'] ? 'input' : 'button';
+ return ( new Tag( $tag ) )->setAttributes( [ 'type' => $type ] );
+ }
+
+ /**
+ * Set label value.
+ *
+ * Overridden to support setting the 'value' of `<input>` elements.
+ *
+ * @param string|null $label Label text
+ * @return $this
+ */
+ public function setLabel( $label ) {
+ if ( $this->useInputTag ) {
+ // Discard non-plaintext labels
+ if ( !is_string( $label ) ) {
+ $label = '';
+ }
+
+ $this->input->setValue( $label );
+ }
+
+ return $this->setLabelElementLabel( $label );
+ }
+
+ /**
+ * Set the value of the input.
+ *
+ * Overridden to disable for `<input>` elements, which have value identical to the label.
+ *
+ * @param string $value New value
+ * @return $this
+ */
+ public function setValue( $value ) {
+ if ( !$this->useInputTag ) {
+ parent::setValue( $value );
+ }
+ return $this;
+ }
+
+ public function getInputId() {
+ // Disable generating `<label>` elements for buttons. One would very rarely need additional label
+ // for a button, and it's already a big clickable target, and it causes unexpected rendering.
+ return null;
+ }
+
+ public function getConfig( &$config ) {
+ if ( $this->useInputTag ) {
+ $config['useInputTag'] = true;
+ }
+ $config['type'] = $this->input->getAttribute( 'type' );
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonWidget.php
new file mode 100644
index 00000000..1312ca95
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/ButtonWidget.php
@@ -0,0 +1,220 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Generic widget for buttons.
+ */
+class ButtonWidget extends Widget {
+ use ButtonElement;
+ use IconElement;
+ use IndicatorElement;
+ use LabelElement;
+ use TitledElement;
+ use FlaggedElement;
+ use TabIndexedElement;
+ use AccessKeyedElement;
+
+ /* Static Properties */
+
+ public static $tagName = 'span';
+
+ /* Properties */
+
+ /**
+ * Whether button is active.
+ *
+ * @var boolean
+ */
+ protected $active = false;
+
+ /**
+ * Hyperlink to visit when clicked.
+ *
+ * @var string
+ */
+ protected $href = null;
+
+ /**
+ * Target to open hyperlink in.
+ *
+ * @var string
+ */
+ protected $target = null;
+
+ /**
+ * Search engine traversal hint.
+ *
+ * True if search engines should avoid following this hyperlink.
+ *
+ * @var boolean
+ */
+ protected $noFollow = true;
+
+ /**
+ * @param array $config Configuration options
+ * @param bool $config['active'] Whether button should be shown as active (default: false)
+ * @param string $config['href'] Hyperlink to visit when clicked
+ * @param string $config['target'] Target to open hyperlink in
+ * @param bool $config['noFollow'] Search engine traversal hint (default: true)
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Traits
+ $this->initializeButtonElement( $config );
+ $this->initializeIconElement( $config );
+ $this->initializeIndicatorElement( $config );
+ $this->initializeLabelElement( $config );
+ $this->initializeTitledElement(
+ array_merge( $config, [ 'titled' => $this->button ] ) );
+ $this->initializeFlaggedElement( $config );
+ $this->initializeTabIndexedElement(
+ array_merge( $config, [ 'tabIndexed' => $this->button ] ) );
+ $this->initializeAccessKeyedElement(
+ array_merge( $config, [ 'accessKeyed' => $this->button ] ) );
+
+ // Initialization
+ $this->button->appendContent( $this->icon, $this->label, $this->indicator );
+ $this
+ ->addClasses( [ 'oo-ui-buttonWidget' ] )
+ ->appendContent( $this->button );
+
+ $this->setActive( isset( $config['active'] ) ? $config['active'] : false );
+ $this->setHref( isset( $config['href'] ) ? $config['href'] : null );
+ $this->setTarget( isset( $config['target'] ) ? $config['target'] : null );
+ $this->setNoFollow( isset( $config['noFollow'] ) ? $config['noFollow'] : true );
+ }
+
+ /**
+ * Get hyperlink location.
+ *
+ * @return string Hyperlink location
+ */
+ public function getHref() {
+ return $this->href;
+ }
+
+ /**
+ * Get hyperlink target.
+ *
+ * @return string Hyperlink target
+ */
+ public function getTarget() {
+ return $this->target;
+ }
+
+ /**
+ * Get search engine traversal hint.
+ *
+ * @return bool Whether search engines should avoid traversing this hyperlink
+ */
+ public function getNoFollow() {
+ return $this->noFollow;
+ }
+
+ /**
+ * Set hyperlink location.
+ *
+ * @param string|null $href Hyperlink location, null to remove
+ * @return $this
+ */
+ public function setHref( $href ) {
+ $this->href = is_string( $href ) ? $href : null;
+
+ $this->updateHref();
+
+ return $this;
+ }
+
+ /**
+ * Update the href attribute, in case of changes to href or disabled
+ * state.
+ *
+ * @return $this
+ */
+ public function updateHref() {
+ if ( $this->href !== null && !$this->isDisabled() ) {
+ $this->button->setAttributes( [ 'href' => $this->href ] );
+ } else {
+ $this->button->removeAttributes( [ 'href' ] );
+ }
+ return $this;
+ }
+
+ /**
+ * Set hyperlink target.
+ *
+ * @param string|null $target Hyperlink target, null to remove
+ * @return $this
+ */
+ public function setTarget( $target ) {
+ $this->target = is_string( $target ) ? $target : null;
+
+ if ( $this->target !== null ) {
+ $this->button->setAttributes( [ 'target' => $target ] );
+ } else {
+ $this->button->removeAttributes( [ 'target' ] );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set search engine traversal hint.
+ *
+ * @param bool $noFollow True if search engines should avoid traversing this hyperlink
+ * @return $this
+ */
+ public function setNoFollow( $noFollow ) {
+ $this->noFollow = is_bool( $noFollow ) ? $noFollow : true;
+
+ if ( $this->noFollow ) {
+ $this->button->setAttributes( [ 'rel' => 'nofollow' ] );
+ } else {
+ $this->button->removeAttributes( [ 'rel' ] );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Toggle active state.
+ *
+ * A button should be marked as active when clicking it would only refresh the page.
+ *
+ * @param bool $active Make button active
+ * @return $this
+ */
+ public function setActive( $active = null ) {
+ $this->active = !!$active;
+ $this->toggleClasses( [ 'oo-ui-buttonElement-active' ], $this->active );
+ return $this;
+ }
+
+ /**
+ * Check if button is active.
+ *
+ * @return bool Button is active
+ */
+ public function isActive() {
+ return $this->active;
+ }
+
+ public function getConfig( &$config ) {
+ if ( $this->active !== false ) {
+ $config['active'] = $this->active;
+ }
+ if ( $this->href !== null ) {
+ $config['href'] = $this->href;
+ }
+ if ( $this->target !== null ) {
+ $config['target'] = $this->target;
+ }
+ if ( $this->noFollow !== true ) {
+ $config['noFollow'] = $this->noFollow;
+ }
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/CheckboxInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/CheckboxInputWidget.php
new file mode 100644
index 00000000..3a779b55
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/CheckboxInputWidget.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Checkbox input widget.
+ */
+class CheckboxInputWidget extends InputWidget {
+
+ /* Static Properties */
+
+ public static $tagName = 'span';
+
+ /* Properties */
+
+ /**
+ * Whether the checkbox is selected.
+ *
+ * @var boolean
+ */
+ protected $selected;
+
+ /**
+ * @param array $config Configuration options
+ * @param bool $config['selected'] Whether the checkbox is initially selected
+ * (default: false)
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Properties
+ $this->checkIcon = new IconWidget( [
+ 'icon' => 'check',
+ 'classes' => [ 'oo-ui-checkboxInputWidget-checkIcon' ],
+ ] );
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-checkboxInputWidget' ] );
+ // Required for pretty styling in WikimediaUI theme
+ $this->appendContent( $this->checkIcon );
+ $this->setSelected( isset( $config['selected'] ) ? $config['selected'] : false );
+ }
+
+ protected function getInputElement( $config ) {
+ return ( new Tag( 'input' ) )->setAttributes( [ 'type' => 'checkbox' ] );
+ }
+
+ /**
+ * Set selection state of this checkbox.
+ *
+ * @param bool $state Whether the checkbox is selected
+ * @return $this
+ */
+ public function setSelected( $state ) {
+ $this->selected = (bool)$state;
+ if ( $this->selected ) {
+ $this->input->setAttributes( [ 'checked' => 'checked' ] );
+ } else {
+ $this->input->removeAttributes( [ 'checked' ] );
+ }
+ return $this;
+ }
+
+ /**
+ * Check if this checkbox is selected.
+ *
+ * @return bool Checkbox is selected
+ */
+ public function isSelected() {
+ return $this->selected;
+ }
+
+ public function getConfig( &$config ) {
+ if ( $this->selected ) {
+ $config['selected'] = $this->selected;
+ }
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/CheckboxMultiselectInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/CheckboxMultiselectInputWidget.php
new file mode 100644
index 00000000..01a63ddd
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/CheckboxMultiselectInputWidget.php
@@ -0,0 +1,155 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Multiple checkbox input widget. Intended to be used within a OO.ui.FormLayout.
+ */
+class CheckboxMultiselectInputWidget extends InputWidget {
+
+ /* Properties */
+
+ /**
+ * @var string|null
+ */
+ protected $name = null;
+
+ /**
+ * Input value.
+ *
+ * @var string[]
+ */
+ protected $value = [];
+
+ /**
+ * Layouts for this input, as FieldLayouts.
+ *
+ * @var array
+ */
+ protected $fields = [];
+
+ /**
+ * @param array $config Configuration options
+ * @param array[] $config['options'] Array of menu options in the format
+ * `[ 'data' => …, 'label' => …, 'disabled' => … ]`
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ if ( isset( $config['name'] ) ) {
+ $this->name = $config['name'];
+ }
+
+ // Initialization
+ $this->setOptions( isset( $config['options'] ) ? $config['options'] : [] );
+ // Have to repeat this from parent, as we need options to be set up for this to make sense
+ $this->setValue( isset( $config['value'] ) ? $config['value'] : null );
+ $this->addClasses( [ 'oo-ui-checkboxMultiselectInputWidget' ] );
+ }
+
+ protected function getInputElement( $config ) {
+ // Actually unused
+ return new Tag( 'unused' );
+ }
+
+ /**
+ * Set the value of the input.
+ *
+ * @param string[] $value New value
+ * @return $this
+ */
+ public function setValue( $value ) {
+ $this->value = $this->cleanUpValue( $value );
+ // Deselect all options
+ foreach ( $this->fields as $field ) {
+ $field->getField()->setSelected( false );
+ }
+ // Select the requested ones
+ foreach ( $this->value as $key ) {
+ $this->fields[ $key ]->getField()->setSelected( true );
+ }
+ return $this;
+ }
+
+ /**
+ * Clean up incoming value.
+ *
+ * @param string[] $value Original value
+ * @return string[] Cleaned up value
+ */
+ protected function cleanUpValue( $value ) {
+ $cleanValue = [];
+ if ( !is_array( $value ) ) {
+ return $cleanValue;
+ }
+ foreach ( $value as $singleValue ) {
+ $singleValue = parent::cleanUpValue( $singleValue );
+ // Remove options that we don't have here
+ if ( !isset( $this->fields[ $singleValue ] ) ) {
+ continue;
+ }
+ $cleanValue[] = $singleValue;
+ }
+ return $cleanValue;
+ }
+
+ /**
+ * Set the options available for this input.
+ *
+ * @param array[] $options Array of menu options in the format
+ * `[ 'data' => …, 'label' => …, 'disabled' => … ]`
+ * @return $this
+ */
+ public function setOptions( $options ) {
+ $this->fields = [];
+
+ // Rebuild the checkboxes
+ $this->clearContent();
+ $name = $this->name;
+ foreach ( $options as $opt ) {
+ $optValue = parent::cleanUpValue( $opt['data'] );
+ $optDisabled = isset( $opt['disabled'] ) ? $opt['disabled'] : false;
+ $field = new FieldLayout(
+ new CheckboxInputWidget( [
+ 'name' => $name,
+ 'value' => $optValue,
+ 'disabled' => $this->isDisabled() || $optDisabled,
+ ] ),
+ [
+ 'label' => isset( $opt['label'] ) ? $opt['label'] : $optValue,
+ 'align' => 'inline',
+ ]
+ );
+
+ $this->fields[ $optValue ] = $field;
+ $this->appendContent( $field );
+ }
+
+ // Re-set the value, checking the checkboxes as needed.
+ // This will also get rid of any stale options that we just removed.
+ $this->setValue( $this->getValue() );
+
+ return $this;
+ }
+
+ public function setDisabled( $state ) {
+ parent::setDisabled( $state );
+ foreach ( $this->fields as $field ) {
+ $field->getField()->setDisabled( $this->isDisabled() );
+ }
+ return $this;
+ }
+
+ public function getConfig( &$config ) {
+ $o = [];
+ foreach ( $this->fields as $field ) {
+ $label = $field->getLabel();
+ $data = $field->getField()->getValue();
+ $disabled = $field->getField()->isDisabled();
+ $o[] = [ 'data' => $data, 'label' => $label, 'disabled' => $disabled ];
+ }
+ $config['options'] = $o;
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/ComboBoxInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/ComboBoxInputWidget.php
new file mode 100644
index 00000000..d2fe4712
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/ComboBoxInputWidget.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Combo box input widget, wrapping a text input with `<datalist>`. Intended to be used within a
+ * OO.ui.FormLayout.
+ */
+class ComboBoxInputWidget extends TextInputWidget {
+ /**
+ * HTML `<option>` tags for this widget, as Tags.
+ * @var array
+ */
+ protected $options = [];
+
+ /**
+ * @param array $config Configuration options
+ * @param array[] $config['options'] Array of menu options in the format
+ * `[ 'data' => …, 'label' => … ]`
+ */
+ public function __construct( array $config = [] ) {
+ // ComboBoxInputWidget shouldn't support `multiline`
+ $config['multiline'] = false;
+
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Initialization
+ $this->forceAutocomplete = isset( $config['autocomplete'] ) ? $config['autocomplete'] : false;
+ $this->downIndicator = new IndicatorWidget( [ 'indicator' => 'down' ] );
+ $this->datalist = new Tag( 'datalist' );
+ $this->datalist->setAttributes( [ 'id' => Tag::generateElementId() ] );
+ $this->input->setAttributes( [ 'list' => $this->datalist->getAttribute( 'id' ) ] );
+
+ $this->setOptions( isset( $config['options'] ) ? $config['options'] : [] );
+ $this->addClasses( [ 'oo-ui-comboBoxInputWidget', 'oo-ui-comboBoxInputWidget-php' ] );
+ $this->appendContent( $this->downIndicator, $this->datalist );
+ }
+
+ /**
+ * Set the options available for this input.
+ *
+ * @param array[] $options Array of menu options in the format
+ * `[ 'data' => …, 'label' => … ]`
+ * @return $this
+ */
+ public function setOptions( $options ) {
+ $this->options = [];
+
+ $this->datalist->clearContent();
+ foreach ( $options as $opt ) {
+ $option = ( new Tag( 'option' ) )
+ ->setAttributes( [ 'value' => $opt['data'] ] )
+ ->appendContent( isset( $opt['label'] ) ? $opt['label'] : $opt['data'] );
+
+ $this->options[] = $option;
+ $this->datalist->appendContent( $option );
+ }
+
+ return $this;
+ }
+
+ public function getConfig( &$config ) {
+ $o = [];
+ foreach ( $this->options as $option ) {
+ $label = $option->content[0];
+ $data = $option->getAttribute( 'value' );
+ $o[] = [ 'data' => $data, 'label' => $label ];
+ }
+ $config['options'] = $o;
+ // JS ComboBoxInputWidget has `autocomplete: false` in the defaults. Make sure
+ // explicitly passing `autocomplete: true` overrides that. Doing so doesn't make
+ // much sense, this is just to make the tests happy.
+ if ( $this->forceAutocomplete ) {
+ $config['autocomplete'] = true;
+ }
+ $config['$overlay'] = true;
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/DropdownInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/DropdownInputWidget.php
new file mode 100644
index 00000000..a453b7b0
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/DropdownInputWidget.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Dropdown input widget, wrapping a `<select>` element. Intended to be used within a
+ * OO.ui.FormLayout.
+ */
+class DropdownInputWidget extends InputWidget {
+ /**
+ * HTML `<option>` tags for this widget, as Tags.
+ * @var array
+ */
+ protected $options = [];
+
+ /**
+ * @param array $config Configuration options
+ * @param array[] $config['options'] Array of menu options in the format
+ * `[ 'data' => …, 'label' => … ]`
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Initialization
+ $this->setOptions( isset( $config['options'] ) ? $config['options'] : [] );
+ $this->addClasses( [ 'oo-ui-dropdownInputWidget', 'oo-ui-dropdownInputWidget-php' ] );
+ $this->input->addClasses( [ 'oo-ui-indicator-down' ] );
+ }
+
+ protected function getInputElement( $config ) {
+ return new Tag( 'select' );
+ }
+
+ public function setValue( $value ) {
+ $this->value = $this->cleanUpValue( $value );
+ foreach ( $this->options as &$opt ) {
+ if ( $opt->getAttribute( 'value' ) === $this->value ) {
+ $opt->setAttributes( [ 'selected' => 'selected' ] );
+ } else {
+ $opt->removeAttributes( [ 'selected' ] );
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Set the options available for this input.
+ *
+ * @param array[] $options Array of menu options in the format
+ * `[ 'data' => …, 'label' => … ]`
+ * @return $this
+ */
+ public function setOptions( $options ) {
+ $value = $this->getValue();
+ $isValueAvailable = false;
+ $this->options = [];
+ $container = $this->input;
+
+ // Rebuild the dropdown menu
+ $this->input->clearContent();
+ foreach ( $options as $opt ) {
+ if ( empty( $opt['optgroup'] ) ) {
+ $optValue = $this->cleanUpValue( $opt['data'] );
+ $option = ( new Tag( 'option' ) )
+ ->setAttributes( [ 'value' => $optValue ] )
+ ->appendContent( isset( $opt['label'] ) ? $opt['label'] : $optValue );
+
+ if ( $value === $optValue ) {
+ $isValueAvailable = true;
+ }
+ $container->appendContent( $option );
+ } else {
+ $option = ( new Tag( 'optgroup' ) )
+ ->setAttributes( [ 'label' => $opt['optgroup'] ] );
+ $this->input->appendContent( $option );
+ $container = $option;
+ }
+
+ $this->options[] = $option;
+ }
+
+ // Restore the previous value, or reset to something sensible
+ if ( $isValueAvailable ) {
+ // Previous value is still available
+ $this->setValue( $value );
+ } else {
+ // No longer valid, reset
+ if ( count( $options ) ) {
+ $this->setValue( $options[0]['data'] );
+ }
+ }
+
+ return $this;
+ }
+
+ public function getConfig( &$config ) {
+ $o = [];
+ foreach ( $this->options as $option ) {
+ if ( $option->getTag() !== 'optgroup' ) {
+ $label = $option->content[0];
+ $data = $option->getAttribute( 'value' );
+ $o[] = [ 'data' => $data, 'label' => $label ];
+ } else {
+ $optgroup = $option->getAttribute( 'label' );
+ $o[] = [ 'optgroup' => $optgroup ];
+ }
+ }
+ $config['options'] = $o;
+ $config['dropdown']['$overlay'] = true;
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/HiddenInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/HiddenInputWidget.php
new file mode 100644
index 00000000..d848139f
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/HiddenInputWidget.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Data widget intended for creating 'hidden'-type inputs.
+ */
+class HiddenInputWidget extends Widget {
+
+ /**
+ * @var string
+ */
+ public static $tagName = 'input';
+
+ /**
+ * DataWidget constructor.
+ *
+ * @param array $config Configuration options
+ * @param string $config['value'] The data the input contains. (default: '')
+ * @param string $config['name'] The name of the hidden input. (default: '')
+ */
+ public function __construct( array $config ) {
+ // Configuration initialization
+ $config = array_merge( [ 'value' => '', 'name' => '' ], $config );
+
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Initialization
+ $this->setAttributes( [
+ 'type' => 'hidden',
+ 'value' => $config['value'],
+ 'name' => $config['name'],
+ ] );
+ $this->removeAttributes( [ 'aria-disabled' ] );
+ }
+
+ public function getConfig( &$config ) {
+ $config['value'] = $this->getAttribute( 'value' );
+ $config['name'] = $this->getAttribute( 'name' );
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/IconWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/IconWidget.php
new file mode 100644
index 00000000..c90b385d
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/IconWidget.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Icon widget.
+ *
+ * See IconElement for more information.
+ */
+class IconWidget extends Widget {
+ use IconElement;
+ use TitledElement;
+ use FlaggedElement;
+
+ /* Static Properties */
+
+ public static $tagName = 'span';
+
+ /**
+ * @param array $config Configuration options
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Traits
+ $this->initializeIconElement(
+ array_merge( $config, [ 'iconElement' => $this ] ) );
+ $this->initializeTitledElement(
+ array_merge( $config, [ 'titled' => $this ] ) );
+ $this->initializeFlaggedElement( array_merge( $config, [ 'flagged' => $this ] ) );
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-iconWidget' ] );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/IndicatorWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/IndicatorWidget.php
new file mode 100644
index 00000000..8f36a636
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/IndicatorWidget.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Indicator widget.
+ *
+ * See IndicatorElement for more information.
+ */
+class IndicatorWidget extends Widget {
+ use IndicatorElement;
+ use TitledElement;
+
+ /* Static Properties */
+
+ public static $tagName = 'span';
+
+ /**
+ * @param array $config Configuration options
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Traits
+ $this->initializeIndicatorElement(
+ array_merge( $config, [ 'indicatorElement' => $this ] ) );
+ $this->initializeTitledElement(
+ array_merge( $config, [ 'titled' => $this ] ) );
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-indicatorWidget' ] );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/InputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/InputWidget.php
new file mode 100644
index 00000000..2601dbcd
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/InputWidget.php
@@ -0,0 +1,170 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Base class for input widgets.
+ *
+ * @abstract
+ */
+class InputWidget extends Widget {
+ use FlaggedElement;
+ use TabIndexedElement;
+ use TitledElement;
+ use AccessKeyedElement;
+
+ /* Properties */
+
+ /**
+ * Input element.
+ *
+ * @var Tag
+ */
+ protected $input;
+
+ /**
+ * Input value.
+ *
+ * @var string
+ */
+ protected $value = '';
+
+ /**
+ * @param array $config Configuration options
+ * @param string $config['name'] HTML input name (default: '')
+ * @param string $config['value'] Input value (default: '')
+ * @param string $config['dir'] The directionality of the input (ltr/rtl)
+ * @param string $config['inputId'] The value of the input’s HTML `id` attribute.
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Properties
+ $this->input = $this->getInputElement( $config );
+
+ // Traits
+ $this->initializeFlaggedElement( array_merge( $config, [ 'flagged' => $this ] ) );
+ $this->initializeTabIndexedElement(
+ array_merge( $config, [ 'tabIndexed' => $this->input ] ) );
+ $this->initializeTitledElement(
+ array_merge( $config, [ 'titled' => $this->input ] ) );
+ $this->initializeAccessKeyedElement(
+ array_merge( $config, [ 'accessKeyed' => $this->input ] ) );
+
+ // Initialization
+ if ( isset( $config['name'] ) ) {
+ $this->input->setAttributes( [ 'name' => $config['name'] ] );
+ }
+ if ( $this->isDisabled() ) {
+ $this->input->setAttributes( [ 'disabled' => 'disabled' ] );
+ }
+ $this
+ ->addClasses( [ 'oo-ui-inputWidget' ] )
+ ->appendContent( $this->input );
+ $this->input->addClasses( [ 'oo-ui-inputWidget-input' ] );
+ $this->setValue( isset( $config['value'] ) ? $config['value'] : null );
+ if ( isset( $config['dir'] ) ) {
+ $this->setDir( $config['dir'] );
+ }
+ if ( isset( $config['inputId'] ) ) {
+ $this->setInputId( $config['inputId'] );
+ }
+ }
+
+ /**
+ * Get input element.
+ *
+ * @param array $config Configuration options
+ * @return Tag Input element
+ */
+ protected function getInputElement( $config ) {
+ return new Tag( 'input' );
+ }
+
+ /**
+ * Get the value of the input.
+ *
+ * @return string Input value
+ */
+ public function getValue() {
+ return $this->value;
+ }
+
+ /**
+ * Set the directionality of the input.
+ *
+ * @param string $dir Text directionality: 'ltr', 'rtl' or 'auto'
+ * @return $this
+ */
+ public function setDir( $dir ) {
+ $this->input->setAttributes( [ 'dir' => $dir ] );
+ return $this;
+ }
+
+ /**
+ * Set the value of the input.
+ *
+ * @param string $value New value
+ * @return $this
+ */
+ public function setValue( $value ) {
+ $this->value = $this->cleanUpValue( $value );
+ $this->input->setValue( $this->value );
+ return $this;
+ }
+
+ /**
+ * Clean up incoming value.
+ *
+ * Ensures value is a string, and converts null to empty string.
+ *
+ * @param string $value Original value
+ * @return string Cleaned up value
+ */
+ protected function cleanUpValue( $value ) {
+ if ( $value === null ) {
+ return '';
+ } else {
+ return (string)$value;
+ }
+ }
+
+ public function setDisabled( $state ) {
+ parent::setDisabled( $state );
+ if ( isset( $this->input ) ) {
+ if ( $this->isDisabled() ) {
+ $this->input->setAttributes( [ 'disabled' => 'disabled' ] );
+ } else {
+ $this->input->removeAttributes( [ 'disabled' ] );
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Set the 'id' attribute of the `<input>` element.
+ *
+ * @param string $id The ID of the input element
+ * @return $this
+ */
+ public function setInputId( $id ) {
+ $this->input->setAttributes( [ 'id' => $id ] );
+ return $this;
+ }
+
+ public function getConfig( &$config ) {
+ $name = $this->input->getAttribute( 'name' );
+ if ( $name !== null ) {
+ $config['name'] = $name;
+ }
+ if ( $this->value !== '' ) {
+ $config['value'] = $this->value;
+ }
+ $id = $this->input->getAttribute( 'id' );
+ if ( $id !== null ) {
+ $config['inputId'] = $id;
+ }
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/LabelWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/LabelWidget.php
new file mode 100644
index 00000000..593840cf
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/LabelWidget.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Label widget.
+ */
+class LabelWidget extends Widget {
+ use LabelElement;
+
+ /* Static Properties */
+
+ public static $tagName = 'label';
+
+ /* Properties */
+
+ /**
+ * Associated input element.
+ *
+ * @var InputWidget|null
+ */
+ protected $input;
+
+ /**
+ * @param array $config Configuration options
+ * @param InputWidget $config['input'] Input widget this label is for
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Traits
+ $this->initializeLabelElement(
+ array_merge( $config, [ 'labelElement' => $this ] ) );
+
+ // Properties
+ $this->input = isset( $config['input'] ) ? $config['input'] : null;
+
+ // Initialization
+ if ( $this->input && $this->input->getInputId() ) {
+ $this->setAttributes( [ 'for' => $this->input->getInputId() ] );
+ }
+ $this->addClasses( [ 'oo-ui-labelWidget' ] );
+ }
+
+ public function getConfig( &$config ) {
+ if ( $this->input !== null ) {
+ $config['input'] = $this->input;
+ }
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/MultilineTextInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/MultilineTextInputWidget.php
new file mode 100644
index 00000000..81e3eb0d
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/MultilineTextInputWidget.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Input widget with a text field.
+ */
+class MultilineTextInputWidget extends TextInputWidget {
+
+ /**
+ * Allow multiple lines of text.
+ *
+ * @var boolean
+ */
+ protected $multiline = true;
+
+ /**
+ * @param array $config Configuration options
+ * @param int $config['rows'] If multiline, number of visible lines in textarea
+ */
+ public function __construct( array $config = [] ) {
+ // Config initialization
+ $config = array_merge( [
+ 'readOnly' => false,
+ 'autofocus' => false,
+ 'required' => false,
+ 'multiline' => true,
+ ], $config );
+
+ // Parent constructor
+ parent::__construct( $config );
+ }
+
+ /**
+ * Check if input supports multiple lines.
+ *
+ * @return bool
+ */
+ public function isMultiline() {
+ return true;
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/ProgressBarWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/ProgressBarWidget.php
new file mode 100644
index 00000000..e49ea202
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/ProgressBarWidget.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace OOUI;
+
+class ProgressBarWidget extends Widget {
+ /**
+ * @var bool|int
+ */
+ protected $progress;
+
+ /**
+ * @var Tag
+ */
+ protected $bar;
+
+ /**
+ * @param array $config Configuration options
+ * @param bool|int $config['progress'] Numeric value between 0 and 100 (the percent complete)
+ * for determinate progress bar, or `false` for indeterminate progress bar (default: false)
+ */
+ public function __construct( array $config = [] ) {
+ parent::__construct( $config );
+
+ $this->bar = new Tag( 'div' );
+ $this->bar->addClasses( [ 'oo-ui-progressBarWidget-bar' ] );
+
+ $this->setProgress( array_key_exists( 'progress', $config ) ? $config['progress'] : false );
+
+ $this
+ ->setAttributes( [
+ 'role' => 'progressbar',
+ 'aria-valuemin' => 0,
+ 'aria-valuemax' => 100,
+ ] )
+ ->addClasses( [ 'oo-ui-progressBarWidget' ] )
+ ->appendContent( $this->bar );
+ }
+
+ /**
+ * @return bool|int
+ */
+ public function getProgress() {
+ return $this->progress;
+ }
+
+ /**
+ * @param bool|int $progress Numeric value between 0 and 100 (the percent complete)
+ * for determinate progress bar, or `false` for indeterminate progress bar (default: false)
+ */
+ public function setProgress( $progress ) {
+ $this->progress = $progress;
+
+ if ( $progress !== false ) {
+ $this->bar->setAttributes( [ 'style' => 'width: ' . $this->progress . '%;' ] );
+ $this->setAttributes( [ 'aria-valuenow' => $this->progress ] );
+ } else {
+ $this->removeAttributes( [ 'aria-valuenow' ] );
+ }
+ $this->toggleClasses( [ 'oo-ui-progressBarWidget-indeterminate' ], $progress === false );
+ }
+
+ public function getConfig( &$config ) {
+ if ( $this->progress !== null ) {
+ $config['progress'] = $this->progress;
+ }
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/RadioInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/RadioInputWidget.php
new file mode 100644
index 00000000..5f96a013
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/RadioInputWidget.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Radio input widget.
+ */
+class RadioInputWidget extends InputWidget {
+
+ /* Static Properties */
+
+ public static $tagName = 'span';
+
+ /**
+ * @param array $config Configuration options
+ * @param bool $config['selected'] Whether the radio button is initially selected
+ * (default: false)
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Initialization
+ $this->addClasses( [ 'oo-ui-radioInputWidget' ] );
+ // Required for pretty styling in WikimediaUI theme
+ $this->appendContent( new Tag( 'span' ) );
+ $this->setSelected( isset( $config['selected'] ) ? $config['selected'] : false );
+ }
+
+ protected function getInputElement( $config ) {
+ return ( new Tag( 'input' ) )->setAttributes( [ 'type' => 'radio' ] );
+ }
+
+ /**
+ * Set selection state of this radio button.
+ *
+ * @param bool $state Whether the button is selected
+ * @return $this
+ */
+ public function setSelected( $state ) {
+ // RadioInputWidget doesn't track its state.
+ if ( $state ) {
+ $this->input->setAttributes( [ 'checked' => 'checked' ] );
+ } else {
+ $this->input->removeAttributes( [ 'checked' ] );
+ }
+ return $this;
+ }
+
+ /**
+ * Check if this radio button is selected.
+ *
+ * @return bool Radio is selected
+ */
+ public function isSelected() {
+ return $this->input->getAttribute( 'checked' ) === 'checked';
+ }
+
+ public function getConfig( &$config ) {
+ if ( $this->isSelected() ) {
+ $config['selected'] = true;
+ }
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/RadioSelectInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/RadioSelectInputWidget.php
new file mode 100644
index 00000000..30492c6d
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/RadioSelectInputWidget.php
@@ -0,0 +1,126 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Multiple radio buttons input widget. Intended to be used within a OO.ui.FormLayout.
+ */
+class RadioSelectInputWidget extends InputWidget {
+
+ /* Properties */
+
+ /**
+ * @var string|null
+ */
+ protected $name = null;
+
+ /**
+ * Layouts for this input, as FieldLayouts.
+ *
+ * @var array
+ */
+ protected $fields = [];
+
+ /**
+ * @param array $config Configuration options
+ * @param array[] $config['options'] Array of menu options in the format
+ * `[ 'data' => …, 'label' => … ]`
+ */
+ public function __construct( array $config = [] ) {
+ // Parent constructor
+ parent::__construct( $config );
+
+ if ( isset( $config['name'] ) ) {
+ $this->name = $config['name'];
+ }
+
+ // Initialization
+ $this->setOptions( isset( $config['options'] ) ? $config['options'] : [] );
+ $this->addClasses( [ 'oo-ui-radioSelectInputWidget' ] );
+ }
+
+ protected function getInputElement( $config ) {
+ // Actually unused
+ return new Tag( 'unused' );
+ }
+
+ public function setValue( $value ) {
+ $this->value = $this->cleanUpValue( $value );
+ foreach ( $this->fields as &$field ) {
+ $field->getField()->setSelected( $field->getField()->getValue() === $this->value );
+ }
+ return $this;
+ }
+
+ /**
+ * Set the options available for this input.
+ *
+ * @param array[] $options Array of menu options in the format
+ * `[ 'data' => …, 'label' => … ]`
+ * @return $this
+ */
+ public function setOptions( $options ) {
+ $value = $this->getValue();
+ $isValueAvailable = false;
+ $this->fields = [];
+
+ // Rebuild the radio buttons
+ $this->clearContent();
+ // Need a unique name, otherwise more than one radio will be selectable
+ // Note: This is not going in the ID attribute, not that it matters
+ $name = $this->name ?: Tag::generateElementId();
+ foreach ( $options as $opt ) {
+ $optValue = $this->cleanUpValue( $opt['data'] );
+ $field = new FieldLayout(
+ new RadioInputWidget( [
+ 'name' => $name,
+ 'value' => $optValue,
+ 'disabled' => $this->isDisabled(),
+ ] ),
+ [
+ 'label' => isset( $opt['label'] ) ? $opt['label'] : $optValue,
+ 'align' => 'inline',
+ ]
+ );
+
+ if ( $value === $optValue ) {
+ $isValueAvailable = true;
+ }
+
+ $this->fields[] = $field;
+ $this->appendContent( $field );
+ }
+
+ // Restore the previous value, or reset to something sensible
+ if ( $isValueAvailable ) {
+ // Previous value is still available
+ $this->setValue( $value );
+ } else {
+ // No longer valid, reset
+ if ( count( $options ) ) {
+ $this->setValue( $options[0]['data'] );
+ }
+ }
+
+ return $this;
+ }
+
+ public function setDisabled( $state ) {
+ parent::setDisabled( $state );
+ foreach ( $this->fields as $field ) {
+ $field->getField()->setDisabled( $this->isDisabled() );
+ }
+ return $this;
+ }
+
+ public function getConfig( &$config ) {
+ $o = [];
+ foreach ( $this->fields as $field ) {
+ $label = $field->getLabel();
+ $data = $field->getField()->getValue();
+ $o[] = [ 'data' => $data, 'label' => $label ];
+ }
+ $config['options'] = $o;
+ return parent::getConfig( $config );
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/SearchInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/SearchInputWidget.php
new file mode 100644
index 00000000..0c87b0f8
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/SearchInputWidget.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Input widget with a text field.
+ */
+class SearchInputWidget extends TextInputWidget {
+
+ public function __construct( array $config = [] ) {
+ // Config initialization
+ $config = array_merge( [
+ 'icon' => 'search',
+ ], $config );
+
+ // Parent constructor
+ parent::__construct( $config );
+ }
+
+ protected function getSaneType( $config ) {
+ return 'search';
+ }
+}
diff --git a/www/wiki/vendor/oojs/oojs-ui/php/widgets/TextInputWidget.php b/www/wiki/vendor/oojs/oojs-ui/php/widgets/TextInputWidget.php
new file mode 100644
index 00000000..04acbda6
--- /dev/null
+++ b/www/wiki/vendor/oojs/oojs-ui/php/widgets/TextInputWidget.php
@@ -0,0 +1,249 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Input widget with a text field.
+ */
+class TextInputWidget extends InputWidget {
+ use IconElement;
+ use IndicatorElement;
+
+ /* Properties */
+
+ /**
+ * Input field type.
+ *
+ * @var string
+ */
+ protected $type = null;
+
+ /**
+ * Prevent changes.
+ *
+ * @var boolean
+ */
+ protected $readOnly = false;
+
+ /**
+ * Mark as required.
+ *
+ * @var boolean
+ */
+ protected $required = false;
+
+ /**
+ * Allow multiple lines of text.
+ *
+ * @var boolean
+ */
+ protected $multiline = false;
+
+ /**
+ * @param array $config Configuration options
+ * @param string $config['type'] HTML tag `type` attribute: 'text', 'password', 'email',
+ * 'url' or 'number'. Ignored if `multiline` is true. (default: 'text')
+ * @param string $config['placeholder'] Placeholder text
+ * @param bool $config['autofocus'] Ask the browser to focus this widget, using the 'autofocus'
+ * HTML attribute (default: false)
+ * @param bool $config['readOnly'] Prevent changes (default: false)
+ * @param number $config['maxLength'] Maximum allowed number of characters to input
+ *
+ * For unfortunate historical reasons, this counts the number of UTF-16 code units rather than
+ * Unicode codepoints, which means that codepoints outside the Basic Multilingual Plane (e.g.
+ * many emojis) count as 2 characters each.
+ * @param bool $config['multiline'] Allow multiple lines of text (default: false)
+ * @param bool $config['required'] Mark the field as required.
+ * Implies `indicator: 'required'`. Note that `false` & setting `indicator: 'required'
+ * will result in no indicator shown. (default: false)
+ * @param bool $config['autocomplete'] If the field should support autocomplete
+ * or not (default: true)
+ * @param bool $config['spellcheck'] If the field should support spellcheck
+ * or not (default: browser-dependent)
+ */
+ public function __construct( array $config = [] ) {
+ // Config initialization
+ $config = array_merge( [
+ 'type' => 'text',
+ 'readOnly' => false,
+ 'autofocus' => false,
+ 'required' => false,
+ 'autocomplete' => true,
+ ], $config );
+
+ // Parent constructor
+ parent::__construct( $config );
+
+ // Properties
+ $this->type = $this->getSaneType( $config );
+ $this->multiline = isset( $config['multiline'] ) ? (bool)$config['multiline'] : false;
+
+ if ( $this->multiline && !( $this instanceof MultilineTextInputWidget ) ) {
+ Element::warnDeprecation(
+ 'The TextInputWidget "multiline" option is deprecated as of OOUI v0.22.2. ' .
+ 'Use MultilineTextInputWidget instead.'
+ );
+ }
+
+ // Traits
+ $this->initializeIconElement( $config );
+ $this->initializeIndicatorElement( $config );
+
+ // Initialization
+ $this
+ ->addClasses( [
+ 'oo-ui-textInputWidget',
+ 'oo-ui-textInputWidget-type-' . $this->type,
+ 'oo-ui-textInputWidget-php',
+ ] )
+ ->appendContent( $this->icon, $this->indicator );
+ $this->setReadOnly( $config['readOnly'] );
+ $this->setRequired( $config['required'] );
+ if ( isset( $config['placeholder'] ) ) {
+ $this->input->setAttributes( [ 'placeholder' => $config['placeholder'] ] );
+ }
+ if ( isset( $config['maxLength'] ) ) {
+ $this->input->setAttributes( [ 'maxlength' => $config['maxLength'] ] );
+ }
+ if ( $config['autofocus'] ) {
+ $this->input->setAttributes( [ 'autofocus' => 'autofocus' ] );
+ }
+ if ( !$config['autocomplete'] ) {
+ $this->input->setAttributes( [ 'autocomplete' => 'off' ] );
+ }
+ if ( isset( $config['spellcheck'] ) ) {
+ $this->input->setAttributes( [ 'spellcheck' => $config['spellcheck'] ? 'true' : 'false' ] );
+ }
+ if ( $this->multiline && isset( $config['rows'] ) && $config['rows'] ) {
+ $this->input->setAttributes( [ 'rows' => $config['rows'] ] );
+ }
+ }
+
+ /**
+ * Check if the widget is read-only.
+ *
+ * @return bool
+ */
+ public function isReadOnly() {
+ return $this->readOnly;
+ }
+
+ /**
+ * Set the read-only state of the widget. This should probably change the widget's appearance and
+ * prevent it from being used.
+ *
+ * @param bool $state Make input read-only
+ * @return $this
+ */
+ public function setReadOnly( $state ) {
+ $this->readOnly = (bool)$state;
+ if ( $this->readOnly ) {
+ $this->input->setAttributes( [ 'readonly' => 'readonly' ] );
+ } else {
+ $this->input->removeAttributes( [ 'readonly' ] );
+ }
+ return $this;
+ }
+
+ /**
+ * Check if the widget is required.
+ *
+ * @return bool
+ */
+ public function isRequired() {
+ return $this->required;
+ }
+
+ /**
+ * Set the required state of the widget.
+ *
+ * @param bool $state Make input required
+ * @return $this
+ */
+ public function setRequired( $state ) {
+ $this->required = (bool)$state;
+ if ( $this->required ) {
+ $this->input->setAttributes( [ 'required' => 'required', 'aria-required' => 'true' ] );
+ if ( $this->getIndicator() === null ) {
+ $this->setIndicator( 'required' );
+ }
+ } else {
+ $this->input->removeAttributes( [ 'required', 'aria-required' ] );
+ if ( $this->getIndicator() === 'required' ) {
+ $this->setIndicator( null );
+ }
+ }
+ return $this;
+ }
+
+ protected function getInputElement( $config ) {
+ if ( isset( $config['multiline'] ) && $config['multiline'] ) {
+ return new Tag( 'textarea' );
+ } elseif ( $this->getSaneType( $config ) === 'number' ) {
+ return ( new Tag( 'input' ) )->setAttributes( [
+ 'step' => 'any',
+ 'type' => 'number',
+ ] );
+ } else {
+ return ( new Tag( 'input' ) )->setAttributes( [ 'type' => $this->getSaneType( $config ) ] );
+ }
+ }
+
+ protected function getSaneType( $config ) {
+ $allowedTypes = [
+ 'text',
+ 'password',
+ 'email',
+ 'url',
+ 'number'
+ ];
+ return in_array( $config['type'], $allowedTypes ) ? $config['type'] : 'text';
+ }
+
+ /**
+ * Check if input supports multiple lines.
+ *
+ * @return bool
+ */
+ public function isMultiline() {
+ return (bool)$this->multiline;
+ }
+
+ public function getConfig( &$config ) {
+ if ( $this->isMultiline() ) {
+ $config['multiline'] = true;
+ $rows = $this->input->getAttribute( 'rows' );
+ if ( $rows !== null ) {
+ $config['rows'] = $rows;
+ }
+ }
+ if ( $this->type !== 'text' ) {
+ $config['type'] = $this->type;
+ }
+ if ( $this->isReadOnly() ) {
+ $config['readOnly'] = true;
+ }
+ $placeholder = $this->input->getAttribute( 'placeholder' );
+ if ( $placeholder !== null ) {
+ $config['placeholder'] = $placeholder;
+ }
+ $maxlength = $this->input->getAttribute( 'maxlength' );
+ if ( $maxlength !== null ) {
+ $config['maxLength'] = $maxlength;
+ }
+ $autofocus = $this->input->getAttribute( 'autofocus' );
+ if ( $autofocus !== null ) {
+ $config['autofocus'] = true;
+ }
+ $required = $this->input->getAttribute( 'required' );
+ $ariarequired = $this->input->getAttribute( 'aria-required' );
+ if ( ( $required !== null ) || ( $ariarequired !== null ) ) {
+ $config['required'] = true;
+ }
+ $autocomplete = $this->input->getAttribute( 'autocomplete' );
+ if ( $autocomplete !== null ) {
+ $config['autocomplete'] = false;
+ }
+ return parent::getConfig( $config );
+ }
+}