oojs-ui: Fix up addition to core
authorTimo Tijhof <krinklemail@gmail.com>
Thu, 13 Feb 2014 01:53:09 +0000 (17:53 -0800)
committerTimo Tijhof <krinklemail@gmail.com>
Thu, 13 Feb 2014 18:05:10 +0000 (10:05 -0800)
Follows-up I0736601e04a15c8.

* Move to its own directory instead of mixing in the oojs.js dir.
* This also fixes the jsduck errors as it was immediately being
  indexed with settings for oojs, eventhough oojs-ui correctly
  does not index without errors with core's jsduck config.
* Remove spurious .gitignore file.

Change-Id: I01f99deb3967d731d7b0e8bca2a2497b3c0151ac

376 files changed:
.jshintignore
includes/DefaultSettings.php
resources/Resources.php
resources/oojs-ui/i18n/ace.json [new file with mode: 0644]
resources/oojs-ui/i18n/af.json [new file with mode: 0644]
resources/oojs-ui/i18n/am.json [new file with mode: 0644]
resources/oojs-ui/i18n/ar.json [new file with mode: 0644]
resources/oojs-ui/i18n/arc.json [new file with mode: 0644]
resources/oojs-ui/i18n/ast.json [new file with mode: 0644]
resources/oojs-ui/i18n/az.json [new file with mode: 0644]
resources/oojs-ui/i18n/ba.json [new file with mode: 0644]
resources/oojs-ui/i18n/bcl.json [new file with mode: 0644]
resources/oojs-ui/i18n/be-tarask.json [new file with mode: 0644]
resources/oojs-ui/i18n/be.json [new file with mode: 0644]
resources/oojs-ui/i18n/bg.json [new file with mode: 0644]
resources/oojs-ui/i18n/bn.json [new file with mode: 0644]
resources/oojs-ui/i18n/br.json [new file with mode: 0644]
resources/oojs-ui/i18n/bs.json [new file with mode: 0644]
resources/oojs-ui/i18n/ca.json [new file with mode: 0644]
resources/oojs-ui/i18n/ce.json [new file with mode: 0644]
resources/oojs-ui/i18n/ckb.json [new file with mode: 0644]
resources/oojs-ui/i18n/co.json [new file with mode: 0644]
resources/oojs-ui/i18n/cs.json [new file with mode: 0644]
resources/oojs-ui/i18n/cu.json [new file with mode: 0644]
resources/oojs-ui/i18n/cy.json [new file with mode: 0644]
resources/oojs-ui/i18n/da.json [new file with mode: 0644]
resources/oojs-ui/i18n/de.json [new file with mode: 0644]
resources/oojs-ui/i18n/diq.json [new file with mode: 0644]
resources/oojs-ui/i18n/dsb.json [new file with mode: 0644]
resources/oojs-ui/i18n/el.json [new file with mode: 0644]
resources/oojs-ui/i18n/eml.json [new file with mode: 0644]
resources/oojs-ui/i18n/en.json [new file with mode: 0644]
resources/oojs-ui/i18n/eo.json [new file with mode: 0644]
resources/oojs-ui/i18n/es.json [new file with mode: 0644]
resources/oojs-ui/i18n/et.json [new file with mode: 0644]
resources/oojs-ui/i18n/eu.json [new file with mode: 0644]
resources/oojs-ui/i18n/fa.json [new file with mode: 0644]
resources/oojs-ui/i18n/fi.json [new file with mode: 0644]
resources/oojs-ui/i18n/fo.json [new file with mode: 0644]
resources/oojs-ui/i18n/fr.json [new file with mode: 0644]
resources/oojs-ui/i18n/frr.json [new file with mode: 0644]
resources/oojs-ui/i18n/fur.json [new file with mode: 0644]
resources/oojs-ui/i18n/gl.json [new file with mode: 0644]
resources/oojs-ui/i18n/gu.json [new file with mode: 0644]
resources/oojs-ui/i18n/he.json [new file with mode: 0644]
resources/oojs-ui/i18n/hi.json [new file with mode: 0644]
resources/oojs-ui/i18n/hr.json [new file with mode: 0644]
resources/oojs-ui/i18n/hsb.json [new file with mode: 0644]
resources/oojs-ui/i18n/hu.json [new file with mode: 0644]
resources/oojs-ui/i18n/hy.json [new file with mode: 0644]
resources/oojs-ui/i18n/ia.json [new file with mode: 0644]
resources/oojs-ui/i18n/id.json [new file with mode: 0644]
resources/oojs-ui/i18n/ie.json [new file with mode: 0644]
resources/oojs-ui/i18n/ilo.json [new file with mode: 0644]
resources/oojs-ui/i18n/is.json [new file with mode: 0644]
resources/oojs-ui/i18n/it.json [new file with mode: 0644]
resources/oojs-ui/i18n/ja.json [new file with mode: 0644]
resources/oojs-ui/i18n/jv.json [new file with mode: 0644]
resources/oojs-ui/i18n/ka.json [new file with mode: 0644]
resources/oojs-ui/i18n/kk-cyrl.json [new file with mode: 0644]
resources/oojs-ui/i18n/ko.json [new file with mode: 0644]
resources/oojs-ui/i18n/krc.json [new file with mode: 0644]
resources/oojs-ui/i18n/kw.json [new file with mode: 0644]
resources/oojs-ui/i18n/ky.json [new file with mode: 0644]
resources/oojs-ui/i18n/lb.json [new file with mode: 0644]
resources/oojs-ui/i18n/lmo.json [new file with mode: 0644]
resources/oojs-ui/i18n/lt.json [new file with mode: 0644]
resources/oojs-ui/i18n/lv.json [new file with mode: 0644]
resources/oojs-ui/i18n/mg.json [new file with mode: 0644]
resources/oojs-ui/i18n/min.json [new file with mode: 0644]
resources/oojs-ui/i18n/mk.json [new file with mode: 0644]
resources/oojs-ui/i18n/ml.json [new file with mode: 0644]
resources/oojs-ui/i18n/mr.json [new file with mode: 0644]
resources/oojs-ui/i18n/ms.json [new file with mode: 0644]
resources/oojs-ui/i18n/nap.json [new file with mode: 0644]
resources/oojs-ui/i18n/nb.json [new file with mode: 0644]
resources/oojs-ui/i18n/nds-nl.json [new file with mode: 0644]
resources/oojs-ui/i18n/nds.json [new file with mode: 0644]
resources/oojs-ui/i18n/ne.json [new file with mode: 0644]
resources/oojs-ui/i18n/nl.json [new file with mode: 0644]
resources/oojs-ui/i18n/nn.json [new file with mode: 0644]
resources/oojs-ui/i18n/om.json [new file with mode: 0644]
resources/oojs-ui/i18n/or.json [new file with mode: 0644]
resources/oojs-ui/i18n/pa.json [new file with mode: 0644]
resources/oojs-ui/i18n/pl.json [new file with mode: 0644]
resources/oojs-ui/i18n/pms.json [new file with mode: 0644]
resources/oojs-ui/i18n/ps.json [new file with mode: 0644]
resources/oojs-ui/i18n/pt-br.json [new file with mode: 0644]
resources/oojs-ui/i18n/pt.json [new file with mode: 0644]
resources/oojs-ui/i18n/qqq.json [new file with mode: 0644]
resources/oojs-ui/i18n/qu.json [new file with mode: 0644]
resources/oojs-ui/i18n/ro.json [new file with mode: 0644]
resources/oojs-ui/i18n/roa-tara.json [new file with mode: 0644]
resources/oojs-ui/i18n/ru.json [new file with mode: 0644]
resources/oojs-ui/i18n/sah.json [new file with mode: 0644]
resources/oojs-ui/i18n/scn.json [new file with mode: 0644]
resources/oojs-ui/i18n/sh.json [new file with mode: 0644]
resources/oojs-ui/i18n/si.json [new file with mode: 0644]
resources/oojs-ui/i18n/sk.json [new file with mode: 0644]
resources/oojs-ui/i18n/sl.json [new file with mode: 0644]
resources/oojs-ui/i18n/sq.json [new file with mode: 0644]
resources/oojs-ui/i18n/sr-ec.json [new file with mode: 0644]
resources/oojs-ui/i18n/sv.json [new file with mode: 0644]
resources/oojs-ui/i18n/sw.json [new file with mode: 0644]
resources/oojs-ui/i18n/ta.json [new file with mode: 0644]
resources/oojs-ui/i18n/te.json [new file with mode: 0644]
resources/oojs-ui/i18n/th.json [new file with mode: 0644]
resources/oojs-ui/i18n/tl.json [new file with mode: 0644]
resources/oojs-ui/i18n/tr.json [new file with mode: 0644]
resources/oojs-ui/i18n/tt-cyrl.json [new file with mode: 0644]
resources/oojs-ui/i18n/ug-arab.json [new file with mode: 0644]
resources/oojs-ui/i18n/uk.json [new file with mode: 0644]
resources/oojs-ui/i18n/uz.json [new file with mode: 0644]
resources/oojs-ui/i18n/vec.json [new file with mode: 0644]
resources/oojs-ui/i18n/vi.json [new file with mode: 0644]
resources/oojs-ui/i18n/vo.json [new file with mode: 0644]
resources/oojs-ui/i18n/wuu.json [new file with mode: 0644]
resources/oojs-ui/i18n/yi.json [new file with mode: 0644]
resources/oojs-ui/i18n/yo.json [new file with mode: 0644]
resources/oojs-ui/i18n/zh-hans.json [new file with mode: 0644]
resources/oojs-ui/i18n/zh-hant.json [new file with mode: 0644]
resources/oojs-ui/i18n/zh-hk.json [new file with mode: 0644]
resources/oojs-ui/i18n/zh-tw.json [new file with mode: 0644]
resources/oojs-ui/images/fade-down.png [new file with mode: 0644]
resources/oojs-ui/images/fade-up.png [new file with mode: 0644]
resources/oojs-ui/images/icons/accept.png [new file with mode: 0644]
resources/oojs-ui/images/icons/accept.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/add-item.png [new file with mode: 0644]
resources/oojs-ui/images/icons/add-item.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/advanced.png [new file with mode: 0644]
resources/oojs-ui/images/icons/advanced.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/alert.png [new file with mode: 0644]
resources/oojs-ui/images/icons/alert.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/arched-arrow-ltr.png [new file with mode: 0644]
resources/oojs-ui/images/icons/arched-arrow-ltr.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/arched-arrow-rtl.png [new file with mode: 0644]
resources/oojs-ui/images/icons/arched-arrow-rtl.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/check.png [new file with mode: 0644]
resources/oojs-ui/images/icons/check.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/clear.png [new file with mode: 0644]
resources/oojs-ui/images/icons/clear.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/close.png [new file with mode: 0644]
resources/oojs-ui/images/icons/close.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/code.png [new file with mode: 0644]
resources/oojs-ui/images/icons/code.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/collapse.png [new file with mode: 0644]
resources/oojs-ui/images/icons/collapse.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/comment.png [new file with mode: 0644]
resources/oojs-ui/images/icons/comment.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/expand.png [new file with mode: 0644]
resources/oojs-ui/images/icons/expand.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/help.png [new file with mode: 0644]
resources/oojs-ui/images/icons/help.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/history.png [new file with mode: 0644]
resources/oojs-ui/images/icons/history.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/link.png [new file with mode: 0644]
resources/oojs-ui/images/icons/link.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/menu.png [new file with mode: 0644]
resources/oojs-ui/images/icons/menu.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/move-ltr.png [new file with mode: 0644]
resources/oojs-ui/images/icons/move-ltr.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/move-rtl.png [new file with mode: 0644]
resources/oojs-ui/images/icons/move-rtl.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/picture.png [new file with mode: 0644]
resources/oojs-ui/images/icons/picture.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/remove-item.png [new file with mode: 0644]
resources/oojs-ui/images/icons/remove-item.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/remove.png [new file with mode: 0644]
resources/oojs-ui/images/icons/remove.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/search.png [new file with mode: 0644]
resources/oojs-ui/images/icons/search.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/settings.png [new file with mode: 0644]
resources/oojs-ui/images/icons/settings.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/tag.png [new file with mode: 0644]
resources/oojs-ui/images/icons/tag.svg [new file with mode: 0644]
resources/oojs-ui/images/icons/window.png [new file with mode: 0644]
resources/oojs-ui/images/icons/window.svg [new file with mode: 0644]
resources/oojs-ui/images/indicators/down.png [new file with mode: 0644]
resources/oojs-ui/images/indicators/down.svg [new file with mode: 0644]
resources/oojs-ui/images/indicators/required.png [new file with mode: 0644]
resources/oojs-ui/images/indicators/required.svg [new file with mode: 0644]
resources/oojs-ui/images/indicators/up.png [new file with mode: 0644]
resources/oojs-ui/images/indicators/up.svg [new file with mode: 0644]
resources/oojs-ui/images/tail.svg [new file with mode: 0644]
resources/oojs-ui/images/textures/pending.gif [new file with mode: 0644]
resources/oojs-ui/images/textures/transparency.png [new file with mode: 0644]
resources/oojs-ui/images/toolbar-shadow.png [new file with mode: 0644]
resources/oojs-ui/oojs-ui.js [new file with mode: 0644]
resources/oojs-ui/oojs-ui.svg.css [new file with mode: 0644]
resources/oojs/.gitignore [deleted file]
resources/oojs/i18n/ace.json [deleted file]
resources/oojs/i18n/af.json [deleted file]
resources/oojs/i18n/am.json [deleted file]
resources/oojs/i18n/ar.json [deleted file]
resources/oojs/i18n/arc.json [deleted file]
resources/oojs/i18n/ast.json [deleted file]
resources/oojs/i18n/az.json [deleted file]
resources/oojs/i18n/ba.json [deleted file]
resources/oojs/i18n/bcl.json [deleted file]
resources/oojs/i18n/be-tarask.json [deleted file]
resources/oojs/i18n/be.json [deleted file]
resources/oojs/i18n/bg.json [deleted file]
resources/oojs/i18n/bn.json [deleted file]
resources/oojs/i18n/br.json [deleted file]
resources/oojs/i18n/bs.json [deleted file]
resources/oojs/i18n/ca.json [deleted file]
resources/oojs/i18n/ce.json [deleted file]
resources/oojs/i18n/ckb.json [deleted file]
resources/oojs/i18n/co.json [deleted file]
resources/oojs/i18n/cs.json [deleted file]
resources/oojs/i18n/cu.json [deleted file]
resources/oojs/i18n/cy.json [deleted file]
resources/oojs/i18n/da.json [deleted file]
resources/oojs/i18n/de.json [deleted file]
resources/oojs/i18n/diq.json [deleted file]
resources/oojs/i18n/dsb.json [deleted file]
resources/oojs/i18n/el.json [deleted file]
resources/oojs/i18n/eml.json [deleted file]
resources/oojs/i18n/en.json [deleted file]
resources/oojs/i18n/eo.json [deleted file]
resources/oojs/i18n/es.json [deleted file]
resources/oojs/i18n/et.json [deleted file]
resources/oojs/i18n/eu.json [deleted file]
resources/oojs/i18n/fa.json [deleted file]
resources/oojs/i18n/fi.json [deleted file]
resources/oojs/i18n/fo.json [deleted file]
resources/oojs/i18n/fr.json [deleted file]
resources/oojs/i18n/frr.json [deleted file]
resources/oojs/i18n/fur.json [deleted file]
resources/oojs/i18n/gl.json [deleted file]
resources/oojs/i18n/gu.json [deleted file]
resources/oojs/i18n/he.json [deleted file]
resources/oojs/i18n/hi.json [deleted file]
resources/oojs/i18n/hr.json [deleted file]
resources/oojs/i18n/hsb.json [deleted file]
resources/oojs/i18n/hu.json [deleted file]
resources/oojs/i18n/hy.json [deleted file]
resources/oojs/i18n/ia.json [deleted file]
resources/oojs/i18n/id.json [deleted file]
resources/oojs/i18n/ie.json [deleted file]
resources/oojs/i18n/ilo.json [deleted file]
resources/oojs/i18n/is.json [deleted file]
resources/oojs/i18n/it.json [deleted file]
resources/oojs/i18n/ja.json [deleted file]
resources/oojs/i18n/jv.json [deleted file]
resources/oojs/i18n/ka.json [deleted file]
resources/oojs/i18n/kk-cyrl.json [deleted file]
resources/oojs/i18n/ko.json [deleted file]
resources/oojs/i18n/krc.json [deleted file]
resources/oojs/i18n/kw.json [deleted file]
resources/oojs/i18n/ky.json [deleted file]
resources/oojs/i18n/lb.json [deleted file]
resources/oojs/i18n/lmo.json [deleted file]
resources/oojs/i18n/lt.json [deleted file]
resources/oojs/i18n/lv.json [deleted file]
resources/oojs/i18n/mg.json [deleted file]
resources/oojs/i18n/min.json [deleted file]
resources/oojs/i18n/mk.json [deleted file]
resources/oojs/i18n/ml.json [deleted file]
resources/oojs/i18n/mr.json [deleted file]
resources/oojs/i18n/ms.json [deleted file]
resources/oojs/i18n/nap.json [deleted file]
resources/oojs/i18n/nb.json [deleted file]
resources/oojs/i18n/nds-nl.json [deleted file]
resources/oojs/i18n/nds.json [deleted file]
resources/oojs/i18n/ne.json [deleted file]
resources/oojs/i18n/nl.json [deleted file]
resources/oojs/i18n/nn.json [deleted file]
resources/oojs/i18n/om.json [deleted file]
resources/oojs/i18n/or.json [deleted file]
resources/oojs/i18n/pa.json [deleted file]
resources/oojs/i18n/pl.json [deleted file]
resources/oojs/i18n/pms.json [deleted file]
resources/oojs/i18n/ps.json [deleted file]
resources/oojs/i18n/pt-br.json [deleted file]
resources/oojs/i18n/pt.json [deleted file]
resources/oojs/i18n/qqq.json [deleted file]
resources/oojs/i18n/qu.json [deleted file]
resources/oojs/i18n/ro.json [deleted file]
resources/oojs/i18n/roa-tara.json [deleted file]
resources/oojs/i18n/ru.json [deleted file]
resources/oojs/i18n/sah.json [deleted file]
resources/oojs/i18n/scn.json [deleted file]
resources/oojs/i18n/sh.json [deleted file]
resources/oojs/i18n/si.json [deleted file]
resources/oojs/i18n/sk.json [deleted file]
resources/oojs/i18n/sl.json [deleted file]
resources/oojs/i18n/sq.json [deleted file]
resources/oojs/i18n/sr-ec.json [deleted file]
resources/oojs/i18n/sv.json [deleted file]
resources/oojs/i18n/sw.json [deleted file]
resources/oojs/i18n/ta.json [deleted file]
resources/oojs/i18n/te.json [deleted file]
resources/oojs/i18n/th.json [deleted file]
resources/oojs/i18n/tl.json [deleted file]
resources/oojs/i18n/tr.json [deleted file]
resources/oojs/i18n/tt-cyrl.json [deleted file]
resources/oojs/i18n/ug-arab.json [deleted file]
resources/oojs/i18n/uk.json [deleted file]
resources/oojs/i18n/uz.json [deleted file]
resources/oojs/i18n/vec.json [deleted file]
resources/oojs/i18n/vi.json [deleted file]
resources/oojs/i18n/vo.json [deleted file]
resources/oojs/i18n/wuu.json [deleted file]
resources/oojs/i18n/yi.json [deleted file]
resources/oojs/i18n/yo.json [deleted file]
resources/oojs/i18n/zh-hans.json [deleted file]
resources/oojs/i18n/zh-hant.json [deleted file]
resources/oojs/i18n/zh-hk.json [deleted file]
resources/oojs/i18n/zh-tw.json [deleted file]
resources/oojs/images/fade-down.png [deleted file]
resources/oojs/images/fade-up.png [deleted file]
resources/oojs/images/icons/accept.png [deleted file]
resources/oojs/images/icons/accept.svg [deleted file]
resources/oojs/images/icons/add-item.png [deleted file]
resources/oojs/images/icons/add-item.svg [deleted file]
resources/oojs/images/icons/advanced.png [deleted file]
resources/oojs/images/icons/advanced.svg [deleted file]
resources/oojs/images/icons/alert.png [deleted file]
resources/oojs/images/icons/alert.svg [deleted file]
resources/oojs/images/icons/arched-arrow-ltr.png [deleted file]
resources/oojs/images/icons/arched-arrow-ltr.svg [deleted file]
resources/oojs/images/icons/arched-arrow-rtl.png [deleted file]
resources/oojs/images/icons/arched-arrow-rtl.svg [deleted file]
resources/oojs/images/icons/check.png [deleted file]
resources/oojs/images/icons/check.svg [deleted file]
resources/oojs/images/icons/clear.png [deleted file]
resources/oojs/images/icons/clear.svg [deleted file]
resources/oojs/images/icons/close.png [deleted file]
resources/oojs/images/icons/close.svg [deleted file]
resources/oojs/images/icons/code.png [deleted file]
resources/oojs/images/icons/code.svg [deleted file]
resources/oojs/images/icons/collapse.png [deleted file]
resources/oojs/images/icons/collapse.svg [deleted file]
resources/oojs/images/icons/comment.png [deleted file]
resources/oojs/images/icons/comment.svg [deleted file]
resources/oojs/images/icons/expand.png [deleted file]
resources/oojs/images/icons/expand.svg [deleted file]
resources/oojs/images/icons/help.png [deleted file]
resources/oojs/images/icons/help.svg [deleted file]
resources/oojs/images/icons/history.png [deleted file]
resources/oojs/images/icons/history.svg [deleted file]
resources/oojs/images/icons/link.png [deleted file]
resources/oojs/images/icons/link.svg [deleted file]
resources/oojs/images/icons/menu.png [deleted file]
resources/oojs/images/icons/menu.svg [deleted file]
resources/oojs/images/icons/move-ltr.png [deleted file]
resources/oojs/images/icons/move-ltr.svg [deleted file]
resources/oojs/images/icons/move-rtl.png [deleted file]
resources/oojs/images/icons/move-rtl.svg [deleted file]
resources/oojs/images/icons/picture.png [deleted file]
resources/oojs/images/icons/picture.svg [deleted file]
resources/oojs/images/icons/remove-item.png [deleted file]
resources/oojs/images/icons/remove-item.svg [deleted file]
resources/oojs/images/icons/remove.png [deleted file]
resources/oojs/images/icons/remove.svg [deleted file]
resources/oojs/images/icons/search.png [deleted file]
resources/oojs/images/icons/search.svg [deleted file]
resources/oojs/images/icons/settings.png [deleted file]
resources/oojs/images/icons/settings.svg [deleted file]
resources/oojs/images/icons/tag.png [deleted file]
resources/oojs/images/icons/tag.svg [deleted file]
resources/oojs/images/icons/window.png [deleted file]
resources/oojs/images/icons/window.svg [deleted file]
resources/oojs/images/indicators/down.png [deleted file]
resources/oojs/images/indicators/down.svg [deleted file]
resources/oojs/images/indicators/required.png [deleted file]
resources/oojs/images/indicators/required.svg [deleted file]
resources/oojs/images/indicators/up.png [deleted file]
resources/oojs/images/indicators/up.svg [deleted file]
resources/oojs/images/tail.svg [deleted file]
resources/oojs/images/textures/pending.gif [deleted file]
resources/oojs/images/textures/transparency.png [deleted file]
resources/oojs/images/toolbar-shadow.png [deleted file]
resources/oojs/oojs-ui.js [deleted file]
resources/oojs/oojs-ui.svg.css [deleted file]

index b161f1f..ebc7312 100644 (file)
@@ -29,6 +29,7 @@ resources/jquery.tipsy/
 resources/jquery.ui/
 resources/mediawiki.libs/
 resources/oojs/
+resources/oojs-ui/
 resources/sinonjs/
 
 # github.com/jshint/jshint/issues/729
index bb80beb..dd76a04 100644 (file)
@@ -5958,21 +5958,21 @@ $wgExtensionMessagesFiles = array();
  *
  * @par Simple example:
  * @code
- *    $wgMessagesDirs['ConfirmEdit'] = __DIR__ . '/i18n';
+ *    $wgMessagesDirs['Example'] = __DIR__ . '/i18n';
  * @endcode
  *
  * @par Complex example:
  * @code
- *    $wgMessagesDirs['VisualEditor'] = array(
- *        __DIR__ . '/lib/ve/modules/ve/i18n',
- *        __DIR__ . '/modules/ve-mw/i18n',
- *        __DIR__ . '/modules/ve-wmf/i18n',
+ *    $wgMessagesDirs['Example'] = array(
+ *        __DIR__ . '/lib/ve/i18n',
+ *        __DIR__ . '/lib/oojs-ui/i18n',
+ *        __DIR__ . '/i18n',
  *    )
  * @endcode
  * @since 1.23
  */
 $wgMessagesDirs = array(
-       "$IP/resources/oojs/i18n",
+       "$IP/resources/oojs-ui/i18n",
 );
 
 /**
index 3ae330b..f634c8c 100644 (file)
@@ -1278,10 +1278,10 @@ return array(
 
        'oojs-ui' => array(
                'scripts' => array(
-                       'resources/oojs/oojs-ui.js',
+                       'resources/oojs-ui/oojs-ui.js',
                ),
                'styles' => array(
-                       'resources/oojs/oojs-ui.svg.css',
+                       'resources/oojs-ui/oojs-ui.svg.css',
                ),
                'messages' => array(
                        'ooui-dialog-action-close',
diff --git a/resources/oojs-ui/i18n/ace.json b/resources/oojs-ui/i18n/ace.json
new file mode 100644 (file)
index 0000000..554ae57
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Si Gam Acèh"
+        ]
+    },
+    "ooui-dialog-action-close": "Tôp",
+    "ooui-outline-control-move-down": "Pinah item u yup",
+    "ooui-outline-control-move-up": "Pinah item u ateuëh",
+    "ooui-toolbar-more": "Lom"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/af.json b/resources/oojs-ui/i18n/af.json
new file mode 100644 (file)
index 0000000..a622f89
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Naudefj"
+        ]
+    },
+    "ooui-dialog-action-close": "Sluit",
+    "ooui-outline-control-move-down": "Skuif item af",
+    "ooui-outline-control-move-up": "Skuif item op"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/am.json b/resources/oojs-ui/i18n/am.json
new file mode 100644 (file)
index 0000000..61e4ff6
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "Elfalem"
+        ]
+    },
+    "ooui-dialog-action-close": "ለመዝጋት"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ar.json b/resources/oojs-ui/i18n/ar.json
new file mode 100644 (file)
index 0000000..65e1364
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ciphers",
+            "Claw eg",
+            "Elfalem",
+            "Jdforrester",
+            "Mido",
+            "OsamaK",
+            "زكريا",
+            "مشعل الحربي"
+        ]
+    },
+    "ooui-dialog-action-close": "أغلق",
+    "ooui-outline-control-move-down": "انقل العنصر للأسفل",
+    "ooui-outline-control-move-up": "انقل العنصر للأعلى",
+    "ooui-toolbar-more": "مزيد"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/arc.json b/resources/oojs-ui/i18n/arc.json
new file mode 100644 (file)
index 0000000..0f9e75d
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "Basharh"
+        ]
+    },
+    "ooui-dialog-action-close": "ܣܟܘܪ"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ast.json b/resources/oojs-ui/i18n/ast.json
new file mode 100644 (file)
index 0000000..959ea23
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Basharh",
+            "Bishnu Saikia",
+            "Xuacu"
+        ]
+    },
+    "ooui-dialog-action-close": "Zarrar",
+    "ooui-outline-control-move-down": "Mover abaxo l'elementu",
+    "ooui-outline-control-move-up": "Mover arriba l'elementu",
+    "ooui-toolbar-more": "Más"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/az.json b/resources/oojs-ui/i18n/az.json
new file mode 100644 (file)
index 0000000..8bfcf88
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cekli829",
+            "Interfase",
+            "Jduranboger"
+        ]
+    },
+    "ooui-dialog-action-close": "Bağla",
+    "ooui-outline-control-move-down": "Bəndi aşağı apar",
+    "ooui-outline-control-move-up": "Bəndi yuxarı apar"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ba.json b/resources/oojs-ui/i18n/ba.json
new file mode 100644 (file)
index 0000000..4af0114
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "@metadata": {
+        "authors": [
+            "AiseluRB",
+            "Amire80",
+            "Assele",
+            "Haqmar",
+            "Sagan",
+            "Рустам Нурыев"
+        ]
+    },
+    "ooui-dialog-action-close": "Ябырға",
+    "ooui-outline-control-move-down": "Аҫҡа күсерергә",
+    "ooui-outline-control-move-up": "Өҫкә күсерергә"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/bcl.json b/resources/oojs-ui/i18n/bcl.json
new file mode 100644 (file)
index 0000000..aff451e
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Geopoet",
+            "Sky Harbor"
+        ]
+    },
+    "ooui-dialog-action-close": "Seraduhon",
+    "ooui-outline-control-move-down": "Balyuhon an aytem paibaba",
+    "ooui-outline-control-move-up": "Balyuhon an aytem paitaas",
+    "ooui-toolbar-more": "Kadugangan"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/be-tarask.json b/resources/oojs-ui/i18n/be-tarask.json
new file mode 100644 (file)
index 0000000..5922f61
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "EugeneZelenko",
+            "Wizardist",
+            "Чаховіч Уладзіслаў",
+            "Zedlik"
+        ]
+    },
+    "ooui-dialog-action-close": "Закрыць",
+    "ooui-outline-control-move-down": "Перасунуць ніжэй",
+    "ooui-outline-control-move-up": "Перасунуць вышэй",
+    "ooui-toolbar-more": "Болей"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/be.json b/resources/oojs-ui/i18n/be.json
new file mode 100644 (file)
index 0000000..3058ab8
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "Чаховіч Уладзіслаў"
+        ]
+    },
+    "ooui-dialog-action-close": "Закрыць"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/bg.json b/resources/oojs-ui/i18n/bg.json
new file mode 100644 (file)
index 0000000..67e664b
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "DCLXVI",
+            "Hristofor.mirchev",
+            "පසිඳු කාවින්ද"
+        ]
+    },
+    "ooui-dialog-action-close": "Затваряне",
+    "ooui-toolbar-more": "Още"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/bn.json b/resources/oojs-ui/i18n/bn.json
new file mode 100644 (file)
index 0000000..c321ab1
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "@metadata": {
+        "authors": [
+            "Aftab1995",
+            "Bellayet",
+            "Jayantanth",
+            "Nasir8891",
+            "Runab",
+            "Sayak Sarkar"
+        ]
+    },
+    "ooui-dialog-action-close": "বন্ধ",
+    "ooui-outline-control-move-down": "আইটেম নিচে স্থানান্তর",
+    "ooui-outline-control-move-up": "আইটেম উপরে স্থানান্তর",
+    "ooui-toolbar-more": "আরও"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/br.json b/resources/oojs-ui/i18n/br.json
new file mode 100644 (file)
index 0000000..38eb9e8
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Fohanno",
+            "Fulup",
+            "Y-M D"
+        ]
+    },
+    "ooui-dialog-action-close": "Serriñ",
+    "ooui-outline-control-move-down": "Lakaat an elfenn da ziskenn",
+    "ooui-outline-control-move-up": "Lakaat an elfenn da bignat"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/bs.json b/resources/oojs-ui/i18n/bs.json
new file mode 100644 (file)
index 0000000..7449f07
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "DzWiki"
+        ]
+    },
+    "ooui-dialog-action-close": "Zatvori",
+    "ooui-outline-control-move-down": "Premjesti stavku dole",
+    "ooui-outline-control-move-up": "Premjesti stavku gore",
+    "ooui-toolbar-more": "Više"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ca.json b/resources/oojs-ui/i18n/ca.json
new file mode 100644 (file)
index 0000000..61bb1f6
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "@metadata": {
+        "authors": [
+            "Alvaro Vidal-Abarca",
+            "Amire80",
+            "Arnaugir",
+            "Pginer",
+            "QuimGil",
+            "SMP",
+            "Vriullop"
+        ]
+    },
+    "ooui-dialog-action-close": "Tanca",
+    "ooui-outline-control-move-down": "Baixa element",
+    "ooui-outline-control-move-up": "Puja element",
+    "ooui-toolbar-more": "Més"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ce.json b/resources/oojs-ui/i18n/ce.json
new file mode 100644 (file)
index 0000000..1e145ea
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Amire80",
+            "Умар"
+        ]
+    },
+    "ooui-dialog-action-close": "ДӀачӀагӀа",
+    "ooui-outline-control-move-down": "Лаха яккха элемент",
+    "ooui-outline-control-move-up": "Лаккха яккха элемент",
+    "ooui-toolbar-more": "Кхин тӀе"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ckb.json b/resources/oojs-ui/i18n/ckb.json
new file mode 100644 (file)
index 0000000..839f4a8
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Calak",
+            "Muhammed taha"
+        ]
+    },
+    "ooui-dialog-action-close": "دایخە"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/co.json b/resources/oojs-ui/i18n/co.json
new file mode 100644 (file)
index 0000000..e5edb21
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Paulu"
+        ]
+    },
+    "ooui-dialog-action-close": "Chjude",
+    "ooui-outline-control-move-down": "Fà falà l'ogettu",
+    "ooui-outline-control-move-up": "Fà cullà l'ogettu"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/cs.json b/resources/oojs-ui/i18n/cs.json
new file mode 100644 (file)
index 0000000..9661ec6
--- /dev/null
@@ -0,0 +1,20 @@
+{
+    "@metadata": {
+        "authors": [
+            "Chmee2",
+            "Jkjk",
+            "Juandev",
+            "Koo6",
+            "Littledogboy",
+            "Michaelbrabec",
+            "Mormegil",
+            "Polda18",
+            "Tchoř",
+            "ශ්වෙත"
+        ]
+    },
+    "ooui-dialog-action-close": "Zavřít",
+    "ooui-outline-control-move-down": "Přesunout položku dolů",
+    "ooui-outline-control-move-up": "Přesunout položku nahoru",
+    "ooui-toolbar-more": "Další"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/cu.json b/resources/oojs-ui/i18n/cu.json
new file mode 100644 (file)
index 0000000..fa9b1cf
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "ОйЛ"
+        ]
+    },
+    "ooui-dialog-action-close": "ꙁакрꙑи"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/cy.json b/resources/oojs-ui/i18n/cy.json
new file mode 100644 (file)
index 0000000..d37912d
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Lloffiwr",
+            "Robin Owain",
+            "ОйЛ"
+        ]
+    },
+    "ooui-dialog-action-close": "Caeer",
+    "ooui-outline-control-move-down": "Symud yr eitem lawr",
+    "ooui-outline-control-move-up": "Symud yr eitem lan",
+    "ooui-toolbar-more": "Rhagor"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/da.json b/resources/oojs-ui/i18n/da.json
new file mode 100644 (file)
index 0000000..bf47bcb
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cgtdk",
+            "Christian List",
+            "EileenSanda",
+            "Laketown",
+            "Palnatoke",
+            "Simeondahl",
+            "Tehnix"
+        ]
+    },
+    "ooui-dialog-action-close": "Luk",
+    "ooui-outline-control-move-down": "Flyt ned",
+    "ooui-outline-control-move-up": "Flyt op",
+    "ooui-toolbar-more": "Mere"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/de.json b/resources/oojs-ui/i18n/de.json
new file mode 100644 (file)
index 0000000..3a66648
--- /dev/null
@@ -0,0 +1,20 @@
+{
+    "@metadata": {
+        "authors": [
+            "APPER",
+            "G.Hagedorn",
+            "Inkowik",
+            "Jcornelius",
+            "Jdforrester",
+            "Kghbln",
+            "Metalhead64",
+            "Murma174",
+            "Se4598",
+            "Tomabrafix"
+        ]
+    },
+    "ooui-dialog-action-close": "Schließen",
+    "ooui-outline-control-move-down": "Element nach unten verschieben",
+    "ooui-outline-control-move-up": "Element nach oben verschieben",
+    "ooui-toolbar-more": "Mehr"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/diq.json b/resources/oojs-ui/i18n/diq.json
new file mode 100644 (file)
index 0000000..bb0ac35
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "@metadata": {
+        "authors": [
+            "Erdemaslancan",
+            "Gorizon",
+            "Kghbln",
+            "Marmase",
+            "Mirzali",
+            "Se4598"
+        ]
+    },
+    "ooui-dialog-action-close": "Racnê",
+    "ooui-outline-control-move-down": "Bendi bere cêr",
+    "ooui-outline-control-move-up": "Bendi bere cor",
+    "ooui-toolbar-more": "Zewbi"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/dsb.json b/resources/oojs-ui/i18n/dsb.json
new file mode 100644 (file)
index 0000000..0f47587
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Michawiki"
+        ]
+    },
+    "ooui-dialog-action-close": "Zacyniś",
+    "ooui-outline-control-move-down": "Element dołoj pśesunuś",
+    "ooui-outline-control-move-up": "Element górjej pśesunuś",
+    "ooui-toolbar-more": "Wěcej"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/el.json b/resources/oojs-ui/i18n/el.json
new file mode 100644 (file)
index 0000000..66051f1
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "@metadata": {
+        "authors": [
+            "Astralnet",
+            "Dipa1965",
+            "Evropi",
+            "FocalPoint",
+            "Geraki",
+            "Glavkos",
+            "Nikosguard",
+            "Tifa93"
+        ]
+    },
+    "ooui-dialog-action-close": "Κλείσιμο",
+    "ooui-outline-control-move-down": "Μετακίνηση προς τα κάτω",
+    "ooui-outline-control-move-up": "Μετακίνηση προς τα πάνω",
+    "ooui-toolbar-more": "Περισσότερα"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/eml.json b/resources/oojs-ui/i18n/eml.json
new file mode 100644 (file)
index 0000000..5dd09f5
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Gloria sah",
+            "Lévi"
+        ]
+    },
+    "ooui-dialog-action-close": "Sèra",
+    "ooui-outline-control-move-down": "Spôsta in bâs",
+    "ooui-outline-control-move-up": "Spôsta in êlt",
+    "ooui-toolbar-more": "Êter"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/en.json b/resources/oojs-ui/i18n/en.json
new file mode 100644 (file)
index 0000000..d402de8
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "@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-dialog-action-close": "Close",
+    "ooui-outline-control-move-down": "Move item down",
+    "ooui-outline-control-move-up": "Move item up",
+    "ooui-toolbar-more": "More"
+}
diff --git a/resources/oojs-ui/i18n/eo.json b/resources/oojs-ui/i18n/eo.json
new file mode 100644 (file)
index 0000000..51f3261
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Happy5214",
+            "KuboF",
+            "Shirayuki",
+            "Yekrats"
+        ]
+    },
+    "ooui-dialog-action-close": "Fermi",
+    "ooui-outline-control-move-down": "Movi eron suben",
+    "ooui-outline-control-move-up": "Movi eron supren",
+    "ooui-toolbar-more": "Pli"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/es.json b/resources/oojs-ui/i18n/es.json
new file mode 100644 (file)
index 0000000..0d822bc
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "@metadata": {
+        "authors": [
+            "Armando-Martin",
+            "Aruizdr",
+            "Benfutbol10",
+            "DJ Nietzsche",
+            "Erdemaslancan",
+            "Fitoschido",
+            "Imre",
+            "Invadinado",
+            "Jdforrester",
+            "Jduranboger",
+            "PoLuX124",
+            "Ralgis",
+            "Thehelpfulone"
+        ]
+    },
+    "ooui-dialog-action-close": "Cerrar",
+    "ooui-outline-control-move-down": "Mover abajo",
+    "ooui-outline-control-move-up": "Mover arriba",
+    "ooui-toolbar-more": "Más"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/et.json b/resources/oojs-ui/i18n/et.json
new file mode 100644 (file)
index 0000000..4af8dbe
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Avjoska",
+            "Pikne"
+        ]
+    },
+    "ooui-dialog-action-close": "Sule",
+    "ooui-outline-control-move-down": "Liiguta üksust allapoole",
+    "ooui-outline-control-move-up": "Liiguta üksust ülespoole",
+    "ooui-toolbar-more": "Veel"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/eu.json b/resources/oojs-ui/i18n/eu.json
new file mode 100644 (file)
index 0000000..5d3f08b
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "An13sa",
+            "Unai Fdz. de Betoño",
+            "Xabier Armendaritz"
+        ]
+    },
+    "ooui-dialog-action-close": "Itxi",
+    "ooui-outline-control-move-down": "Mugitu itema beherantz",
+    "ooui-outline-control-move-up": "Mugitu itema gorantz",
+    "ooui-toolbar-more": "Gehiago"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/fa.json b/resources/oojs-ui/i18n/fa.json
new file mode 100644 (file)
index 0000000..173acd7
--- /dev/null
@@ -0,0 +1,19 @@
+{
+    "@metadata": {
+        "authors": [
+            "Dalba",
+            "Ebraminio",
+            "Jdforrester",
+            "Ladsgroup",
+            "Mjbmr",
+            "Nojan Madinehi",
+            "Reza1615",
+            "Taha",
+            "درفش کاویانی"
+        ]
+    },
+    "ooui-dialog-action-close": "بستن",
+    "ooui-outline-control-move-down": "انتقال مورد به پایین",
+    "ooui-outline-control-move-up": "انتقال مورد به بالا",
+    "ooui-toolbar-more": "بیشتر"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/fi.json b/resources/oojs-ui/i18n/fi.json
new file mode 100644 (file)
index 0000000..dcd367f
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "@metadata": {
+        "authors": [
+            "Beluga",
+            "Crt",
+            "Harriv",
+            "Linnea",
+            "Nedergard",
+            "Nike",
+            "Olli",
+            "Pxos",
+            "Samoasambia",
+            "Silvonen",
+            "Skalman",
+            "Stryn",
+            "VezonThunder"
+        ]
+    },
+    "ooui-dialog-action-close": "Sulje",
+    "ooui-outline-control-move-down": "Siirrä kohdetta alaspäin",
+    "ooui-outline-control-move-up": "Siirrä kohdetta ylöspäin",
+    "ooui-toolbar-more": "Lisää"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/fo.json b/resources/oojs-ui/i18n/fo.json
new file mode 100644 (file)
index 0000000..00a48ff
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "EileenSanda"
+        ]
+    },
+    "ooui-dialog-action-close": "Lat aftur",
+    "ooui-outline-control-move-down": "Flyt lutin niður",
+    "ooui-outline-control-move-up": "Flyt lutin upp",
+    "ooui-toolbar-more": "Meira"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/fr.json b/resources/oojs-ui/i18n/fr.json
new file mode 100644 (file)
index 0000000..eb24b5a
--- /dev/null
@@ -0,0 +1,35 @@
+{
+    "@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"
+        ]
+    },
+    "ooui-dialog-action-close": "Fermer",
+    "ooui-outline-control-move-down": "Faire descendre l’élément",
+    "ooui-outline-control-move-up": "Faire monter l’élément",
+    "ooui-toolbar-more": "Plus"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/frr.json b/resources/oojs-ui/i18n/frr.json
new file mode 100644 (file)
index 0000000..ee95b8a
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "ChrisPtDe",
+            "Murma174"
+        ]
+    },
+    "ooui-dialog-action-close": "Slütj",
+    "ooui-outline-control-move-down": "Element efter onern sküüw",
+    "ooui-outline-control-move-up": "Element efter boowen sküüw",
+    "ooui-toolbar-more": "Muar"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/fur.json b/resources/oojs-ui/i18n/fur.json
new file mode 100644 (file)
index 0000000..18ea383
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Klenje",
+            "Tocaibon"
+        ]
+    },
+    "ooui-dialog-action-close": "Siere",
+    "ooui-outline-control-move-down": "sposte sot",
+    "ooui-outline-control-move-up": "sposte in su",
+    "ooui-toolbar-more": "Altri"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/gl.json b/resources/oojs-ui/i18n/gl.json
new file mode 100644 (file)
index 0000000..5d0928f
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Alison",
+            "Kscanne",
+            "Toliño"
+        ]
+    },
+    "ooui-dialog-action-close": "Pechar",
+    "ooui-outline-control-move-down": "Mover o elemento abaixo",
+    "ooui-outline-control-move-up": "Mover o elemento arriba",
+    "ooui-toolbar-more": "Máis"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/gu.json b/resources/oojs-ui/i18n/gu.json
new file mode 100644 (file)
index 0000000..65ec22b
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ashok modhvadia",
+            "KartikMistry",
+            "The Discoverer"
+        ]
+    },
+    "ooui-dialog-action-close": "બંધ કરો",
+    "ooui-outline-control-move-down": "વસ્તુ નીચે ખસેડો",
+    "ooui-outline-control-move-up": "વસ્તુ ઉપર ખસેડો",
+    "ooui-toolbar-more": "વધુ"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/he.json b/resources/oojs-ui/i18n/he.json
new file mode 100644 (file)
index 0000000..31b693c
--- /dev/null
@@ -0,0 +1,22 @@
+{
+    "@metadata": {
+        "authors": [
+            "Amire80",
+            "ExampleTomer",
+            "Guycn2",
+            "Matanya",
+            "Mooeypoo",
+            "Orsa",
+            "Shimmin Beg",
+            "אור שפירא",
+            "חיים",
+            "ערן",
+            "פוילישער",
+            "קיפודנחש"
+        ]
+    },
+    "ooui-dialog-action-close": "סגירה",
+    "ooui-outline-control-move-down": "להזיז את הפריט מטה",
+    "ooui-outline-control-move-up": "להזיז את הפריט מעלה",
+    "ooui-toolbar-more": "עוד"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/hi.json b/resources/oojs-ui/i18n/hi.json
new file mode 100644 (file)
index 0000000..8b79d34
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ansumang",
+            "Devayon",
+            "Rajesh",
+            "Siddhartha Ghai"
+        ]
+    },
+    "ooui-dialog-action-close": "बंद करें",
+    "ooui-outline-control-move-down": "प्रविष्टि नीचे ले जाएँ",
+    "ooui-outline-control-move-up": "प्रविष्टि ऊपर ले जाएँ",
+    "ooui-toolbar-more": "अधिक"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/hr.json b/resources/oojs-ui/i18n/hr.json
new file mode 100644 (file)
index 0000000..1c3f925
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "MaGa",
+            "Roberta F.",
+            "SpeedyGonsales"
+        ]
+    },
+    "ooui-dialog-action-close": "zatvori",
+    "ooui-outline-control-move-down": "Premjesti stavku dolje",
+    "ooui-outline-control-move-up": "Premjesti stavku gore",
+    "ooui-toolbar-more": "Više mogućnosti"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/hsb.json b/resources/oojs-ui/i18n/hsb.json
new file mode 100644 (file)
index 0000000..861c6e5
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "J budissin",
+            "Michawiki"
+        ]
+    },
+    "ooui-dialog-action-close": "Začinić"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/hu.json b/resources/oojs-ui/i18n/hu.json
new file mode 100644 (file)
index 0000000..9f7b435
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Dj",
+            "Einstein2",
+            "Misibacsi",
+            "ViDam"
+        ]
+    },
+    "ooui-dialog-action-close": "Bezár",
+    "ooui-outline-control-move-down": "Elem mozgatása lefelé",
+    "ooui-outline-control-move-up": "Elem mozgatása felfelé",
+    "ooui-toolbar-more": "Tovább..."
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/hy.json b/resources/oojs-ui/i18n/hy.json
new file mode 100644 (file)
index 0000000..f6cb90b
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Vacio",
+            "Xelgen"
+        ]
+    },
+    "ooui-dialog-action-close": "Փակել",
+    "ooui-outline-control-move-down": "Իջեցնել կետը",
+    "ooui-outline-control-move-up": "Բարձրացնել կետը",
+    "ooui-toolbar-more": "Ավելին"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ia.json b/resources/oojs-ui/i18n/ia.json
new file mode 100644 (file)
index 0000000..e335553
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "McDutchie"
+        ]
+    },
+    "ooui-dialog-action-close": "Clauder"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/id.json b/resources/oojs-ui/i18n/id.json
new file mode 100644 (file)
index 0000000..6d3ba4d
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "@metadata": {
+        "authors": [
+            "Farras",
+            "Ilham151096",
+            "Iwan Novirion",
+            "Iyan",
+            "Kenrick95",
+            "McDutchie",
+            "Rv77ax",
+            "William Surya Permana"
+        ]
+    },
+    "ooui-dialog-action-close": "Tutup",
+    "ooui-outline-control-move-down": "Pindahkan butir ke bawah",
+    "ooui-outline-control-move-up": "Pindahkan butir ke atas",
+    "ooui-toolbar-more": "Lainnya"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ie.json b/resources/oojs-ui/i18n/ie.json
new file mode 100644 (file)
index 0000000..84d002d
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Makuba"
+        ]
+    },
+    "ooui-dialog-action-close": "Terminar",
+    "ooui-outline-control-move-down": "Mover element a infra",
+    "ooui-outline-control-move-up": "Mover element a supra",
+    "ooui-toolbar-more": "Plu"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ilo.json b/resources/oojs-ui/i18n/ilo.json
new file mode 100644 (file)
index 0000000..15f42e5
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Lam-ang"
+        ]
+    },
+    "ooui-dialog-action-close": "Irekep",
+    "ooui-outline-control-move-down": "Ipababa ti banag",
+    "ooui-outline-control-move-up": "Ipangato ti banag",
+    "ooui-toolbar-more": "Adu pay"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/is.json b/resources/oojs-ui/i18n/is.json
new file mode 100644 (file)
index 0000000..efe0e67
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Maxí",
+            "Snævar"
+        ]
+    },
+    "ooui-dialog-action-close": "Loka",
+    "ooui-outline-control-move-down": "Færa atriða niður",
+    "ooui-outline-control-move-up": "Færa atriða upp",
+    "ooui-toolbar-more": "Fleira"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/it.json b/resources/oojs-ui/i18n/it.json
new file mode 100644 (file)
index 0000000..6158cff
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    "@metadata": {
+        "authors": [
+            "Beta16",
+            "Darth Kule",
+            "Doc.mari",
+            "Eleonora negri",
+            "Elitre",
+            "F. Cosoleto",
+            "FRacco",
+            "Gianfranco",
+            "Minerva Titani",
+            "Raoli",
+            "Una giornata uggiosa '94"
+        ]
+    },
+    "ooui-dialog-action-close": "Chiudi",
+    "ooui-outline-control-move-down": "Sposta in basso",
+    "ooui-outline-control-move-up": "Sposta in alto",
+    "ooui-toolbar-more": "Altro"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ja.json b/resources/oojs-ui/i18n/ja.json
new file mode 100644 (file)
index 0000000..789fbeb
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Fryed-peach",
+            "Miya",
+            "Penn Station",
+            "Shirayuki"
+        ]
+    },
+    "ooui-dialog-action-close": "閉じる",
+    "ooui-outline-control-move-down": "項目を下に移動させる",
+    "ooui-outline-control-move-up": "項目を上に移動させる",
+    "ooui-toolbar-more": "その他"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/jv.json b/resources/oojs-ui/i18n/jv.json
new file mode 100644 (file)
index 0000000..a362079
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Gleki",
+            "NoiX180",
+            "Pras"
+        ]
+    },
+    "ooui-dialog-action-close": "Tutup",
+    "ooui-outline-control-move-down": "Pindhahaken butir mangandhap"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ka.json b/resources/oojs-ui/i18n/ka.json
new file mode 100644 (file)
index 0000000..78180af
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "@metadata": {
+        "authors": [
+            "BRUTE",
+            "David1010",
+            "Gleki",
+            "ITshnik",
+            "MIKHEIL",
+            "NoiX180",
+            "Pras"
+        ]
+    },
+    "ooui-dialog-action-close": "დახურვა",
+    "ooui-outline-control-move-down": "ელემენტის ქვემოთ გადატანა",
+    "ooui-outline-control-move-up": "ელემენტის ზემოთ გადატანა"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/kk-cyrl.json b/resources/oojs-ui/i18n/kk-cyrl.json
new file mode 100644 (file)
index 0000000..4c27b07
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Arystanbek"
+        ]
+    },
+    "ooui-dialog-action-close": "Жабу",
+    "ooui-outline-control-move-down": "Элементті төмен жылжыту",
+    "ooui-outline-control-move-up": "Элементті жоғары жылжыту",
+    "ooui-toolbar-more": "толығырақ"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ko.json b/resources/oojs-ui/i18n/ko.json
new file mode 100644 (file)
index 0000000..f1f61df
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "@metadata": {
+        "authors": [
+            "Freebiekr",
+            "Hym411",
+            "Kwj2772",
+            "LFM",
+            "아라"
+        ]
+    },
+    "ooui-dialog-action-close": "닫기",
+    "ooui-outline-control-move-down": "항목을 아래로 옮기기",
+    "ooui-outline-control-move-up": "항목을 위로 옮기기",
+    "ooui-toolbar-more": "더 보기"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/krc.json b/resources/oojs-ui/i18n/krc.json
new file mode 100644 (file)
index 0000000..f629139
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Iltever"
+        ]
+    },
+    "ooui-dialog-action-close": "Джаб",
+    "ooui-outline-control-move-down": "Элементни тюбюне кёчюр",
+    "ooui-outline-control-move-up": "Элементни башына кёчюр"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/kw.json b/resources/oojs-ui/i18n/kw.json
new file mode 100644 (file)
index 0000000..95a9b91
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "George Animal",
+            "Nrowe",
+            "Purodha"
+        ]
+    },
+    "ooui-dialog-action-close": "Degea"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ky.json b/resources/oojs-ui/i18n/ky.json
new file mode 100644 (file)
index 0000000..2d62bda
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Chorobek",
+            "George Animal",
+            "Nrowe",
+            "Tynchtyk Chorotegin",
+            "Викиней"
+        ]
+    },
+    "ooui-dialog-action-close": "Жабуу"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/lb.json b/resources/oojs-ui/i18n/lb.json
new file mode 100644 (file)
index 0000000..a18894e
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "@metadata": {
+        "authors": [
+            "Autokrator",
+            "Chorobek",
+            "Robby",
+            "Soued031",
+            "Tynchtyk Chorotegin",
+            "UV",
+            "Викиней"
+        ]
+    },
+    "ooui-dialog-action-close": "Zoumaachen",
+    "ooui-outline-control-move-down": "Element erof réckelen",
+    "ooui-outline-control-move-up": "Element erop réckelen",
+    "ooui-toolbar-more": "Méi"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/lmo.json b/resources/oojs-ui/i18n/lmo.json
new file mode 100644 (file)
index 0000000..e506b7a
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ninonino"
+        ]
+    },
+    "ooui-dialog-action-close": "Sèra",
+    "ooui-outline-control-move-down": "Spòsta 'n zó",
+    "ooui-outline-control-move-up": "Spòsta 'n sö",
+    "ooui-toolbar-more": "Amò"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/lt.json b/resources/oojs-ui/i18n/lt.json
new file mode 100644 (file)
index 0000000..b3a16e8
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Audriusa",
+            "Eitvys200"
+        ]
+    },
+    "ooui-dialog-action-close": "Uždaryti"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/lv.json b/resources/oojs-ui/i18n/lv.json
new file mode 100644 (file)
index 0000000..c633339
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "@metadata": {
+        "authors": [
+            "Admresdeserv.",
+            "Audriusa",
+            "Eitvys200",
+            "Papuass",
+            "PeterisP"
+        ]
+    },
+    "ooui-dialog-action-close": "Aizvērt",
+    "ooui-outline-control-move-down": "Pārvietot vienumu uz leju",
+    "ooui-outline-control-move-up": "Pārvietot vienumu uz augšu",
+    "ooui-toolbar-more": "Vairāk"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/mg.json b/resources/oojs-ui/i18n/mg.json
new file mode 100644 (file)
index 0000000..dcb5fd5
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "Jagwar"
+        ]
+    },
+    "ooui-dialog-action-close": "Hidiana"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/min.json b/resources/oojs-ui/i18n/min.json
new file mode 100644 (file)
index 0000000..55174c0
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Iwan Novirion",
+            "Jagwar"
+        ]
+    },
+    "ooui-dialog-action-close": "Tutuik"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/mk.json b/resources/oojs-ui/i18n/mk.json
new file mode 100644 (file)
index 0000000..b363a45
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Bjankuloski06",
+            "Brest",
+            "Iwan Novirion"
+        ]
+    },
+    "ooui-dialog-action-close": "Затвори",
+    "ooui-outline-control-move-down": "Помести надолу",
+    "ooui-outline-control-move-up": "Помести нагоре",
+    "ooui-toolbar-more": "Повеќе"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ml.json b/resources/oojs-ui/i18n/ml.json
new file mode 100644 (file)
index 0000000..355e337
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Kavya Manohar",
+            "Praveenp",
+            "Santhosh.thottingal",
+            "Vssun"
+        ]
+    },
+    "ooui-dialog-action-close": "അടയ്ക്കുക",
+    "ooui-outline-control-move-down": "ഇനം താഴേയ്ക്ക് മാറ്റുക",
+    "ooui-outline-control-move-up": "ഇനം മുകളിലേയ്ക്ക് മാറ്റുക",
+    "ooui-toolbar-more": "കൂടുതൽ"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/mr.json b/resources/oojs-ui/i18n/mr.json
new file mode 100644 (file)
index 0000000..d4db84f
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "@metadata": {
+        "authors": [
+            "Kaajawa",
+            "Mahitgar",
+            "Praju23",
+            "V.narsikar",
+            "Ydyashad",
+            "संतोष दहिवळ"
+        ]
+    },
+    "ooui-dialog-action-close": "बंद करा",
+    "ooui-outline-control-move-down": "घटक (आयटम) खाली सरकवा",
+    "ooui-outline-control-move-up": "घटक (आयटम) वर सरकवा",
+    "ooui-toolbar-more": "अधिक"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ms.json b/resources/oojs-ui/i18n/ms.json
new file mode 100644 (file)
index 0000000..21aef50
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Anakmalaysia",
+            "Aurora"
+        ]
+    },
+    "ooui-dialog-action-close": "Tutup",
+    "ooui-outline-control-move-down": "Alihkan perkara ke bawah",
+    "ooui-outline-control-move-up": "Alihkan perkara ke atas",
+    "ooui-toolbar-more": "Lagi"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nap.json b/resources/oojs-ui/i18n/nap.json
new file mode 100644 (file)
index 0000000..6b0b3ec
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Chelin",
+            "Chrisportelli",
+            "PiRSquared17"
+        ]
+    },
+    "ooui-dialog-action-close": "Chiure",
+    "ooui-toolbar-more": "Atro"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nb.json b/resources/oojs-ui/i18n/nb.json
new file mode 100644 (file)
index 0000000..7cdecaa
--- /dev/null
@@ -0,0 +1,15 @@
+{
+    "@metadata": {
+        "authors": [
+            "Danmichaelo",
+            "Event",
+            "Jeblad",
+            "Laaknor",
+            "Njardarlogar"
+        ]
+    },
+    "ooui-dialog-action-close": "Lukk",
+    "ooui-outline-control-move-down": "Flytt ned",
+    "ooui-outline-control-move-up": "Flytt opp",
+    "ooui-toolbar-more": "Mer"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nds-nl.json b/resources/oojs-ui/i18n/nds-nl.json
new file mode 100644 (file)
index 0000000..81f8a43
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Servien"
+        ]
+    },
+    "ooui-dialog-action-close": "Sluten",
+    "ooui-outline-control-move-down": "Onderwarp ummeneer zetten",
+    "ooui-outline-control-move-up": "Onderwarp umhoge zetten"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nds.json b/resources/oojs-ui/i18n/nds.json
new file mode 100644 (file)
index 0000000..d0806d0
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Zylbath"
+        ]
+    },
+    "ooui-dialog-action-close": "Dichtmaken",
+    "ooui-outline-control-move-down": "Element na ünnen schuven",
+    "ooui-outline-control-move-up": "Element na baven schuven",
+    "ooui-toolbar-more": "Mehr"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ne.json b/resources/oojs-ui/i18n/ne.json
new file mode 100644 (file)
index 0000000..ae948c6
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "@metadata": {
+        "authors": [
+            "RajeshPandey",
+            "सरोज कुमार ढकाल"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nl.json b/resources/oojs-ui/i18n/nl.json
new file mode 100644 (file)
index 0000000..75db0a7
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    "@metadata": {
+        "authors": [
+            "Bluyten",
+            "Breghtje",
+            "Catrope",
+            "Flightmare",
+            "Hansmuller",
+            "Jdforrester",
+            "Keegan",
+            "Konovalov",
+            "RajeshPandey",
+            "Romaine",
+            "SPQRobin",
+            "Saruman",
+            "Siebrand",
+            "Southparkfan",
+            "सरोज कुमार ढकाल"
+        ]
+    },
+    "ooui-dialog-action-close": "Sluiten",
+    "ooui-outline-control-move-down": "Item omlaag verplaatsen",
+    "ooui-outline-control-move-up": "Item omhoog verplaatsen",
+    "ooui-toolbar-more": "Meer"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/nn.json b/resources/oojs-ui/i18n/nn.json
new file mode 100644 (file)
index 0000000..dd86f5e
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Jeblad",
+            "Njardarlogar"
+        ]
+    },
+    "ooui-dialog-action-close": "Lat att",
+    "ooui-outline-control-move-down": "Flytt element ned",
+    "ooui-outline-control-move-up": "Flytt element opp",
+    "ooui-toolbar-more": "Fleire"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/om.json b/resources/oojs-ui/i18n/om.json
new file mode 100644 (file)
index 0000000..dca7b7d
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cedric31",
+            "Tumsaa"
+        ]
+    },
+    "ooui-dialog-action-close": "Cufi",
+    "ooui-outline-control-move-down": "Gad buusi",
+    "ooui-outline-control-move-up": "Ol baasi",
+    "ooui-toolbar-more": "Dabalata"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/or.json b/resources/oojs-ui/i18n/or.json
new file mode 100644 (file)
index 0000000..35721a1
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Odisha1",
+            "Psubhashish",
+            "ଶିତିକଣ୍ଠ ଦାଶ"
+        ]
+    },
+    "ooui-dialog-action-close": "ବନ୍ଦ କରିବେ"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/pa.json b/resources/oojs-ui/i18n/pa.json
new file mode 100644 (file)
index 0000000..6c76d7f
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Amikeco",
+            "Babanwalia",
+            "Bouron",
+            "Nasir8891"
+        ]
+    },
+    "ooui-dialog-action-close": "বন্ধ"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/pl.json b/resources/oojs-ui/i18n/pl.json
new file mode 100644 (file)
index 0000000..ba33322
--- /dev/null
@@ -0,0 +1,22 @@
+{
+    "@metadata": {
+        "authors": [
+            "Babanwalia",
+            "Chrumps",
+            "Matma Rex",
+            "Mikołka",
+            "Nasir8891",
+            "Odie2",
+            "Rzuwig",
+            "Tar Lócesilion",
+            "Ty221",
+            "WTM",
+            "Woytecr",
+            "Wpedzich"
+        ]
+    },
+    "ooui-dialog-action-close": "Zamknij",
+    "ooui-outline-control-move-down": "Przenieś niżej",
+    "ooui-outline-control-move-up": "Przenieś wyżej",
+    "ooui-toolbar-more": "Więcej"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/pms.json b/resources/oojs-ui/i18n/pms.json
new file mode 100644 (file)
index 0000000..bb8f113
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Borichèt",
+            "Dragonòt",
+            "පසිඳු කාවින්ද"
+        ]
+    },
+    "ooui-dialog-action-close": "Saré",
+    "ooui-outline-control-move-down": "Fé calé giù l'element",
+    "ooui-outline-control-move-up": "Fé monté l'element",
+    "ooui-toolbar-more": "Ëd pi"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ps.json b/resources/oojs-ui/i18n/ps.json
new file mode 100644 (file)
index 0000000..4f21707
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ahmed-Najib-Biabani-Ibrahimkhel"
+        ]
+    },
+    "ooui-dialog-action-close": "تړل",
+    "ooui-outline-control-move-down": "توکی ښکته راوړل",
+    "ooui-outline-control-move-up": "توکی پورته راوړل",
+    "ooui-toolbar-more": "نور"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/pt-br.json b/resources/oojs-ui/i18n/pt-br.json
new file mode 100644 (file)
index 0000000..f758660
--- /dev/null
@@ -0,0 +1,19 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cainamarques",
+            "Dianakc",
+            "Fúlvio",
+            "Helder.wiki",
+            "HenriqueCrang",
+            "Jaideraf",
+            "Luckas",
+            "OTAVIO1981",
+            555
+        ]
+    },
+    "ooui-dialog-action-close": "Fechar",
+    "ooui-outline-control-move-down": "Mover item para baixo",
+    "ooui-outline-control-move-up": "Mover item para cima",
+    "ooui-toolbar-more": "Mais"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/pt.json b/resources/oojs-ui/i18n/pt.json
new file mode 100644 (file)
index 0000000..a4dba27
--- /dev/null
@@ -0,0 +1,19 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cainamarques",
+            "Fúlvio",
+            "GoEThe",
+            "Hamilton Abreu",
+            "Helder.wiki",
+            "Jaideraf",
+            "Jdforrester",
+            "Luckas",
+            "Vitorvicentevalente"
+        ]
+    },
+    "ooui-dialog-action-close": "Fechar",
+    "ooui-outline-control-move-down": "Mover item para baixo",
+    "ooui-outline-control-move-up": "Mover item para cima",
+    "ooui-toolbar-more": "Mais"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/qqq.json b/resources/oojs-ui/i18n/qqq.json
new file mode 100644 (file)
index 0000000..78a70d9
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    "@metadata": {
+        "authors": [
+            "Amire80",
+            "Beta16",
+            "Erik Moeller",
+            "Jdforrester",
+            "Lloffiwr",
+            "Mooeypoo",
+            "Mormegil",
+            "Nike",
+            "PoLuX124",
+            "Purodha",
+            "Raymond",
+            "Sagan",
+            "Sayak Sarkar",
+            "Shirayuki",
+            "Siebrand",
+            "Trevor Parscal"
+        ]
+    },
+    "ooui-dialog-action-close": "Label text for button to exit from dialog.\n\n{{Identical|Close}}",
+    "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-toolbar-more": "Label for the toolbar group that contains a list of all other available tools.\n{{Identical|More}}"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/qu.json b/resources/oojs-ui/i18n/qu.json
new file mode 100644 (file)
index 0000000..9a412f5
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "AlimanRuna"
+        ]
+    },
+    "ooui-dialog-action-close": "Wichq'ay",
+    "ooui-outline-control-move-down": "Qallawata uraykuchiy",
+    "ooui-outline-control-move-up": "Qallawata huqariy",
+    "ooui-toolbar-more": "Aswan"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ro.json b/resources/oojs-ui/i18n/ro.json
new file mode 100644 (file)
index 0000000..861b2fe
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "AlimanRuna",
+            "Firilacroco",
+            "Minisarm",
+            "Stelistcristi"
+        ]
+    },
+    "ooui-dialog-action-close": "Închide",
+    "ooui-outline-control-move-down": "Mută elementul mai jos",
+    "ooui-outline-control-move-up": "Mută elementul mai sus",
+    "ooui-toolbar-more": "Mai mult"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/roa-tara.json b/resources/oojs-ui/i18n/roa-tara.json
new file mode 100644 (file)
index 0000000..c7699d6
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Joetaras"
+        ]
+    },
+    "ooui-dialog-action-close": "Achiude",
+    "ooui-outline-control-move-down": "Spuèste 'a vôsce sotte",
+    "ooui-outline-control-move-up": "Spuèste 'a vôsce sus",
+    "ooui-toolbar-more": "De cchiù"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ru.json b/resources/oojs-ui/i18n/ru.json
new file mode 100644 (file)
index 0000000..be7c6a5
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    "@metadata": {
+        "authors": [
+            "Amire80",
+            "DR",
+            "Eugrus",
+            "Iluvatar",
+            "KPu3uC B Poccuu",
+            "Kalan",
+            "MaxBioHazard",
+            "NBS",
+            "Niklem",
+            "Okras",
+            "Ole Yves",
+            "Putnik",
+            "Sunpriat",
+            "Yury Katkov",
+            "Умар"
+        ]
+    },
+    "ooui-dialog-action-close": "Закрыть",
+    "ooui-outline-control-move-down": "Переместить элемент вниз",
+    "ooui-outline-control-move-up": "Переместить элемент вверх",
+    "ooui-toolbar-more": "Ещё"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sah.json b/resources/oojs-ui/i18n/sah.json
new file mode 100644 (file)
index 0000000..9b3fcc8
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Gazeb",
+            "HalanTul"
+        ]
+    },
+    "ooui-dialog-action-close": "Сап"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/scn.json b/resources/oojs-ui/i18n/scn.json
new file mode 100644 (file)
index 0000000..a699911
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Gazeb",
+            "Gmelfi",
+            "HalanTul"
+        ]
+    },
+    "ooui-dialog-action-close": "Chiùi",
+    "ooui-outline-control-move-down": "Sposta di sutta",
+    "ooui-outline-control-move-up": "Sposta di supra",
+    "ooui-toolbar-more": "Àutri cosi"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sh.json b/resources/oojs-ui/i18n/sh.json
new file mode 100644 (file)
index 0000000..5e29980
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "OC Ripper"
+        ]
+    },
+    "ooui-dialog-action-close": "Zatvori",
+    "ooui-outline-control-move-down": "Pomakni stavku dolje",
+    "ooui-outline-control-move-up": "Pomakni stavku gore"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/si.json b/resources/oojs-ui/i18n/si.json
new file mode 100644 (file)
index 0000000..cf7a9fd
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Singhalawap",
+            "පසිඳු කාවින්ද",
+            "ශ්වෙත"
+        ]
+    },
+    "ooui-dialog-action-close": "නිමවන්න",
+    "ooui-outline-control-move-down": "අයිතමය පහලටදමන්න",
+    "ooui-outline-control-move-up": "අයිතමය ඉහලටදමන්න"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sk.json b/resources/oojs-ui/i18n/sk.json
new file mode 100644 (file)
index 0000000..60b6f43
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Mimarik",
+            "Teslaton"
+        ]
+    },
+    "ooui-dialog-action-close": "Zatvoriť",
+    "ooui-outline-control-move-down": "Posunúť položku nadol",
+    "ooui-outline-control-move-up": "Posunúť položku nahor",
+    "ooui-toolbar-more": "Viac"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sl.json b/resources/oojs-ui/i18n/sl.json
new file mode 100644 (file)
index 0000000..d5bffd9
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Dbc334",
+            "Eleassar",
+            "Pinky sl",
+            "Yerpo"
+        ]
+    },
+    "ooui-dialog-action-close": "Zapri",
+    "ooui-outline-control-move-down": "Prestavi predmet nižje",
+    "ooui-outline-control-move-up": "Prestavi predmet višje",
+    "ooui-toolbar-more": "Več"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sq.json b/resources/oojs-ui/i18n/sq.json
new file mode 100644 (file)
index 0000000..424f1be
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Euriditi"
+        ]
+    },
+    "ooui-dialog-action-close": "Mbylle",
+    "ooui-outline-control-move-down": "Zhvendose artikullin më poshtë",
+    "ooui-outline-control-move-up": "Zhvendose artikullin më lart",
+    "ooui-toolbar-more": "Më tepër..."
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sr-ec.json b/resources/oojs-ui/i18n/sr-ec.json
new file mode 100644 (file)
index 0000000..973baec
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Milicevic01",
+            "Nikola Smolenski",
+            "Милан Јелисавчић"
+        ]
+    },
+    "ooui-dialog-action-close": "Затвори",
+    "ooui-outline-control-move-down": "Премести ставку на доле",
+    "ooui-outline-control-move-up": "Премести ставку на горе",
+    "ooui-toolbar-more": "Више"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sv.json b/resources/oojs-ui/i18n/sv.json
new file mode 100644 (file)
index 0000000..74d654b
--- /dev/null
@@ -0,0 +1,20 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ainali",
+            "Haxpett",
+            "Jopparn",
+            "Knuckles",
+            "Magol",
+            "Milicevic01",
+            "Per",
+            "Sendelbach",
+            "Skalman",
+            "WikiPhoenix"
+        ]
+    },
+    "ooui-dialog-action-close": "Stäng",
+    "ooui-outline-control-move-down": "Flytta ned objekt",
+    "ooui-outline-control-move-up": "Flytta upp objekt",
+    "ooui-toolbar-more": "Mer"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/sw.json b/resources/oojs-ui/i18n/sw.json
new file mode 100644 (file)
index 0000000..1c61b06
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Lloffiwr",
+            "Muddyb Blast Producer"
+        ]
+    },
+    "ooui-dialog-action-close": "Funga",
+    "ooui-outline-control-move-down": "Sogeza kipengee chini",
+    "ooui-outline-control-move-up": "Sogeza kipengee juu",
+    "ooui-toolbar-more": "Zaidi"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ta.json b/resources/oojs-ui/i18n/ta.json
new file mode 100644 (file)
index 0000000..a9795fd
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Jayarathina",
+            "Sank",
+            "Shanmugamp7",
+            "மதனாஹரன்"
+        ]
+    },
+    "ooui-dialog-action-close": "மூடுக"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/te.json b/resources/oojs-ui/i18n/te.json
new file mode 100644 (file)
index 0000000..a1f1285
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "Arjunaraoc",
+            "Jayarathina",
+            "Sank",
+            "Shanmugamp7",
+            "Veeven",
+            "Visdaviva",
+            "மதனாஹரன்"
+        ]
+    },
+    "ooui-dialog-action-close": "మూయి"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/th.json b/resources/oojs-ui/i18n/th.json
new file mode 100644 (file)
index 0000000..b7ee05a
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Supasate",
+            "Taweetham"
+        ]
+    },
+    "ooui-dialog-action-close": "ปิด",
+    "ooui-outline-control-move-down": "เลื่อนรายการลง",
+    "ooui-outline-control-move-up": "ย้ายรายการขึ้น"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/tl.json b/resources/oojs-ui/i18n/tl.json
new file mode 100644 (file)
index 0000000..a073882
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "AnakngAraw",
+            "Sky Harbor"
+        ]
+    },
+    "ooui-dialog-action-close": "Isara",
+    "ooui-outline-control-move-down": "Ilipat ang aytem pababa",
+    "ooui-outline-control-move-up": "Ilipat ang aytem pataas",
+    "ooui-toolbar-more": "Marami pa"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/tr.json b/resources/oojs-ui/i18n/tr.json
new file mode 100644 (file)
index 0000000..94d34a2
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "@metadata": {
+        "authors": [
+            "Emperyan",
+            "Incelemeelemani",
+            "LuCKY",
+            "Maidis",
+            "Rapsar",
+            "Talha Samil Cakir",
+            "TurkishStyles"
+        ]
+    },
+    "ooui-dialog-action-close": "Kapat",
+    "ooui-outline-control-move-down": "Ögeyi aşağı taşı",
+    "ooui-outline-control-move-up": "Ögeyi yukarı taşı",
+    "ooui-toolbar-more": "Daha fazla"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/tt-cyrl.json b/resources/oojs-ui/i18n/tt-cyrl.json
new file mode 100644 (file)
index 0000000..1c0bd90
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "@metadata": {
+        "authors": [
+            "Ajdar"
+        ]
+    },
+    "ooui-dialog-action-close": "Ябу",
+    "ooui-outline-control-move-down": "Элементны аска күчерү",
+    "ooui-outline-control-move-up": "Элементны өскә күчерү"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/ug-arab.json b/resources/oojs-ui/i18n/ug-arab.json
new file mode 100644 (file)
index 0000000..efba086
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Sahran",
+            "Tel'et",
+            "Tifinaghes"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/uk.json b/resources/oojs-ui/i18n/uk.json
new file mode 100644 (file)
index 0000000..9a47ad7
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    "@metadata": {
+        "authors": [
+            "AS",
+            "Aced",
+            "Ahonc",
+            "Andriykopanytsia",
+            "Base",
+            "Perohanych",
+            "RLuts",
+            "Sahran",
+            "Sergento",
+            "Steve.rusyn",
+            "SteveR",
+            "Tel'et",
+            "Tifinaghes",
+            "Ата"
+        ]
+    },
+    "ooui-dialog-action-close": "Закрити",
+    "ooui-outline-control-move-down": "Перемістити елемент униз",
+    "ooui-outline-control-move-up": "Перемістити елемент вгору",
+    "ooui-toolbar-more": "Більше"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/uz.json b/resources/oojs-ui/i18n/uz.json
new file mode 100644 (file)
index 0000000..473fc75
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "@metadata": {
+        "authors": [
+            "CoderSI",
+            "Noor2020",
+            "Sociologist",
+            "පසිඳු කාවින්ද"
+        ]
+    },
+    "ooui-dialog-action-close": "Yopish",
+    "ooui-outline-control-move-down": "Elementni pastga koʻchirish",
+    "ooui-outline-control-move-up": "Elementni yuqoriga koʻchirish",
+    "ooui-toolbar-more": "Yana"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/vec.json b/resources/oojs-ui/i18n/vec.json
new file mode 100644 (file)
index 0000000..01833f7
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "@metadata": {
+        "authors": [
+            "Candalua",
+            "GatoSelvadego"
+        ]
+    },
+    "ooui-dialog-action-close": "Sara",
+    "ooui-outline-control-move-down": "Sposta in baso",
+    "ooui-outline-control-move-up": "Sposta in sima",
+    "ooui-toolbar-more": "Altro"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/vi.json b/resources/oojs-ui/i18n/vi.json
new file mode 100644 (file)
index 0000000..b545ce6
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Cheers!",
+            "Jdforrester",
+            "Minh Nguyen"
+        ]
+    },
+    "ooui-dialog-action-close": "Đóng",
+    "ooui-outline-control-move-down": "Chuyển mục xuống",
+    "ooui-outline-control-move-up": "Chuyển mục lên",
+    "ooui-toolbar-more": "Thêm"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/vo.json b/resources/oojs-ui/i18n/vo.json
new file mode 100644 (file)
index 0000000..2ed7e2f
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Malafaya"
+        ]
+    },
+    "ooui-dialog-action-close": "Färmükön",
+    "ooui-toolbar-more": "Pluikos"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/wuu.json b/resources/oojs-ui/i18n/wuu.json
new file mode 100644 (file)
index 0000000..72aa48b
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "@metadata": {
+        "authors": [
+            "Malafaya",
+            "十弌"
+        ]
+    },
+    "ooui-toolbar-more": "還多"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/yi.json b/resources/oojs-ui/i18n/yi.json
new file mode 100644 (file)
index 0000000..ab5c510
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "@metadata": {
+        "authors": [
+            "Malafaya",
+            "פוילישער",
+            "十弌"
+        ]
+    },
+    "ooui-dialog-action-close": "שליסן",
+    "ooui-outline-control-move-down": "רוקן עלעמענט אראפ",
+    "ooui-outline-control-move-up": "רוקן עלעמענט ארויף",
+    "ooui-toolbar-more": "נאך"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/yo.json b/resources/oojs-ui/i18n/yo.json
new file mode 100644 (file)
index 0000000..f71d3dd
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "@metadata": {
+        "authors": [
+            "Demmy"
+        ]
+    },
+    "ooui-dialog-action-close": "Ìpadé",
+    "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"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/zh-hans.json b/resources/oojs-ui/i18n/zh-hans.json
new file mode 100644 (file)
index 0000000..46cbae3
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    "@metadata": {
+        "authors": [
+            "Anakmalaysia",
+            "Bencmq",
+            "Demmy",
+            "Hydra",
+            "Hzy980512",
+            "Liangent",
+            "Liuxinyu970226",
+            "Qiyue2001",
+            "Shirayuki",
+            "Shizhao",
+            "TianyinLee",
+            "Xiaomingyan",
+            "Yfdyh000",
+            "Zhangjintao",
+            "乌拉跨氪"
+        ]
+    },
+    "ooui-dialog-action-close": "关闭",
+    "ooui-outline-control-move-down": "下移项",
+    "ooui-outline-control-move-up": "上移项",
+    "ooui-toolbar-more": "更多"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/zh-hant.json b/resources/oojs-ui/i18n/zh-hant.json
new file mode 100644 (file)
index 0000000..9aace2f
--- /dev/null
@@ -0,0 +1,22 @@
+{
+    "@metadata": {
+        "authors": [
+            "Anakmalaysia",
+            "Ch.Andrew",
+            "Hydra",
+            "Justincheng12345",
+            "Liflon",
+            "Liuxinyu970226",
+            "Qiyue2001",
+            "Radish10cm",
+            "Shirayuki",
+            "Simon Shek",
+            "Spring Roll Conan",
+            "Waihorace"
+        ]
+    },
+    "ooui-dialog-action-close": "關閉",
+    "ooui-outline-control-move-down": "向下移項",
+    "ooui-outline-control-move-up": "向上移項",
+    "ooui-toolbar-more": "更多"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/zh-hk.json b/resources/oojs-ui/i18n/zh-hk.json
new file mode 100644 (file)
index 0000000..60e8fbd
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "@metadata": [],
+    "ooui-dialog-action-close": "關閉"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/i18n/zh-tw.json b/resources/oojs-ui/i18n/zh-tw.json
new file mode 100644 (file)
index 0000000..f7987e5
--- /dev/null
@@ -0,0 +1,7 @@
+{
+    "@metadata": [],
+    "ooui-dialog-action-close": "關閉",
+    "ooui-outline-control-move-down": "向下移",
+    "ooui-outline-control-move-up": "向上移",
+    "ooui-toolbar-more": "更多"
+}
\ No newline at end of file
diff --git a/resources/oojs-ui/images/fade-down.png b/resources/oojs-ui/images/fade-down.png
new file mode 100644 (file)
index 0000000..50c7931
Binary files /dev/null and b/resources/oojs-ui/images/fade-down.png differ
diff --git a/resources/oojs-ui/images/fade-up.png b/resources/oojs-ui/images/fade-up.png
new file mode 100644 (file)
index 0000000..7a0cb87
Binary files /dev/null and b/resources/oojs-ui/images/fade-up.png differ
diff --git a/resources/oojs-ui/images/icons/accept.png b/resources/oojs-ui/images/icons/accept.png
new file mode 100644 (file)
index 0000000..1075110
Binary files /dev/null and b/resources/oojs-ui/images/icons/accept.png differ
diff --git a/resources/oojs-ui/images/icons/accept.svg b/resources/oojs-ui/images/icons/accept.svg
new file mode 100644 (file)
index 0000000..df78186
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="apply" style="opacity:0.75;">
+       <polygon id="check" style="fill-rule:evenodd;clip-rule:evenodd;" points="19.062,5.139 17.418,4 8.867,16.357 5.413,12.903 4,14.316 9.021,19.338"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/add-item.png b/resources/oojs-ui/images/icons/add-item.png
new file mode 100644 (file)
index 0000000..aa36cd0
Binary files /dev/null and b/resources/oojs-ui/images/icons/add-item.png differ
diff --git a/resources/oojs-ui/images/icons/add-item.svg b/resources/oojs-ui/images/icons/add-item.svg
new file mode 100644 (file)
index 0000000..ff95399
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
+  <g id="add-item">
+    <path d="M13,8 L11,8 L11,11 L8,11 L8,13 L11,13 L11,16 L13,16 L13,13 L16,13 L16,11 L13,11 z" fill="#000000"/>
+  </g>
+  <defs/>
+</svg>
diff --git a/resources/oojs-ui/images/icons/advanced.png b/resources/oojs-ui/images/icons/advanced.png
new file mode 100644 (file)
index 0000000..7f5ada5
Binary files /dev/null and b/resources/oojs-ui/images/icons/advanced.png differ
diff --git a/resources/oojs-ui/images/icons/advanced.svg b/resources/oojs-ui/images/icons/advanced.svg
new file mode 100644 (file)
index 0000000..3e87cab
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="settings" style="opacity:0.75;">
+       <path id="gear" style="fill-rule:evenodd;clip-rule:evenodd;" d="M20.869,13.476C20.948,12.994,21,12.504,21,12
+               s-0.052-0.994-0.131-1.476l-2.463-0.259c-0.149-0.556-0.367-1.082-0.648-1.57l1.558-1.924c-0.576-0.806-1.281-1.511-2.087-2.087
+               l-1.924,1.558c-0.488-0.281-1.015-0.499-1.57-0.648l-0.259-2.463C12.994,3.052,12.504,3,12,3s-0.994,0.052-1.476,0.131
+               l-0.259,2.463C9.71,5.743,9.184,5.961,8.695,6.242L6.771,4.685C5.966,5.261,5.261,5.966,4.685,6.771l1.558,1.924
+               c-0.281,0.488-0.499,1.015-0.648,1.57l-2.463,0.259C3.052,11.006,3,11.496,3,12s0.052,0.994,0.131,1.476l2.463,0.259
+               c0.149,0.556,0.367,1.082,0.648,1.57l-1.558,1.924c0.576,0.806,1.281,1.511,2.087,2.087l1.924-1.558
+               c0.488,0.281,1.015,0.499,1.57,0.648l0.259,2.463C11.006,20.948,11.496,21,12,21s0.994-0.052,1.476-0.131l0.259-2.463
+               c0.556-0.149,1.082-0.367,1.57-0.648l1.924,1.558c0.806-0.576,1.511-1.281,2.087-2.087l-1.558-1.924
+               c0.281-0.488,0.499-1.015,0.648-1.57L20.869,13.476z M12,15.998c-2.209,0-3.998-1.789-3.998-3.998S9.791,8.002,12,8.002
+               S15.998,9.791,15.998,12S14.209,15.998,12,15.998z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/alert.png b/resources/oojs-ui/images/icons/alert.png
new file mode 100644 (file)
index 0000000..992ea2a
Binary files /dev/null and b/resources/oojs-ui/images/icons/alert.png differ
diff --git a/resources/oojs-ui/images/icons/alert.svg b/resources/oojs-ui/images/icons/alert.svg
new file mode 100644 (file)
index 0000000..886a7c0
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="alert" style="opacity:0.75;">
+       <rect id="point" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
+       <polygon id="stroke" style="fill-rule:evenodd;clip-rule:evenodd;" points="13.516,10 10.516,10 11,15 13,15"/>
+       <path id="triangle" d="M12.017,5.974L19.536,19H4.496L12.017,5.974 M12.017,3.5c-0.544,0-1.088,0.357-1.5,1.071L2.532,18.402 C1.707,19.831,2.382,21,4.032,21H20c1.65,0,2.325-1.169,1.5-2.599L13.517,4.572C13.104,3.857,12.561,3.5,12.017,3.5L12.017,3.5z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/arched-arrow-ltr.png b/resources/oojs-ui/images/icons/arched-arrow-ltr.png
new file mode 100644 (file)
index 0000000..5db1c4d
Binary files /dev/null and b/resources/oojs-ui/images/icons/arched-arrow-ltr.png differ
diff --git a/resources/oojs-ui/images/icons/arched-arrow-ltr.svg b/resources/oojs-ui/images/icons/arched-arrow-ltr.svg
new file mode 100644 (file)
index 0000000..5b343a5
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="arched-arrow-ltr" style="opacity:0.75;">
+       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M19.925,14.937l-2.391-6.901l-1.48,2.329 c-0.964-0.845-2.699-1.85-5.513-1.823c-4.887,0.046-6.524,4.244-6.524,4.244s2.753-2.639,6.925-1.949 c1.729,0.286,3.007,1.206,3.675,1.791l-1.474,2.319L19.925,14.937z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/arched-arrow-rtl.png b/resources/oojs-ui/images/icons/arched-arrow-rtl.png
new file mode 100644 (file)
index 0000000..7931971
Binary files /dev/null and b/resources/oojs-ui/images/icons/arched-arrow-rtl.png differ
diff --git a/resources/oojs-ui/images/icons/arched-arrow-rtl.svg b/resources/oojs-ui/images/icons/arched-arrow-rtl.svg
new file mode 100644 (file)
index 0000000..bb5f10e
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="arched-arrow-rtl" style="opacity:0.75;">
+       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M13.401,8.542c-2.814-0.027-4.549,0.978-5.513,1.823 l-1.48-2.329l-2.391,6.901l6.782,0.009l-1.474-2.319c0.668-0.584,1.945-1.504,3.675-1.791c4.172-0.69,6.925,1.949,6.925,1.949 S18.288,8.588,13.401,8.542z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/check.png b/resources/oojs-ui/images/icons/check.png
new file mode 100644 (file)
index 0000000..82c3cb4
Binary files /dev/null and b/resources/oojs-ui/images/icons/check.png differ
diff --git a/resources/oojs-ui/images/icons/check.svg b/resources/oojs-ui/images/icons/check.svg
new file mode 100644 (file)
index 0000000..e67cd6c
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
+  <g id="check">
+    <path d="M7.105,13.473 L8.527,12.05 L10.428,13.952 L15.238,7 L16.895,8.148 L10.635,17 z" fill="#000000"/>
+  </g>
+  <defs/>
+</svg>
diff --git a/resources/oojs-ui/images/icons/clear.png b/resources/oojs-ui/images/icons/clear.png
new file mode 100644 (file)
index 0000000..697dd62
Binary files /dev/null and b/resources/oojs-ui/images/icons/clear.png differ
diff --git a/resources/oojs-ui/images/icons/clear.svg b/resources/oojs-ui/images/icons/clear.svg
new file mode 100644 (file)
index 0000000..d83eb02
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="clear" style="opacity:0.75;">
+       <path id="circle_with_strike" style="fill-rule:evenodd;clip-rule:evenodd;" d="M11.999,5.022c-3.853,0-6.977,3.124-6.977,6.978 c0,3.853,3.124,6.978,6.977,6.978c3.854,0,6.979-3.125,6.979-6.978C18.978,8.146,15.853,5.022,11.999,5.022z M6.886,12 c0-1.092,0.572-3.25,0.93-2.929l7.113,7.113c0.488,0.525-1.837,0.931-2.93,0.931C9.174,17.114,6.886,14.824,6.886,12z M16.184,14.929L9.07,7.816c-0.445-0.483,1.837-0.931,2.929-0.931c2.827,0,5.115,2.289,5.115,5.114 C17.114,13.092,16.75,15.542,16.184,14.929z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/close.png b/resources/oojs-ui/images/icons/close.png
new file mode 100644 (file)
index 0000000..f7eed9f
Binary files /dev/null and b/resources/oojs-ui/images/icons/close.png differ
diff --git a/resources/oojs-ui/images/icons/close.svg b/resources/oojs-ui/images/icons/close.svg
new file mode 100644 (file)
index 0000000..a0118c2
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="close" style="opacity:0.75;">
+       <polygon id="x" style="fill-rule:evenodd;clip-rule:evenodd;" points="18.717,6.697 17.303,5.283 12,10.586 6.697,5.283 5.283,6.697 10.586,12 5.283,17.303 6.697,18.717 12,13.414 17.303,18.717 18.717,17.303 13.414,12            "/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/code.png b/resources/oojs-ui/images/icons/code.png
new file mode 100644 (file)
index 0000000..a5ebdbf
Binary files /dev/null and b/resources/oojs-ui/images/icons/code.png differ
diff --git a/resources/oojs-ui/images/icons/code.svg b/resources/oojs-ui/images/icons/code.svg
new file mode 100644 (file)
index 0000000..6f1ed53
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+        width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
+<g id="code" opacity="0.75">
+       <path id="left-bracket" d="M4,12v-1h1c1,0,1,0,1-1V7.614C6,7.1,6.024,6.718,6.073,6.472C6.127,6.22,6.212,6.009,6.33,5.839
+               C6.534,5.56,6.803,5.364,7.138,5.255C7.473,5.14,8.01,5,8.973,5H10v1H9.248c-0.457,0-0.77,0.191-0.936,0.408
+               C8.145,6.623,8,6.853,8,7.476v1.857c0,0.729-0.041,1.18-0.244,1.493c-0.2,0.307-0.562,0.529-1.09,0.667
+               c0.535,0.155,0.9,0.385,1.096,0.688C7.961,12.484,8,12.938,8,13.665v1.862c0,0.619,0.145,0.848,0.312,1.062
+               c0.166,0.22,0.479,0.407,0.936,0.407L10,17l0,0v1H8.973c-0.963,0-1.5-0.133-1.835-0.248c-0.335-0.109-0.604-0.307-0.808-0.591
+               c-0.118-0.165-0.203-0.374-0.257-0.625C6.024,16.283,6,15.9,6,15.387V13c0-1,0-1-1-1H4z"/>
+       <use transform="matrix(-1,0,0,1,24,0)" id="right-bracket" x="0" y="0" width="24" height="24" xlink:href="#left-bracket" />
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/collapse.png b/resources/oojs-ui/images/icons/collapse.png
new file mode 100644 (file)
index 0000000..38b796f
Binary files /dev/null and b/resources/oojs-ui/images/icons/collapse.png differ
diff --git a/resources/oojs-ui/images/icons/collapse.svg b/resources/oojs-ui/images/icons/collapse.svg
new file mode 100644 (file)
index 0000000..a89cebf
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="collapse" style="opacity:0.75;">
+       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="6.697,15.714 12,10.412 17.303,15.714 18.717,14.3 12,7.583 5.283,14.3"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/comment.png b/resources/oojs-ui/images/icons/comment.png
new file mode 100644 (file)
index 0000000..9546455
Binary files /dev/null and b/resources/oojs-ui/images/icons/comment.png differ
diff --git a/resources/oojs-ui/images/icons/comment.svg b/resources/oojs-ui/images/icons/comment.svg
new file mode 100644 (file)
index 0000000..e052935
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="comment" style="opacity:0.75;">
+       <path id="speech_bubble" style="fill-rule:evenodd;clip-rule:evenodd;" d="M15,6H9C7.343,6,6,7.344,6,9v4c0,1.656,1.343,3,3,3v3 l3-3h3c1.657,0,3-1.344,3-3V9C18,7.344,16.657,6,15,6z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/expand.png b/resources/oojs-ui/images/icons/expand.png
new file mode 100644 (file)
index 0000000..e90aca1
Binary files /dev/null and b/resources/oojs-ui/images/icons/expand.png differ
diff --git a/resources/oojs-ui/images/icons/expand.svg b/resources/oojs-ui/images/icons/expand.svg
new file mode 100644 (file)
index 0000000..b542f5f
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="expand" style="opacity:0.75;">
+       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="17.303,8.283 12,13.586 6.697,8.283 5.283,9.697 12,16.414 18.717,9.697"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/help.png b/resources/oojs-ui/images/icons/help.png
new file mode 100644 (file)
index 0000000..dca745b
Binary files /dev/null and b/resources/oojs-ui/images/icons/help.png differ
diff --git a/resources/oojs-ui/images/icons/help.svg b/resources/oojs-ui/images/icons/help.svg
new file mode 100644 (file)
index 0000000..c68bdda
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="help" style="opacity:0.75;">
+       <path id="circle" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12.001,2.085c-5.478,0-9.916,4.438-9.916,9.916 c0,5.476,4.438,9.914,9.916,9.914c5.476,0,9.914-4.438,9.914-9.914C21.915,6.523,17.477,2.085,12.001,2.085z M12.002,20.085 c-4.465,0-8.084-3.619-8.084-8.083c0-4.465,3.619-8.084,8.084-8.084c4.464,0,8.083,3.619,8.083,8.084 C20.085,16.466,16.466,20.085,12.002,20.085z"/>
+       <g id="question_mark">
+               <path id="top" style="fill-rule:evenodd;clip-rule:evenodd;" d="M11.766,6.688c-2.5,0-3.219,2.188-3.219,2.188l1.411,0.854 c0,0,0.298-0.791,0.901-1.229c0.516-0.375,1.625-0.625,2.219,0.125c0.701,0.885-0.17,1.587-1.078,2.719 C11.047,12.531,11,15,11,15h1.969c0,0,0.135-2.318,1.041-3.381c0.603-0.707,1.443-1.338,1.443-2.494S14.266,6.688,11.766,6.688z"/>
+               <rect id="bottom" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
+       </g>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/history.png b/resources/oojs-ui/images/icons/history.png
new file mode 100644 (file)
index 0000000..c049931
Binary files /dev/null and b/resources/oojs-ui/images/icons/history.png differ
diff --git a/resources/oojs-ui/images/icons/history.svg b/resources/oojs-ui/images/icons/history.svg
new file mode 100644 (file)
index 0000000..40c0ae3
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="history" style="opacity:0.75;">
+       <path id="clock_hands" style="fill-rule:evenodd;clip-rule:evenodd;" d="M17.26,15.076c0,0-2.385-1.935-4.005-3.062 c0.72-2.397,1.702-6.559,1.702-6.559s-4.35,5.363-4.877,6.699c-0.463,1.168,1.459,2.209,2.346,1.678 C14.326,14.383,17.26,15.076,17.26,15.076z"/>
+       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12.086,2.085c-5.478,0-9.916,4.438-9.916,9.916 c0,1.783,0.476,3.454,1.301,4.898l-2.223,2.04h5.688v-5.219l-2.066,1.896c-0.55-1.088-0.866-2.312-0.866-3.615 c0-4.465,3.619-8.084,8.084-8.084c4.464,0,8.083,3.619,8.083,8.084c0,4.464-3.619,8.083-8.083,8.083 c-1.145,0-2.228-0.247-3.213-0.678l-0.833,1.634c1.235,0.557,2.602,0.874,4.045,0.874c5.476,0,9.914-4.438,9.914-9.914 C22,6.523,17.562,2.085,12.086,2.085z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/link.png b/resources/oojs-ui/images/icons/link.png
new file mode 100644 (file)
index 0000000..7dfa268
Binary files /dev/null and b/resources/oojs-ui/images/icons/link.png differ
diff --git a/resources/oojs-ui/images/icons/link.svg b/resources/oojs-ui/images/icons/link.svg
new file mode 100644 (file)
index 0000000..dadf69c
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="link" style="opacity:0.75;">
+       <path id="right" d="M19.188,12.001c0,1.1-0.891,2.015-1.988,2.015l-4.195-0.015C13.543,15.089,13.968,16,15.002,16h3
+               C19.658,16,21,13.657,21,12s-1.342-4-2.998-4h-3c-1.034,0-1.459,0.911-1.998,1.999l4.195-0.015
+               C18.297,9.984,19.188,10.901,19.188,12.001z"/>
+       <path id="center" d="M8,12c0,0.535,0.42,1,0.938,1h6.109c0.518,0,0.938-0.465,0.938-1c0-0.534-0.42-1-0.938-1H8.938
+               C8.42,11,8,11.466,8,12z"/>
+       <path id="left" d="M4.816,11.999c0-1.1,0.891-2.015,1.988-2.015L11,9.999C10.461,8.911,10.036,8,9.002,8h-3
+               c-1.656,0-2.998,2.343-2.998,4s1.342,4,2.998,4h3c1.034,0,1.459-0.911,1.998-1.999l-4.195,0.015
+               C5.707,14.016,4.816,13.099,4.816,11.999z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/menu.png b/resources/oojs-ui/images/icons/menu.png
new file mode 100644 (file)
index 0000000..b5ac60f
Binary files /dev/null and b/resources/oojs-ui/images/icons/menu.png differ
diff --git a/resources/oojs-ui/images/icons/menu.svg b/resources/oojs-ui/images/icons/menu.svg
new file mode 100644 (file)
index 0000000..657fab2
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="menu" style="opacity:0.75;">
+       <path id="lines" d="M6,15h12c0.553,0,1,0.447,1,1v1c0,0.553-0.447,1-1,1H6c-0.553,0-1-0.447-1-1v-1C5,15.447,5.447,15,6,15z M5,11v1
+               c0,0.553,0.447,1,1,1h12c0.553,0,1-0.447,1-1v-1c0-0.553-0.447-1-1-1H6C5.447,10,5,10.447,5,11z M5,6v1c0,0.553,0.447,1,1,1h12
+               c0.553,0,1-0.447,1-1V6c0-0.553-0.447-1-1-1H6C5.447,5,5,5.447,5,6z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/move-ltr.png b/resources/oojs-ui/images/icons/move-ltr.png
new file mode 100644 (file)
index 0000000..ded5f05
Binary files /dev/null and b/resources/oojs-ui/images/icons/move-ltr.png differ
diff --git a/resources/oojs-ui/images/icons/move-ltr.svg b/resources/oojs-ui/images/icons/move-ltr.svg
new file mode 100644 (file)
index 0000000..a378a5d
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="move-ltr" style="opacity:0.75;">
+       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="8.935,7.181 14.237,12.483 8.935,17.786
+               10.349,19.2 17.065,12.483 10.349,5.767"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/move-rtl.png b/resources/oojs-ui/images/icons/move-rtl.png
new file mode 100644 (file)
index 0000000..fc6e62d
Binary files /dev/null and b/resources/oojs-ui/images/icons/move-rtl.png differ
diff --git a/resources/oojs-ui/images/icons/move-rtl.svg b/resources/oojs-ui/images/icons/move-rtl.svg
new file mode 100644 (file)
index 0000000..c0b334b
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="move-rtl" style="opacity:0.75;">
+       <polygon id="arrow_9_" style="fill-rule:evenodd;clip-rule:evenodd;" points="15.065,17.786 9.763,12.483 15.065,7.181
+               13.651,5.767 6.935,12.483 13.651,19.2"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/picture.png b/resources/oojs-ui/images/icons/picture.png
new file mode 100644 (file)
index 0000000..faf8af9
Binary files /dev/null and b/resources/oojs-ui/images/icons/picture.png differ
diff --git a/resources/oojs-ui/images/icons/picture.svg b/resources/oojs-ui/images/icons/picture.svg
new file mode 100644 (file)
index 0000000..078ce10
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="picture" style="opacity:0.75;">
+       <path id="frame" style="fill-rule:evenodd;clip-rule:evenodd;" d="M18,4H6C4,3.993,3,4.993,3,6.993L3.014,16C3,18,4,18.988,6,19h12
+               c2-0.012,2.994-1,3-3.006V6.993C20.994,4.993,20,3.993,18,4z M19,17H5V6h14V17z"/>
+       <polygon id="mountains" style="fill-rule:evenodd;clip-rule:evenodd;" points="6,13.5 9.5,10 11.828,12.312 10.516,13.406
+               11.391,14.438 15.5,11 18,13 18,16 6,16"/>
+       <polygon id="sky" style="fill-rule:evenodd;clip-rule:evenodd;" points="6,12 9.516,7.844 12.562,11.016 15.5,9 18,11 18,7 6,7"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/remove-item.png b/resources/oojs-ui/images/icons/remove-item.png
new file mode 100644 (file)
index 0000000..2f11db3
Binary files /dev/null and b/resources/oojs-ui/images/icons/remove-item.png differ
diff --git a/resources/oojs-ui/images/icons/remove-item.svg b/resources/oojs-ui/images/icons/remove-item.svg
new file mode 100644 (file)
index 0000000..b95e7d3
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
+  <g id="remove-item">
+    <path d="M8,11 L16,11 L16,13 L8,13 z" fill="#000000"/>
+  </g>
+  <defs/>
+</svg>
diff --git a/resources/oojs-ui/images/icons/remove.png b/resources/oojs-ui/images/icons/remove.png
new file mode 100644 (file)
index 0000000..d7e116c
Binary files /dev/null and b/resources/oojs-ui/images/icons/remove.png differ
diff --git a/resources/oojs-ui/images/icons/remove.svg b/resources/oojs-ui/images/icons/remove.svg
new file mode 100644 (file)
index 0000000..17c8d39
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="remove" style="opacity:0.75;">
+       <path id="trash_can" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12,10h-1v6h1V10z M10,10H9v6h1V10z M14,10h-1v6h1V10z
+                M14,6V5H9v1H6v3h1v7.966l1,1.031v-0.074V18h6.984L15,17.982v0.015l1-1.031V9h1V6H14z M15,17H8V9h7V17z M16,8H7V7h9V8z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/search.png b/resources/oojs-ui/images/icons/search.png
new file mode 100644 (file)
index 0000000..df29792
Binary files /dev/null and b/resources/oojs-ui/images/icons/search.png differ
diff --git a/resources/oojs-ui/images/icons/search.svg b/resources/oojs-ui/images/icons/search.svg
new file mode 100644 (file)
index 0000000..37feda4
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="search" style="opacity:0.75;">
+       <path id="magnifying_glass" d="M16.021,15.96l-2.374-2.375c-0.048-0.047-0.105-0.079-0.169-0.099c0.403-0.566,0.643-1.26,0.643-2.009
+               C14.12,9.557,12.563,8,10.644,8c-1.921,0-3.478,1.557-3.478,3.478c0,1.92,1.557,3.477,3.478,3.477c0.749,0,1.442-0.239,2.01-0.643
+               c0.019,0.063,0.051,0.121,0.098,0.169l2.375,2.374c0.19,0.189,0.543,0.143,0.79-0.104S16.21,16.15,16.021,15.96z M10.644,13.69
+               c-1.221,0-2.213-0.991-2.213-2.213c0-1.221,0.992-2.213,2.213-2.213c1.222,0,2.213,0.992,2.213,2.213
+               C12.856,12.699,11.865,13.69,10.644,13.69z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/settings.png b/resources/oojs-ui/images/icons/settings.png
new file mode 100644 (file)
index 0000000..b1b35e9
Binary files /dev/null and b/resources/oojs-ui/images/icons/settings.png differ
diff --git a/resources/oojs-ui/images/icons/settings.svg b/resources/oojs-ui/images/icons/settings.svg
new file mode 100644 (file)
index 0000000..1464a79
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
+  <g id="settings" opacity="0.75">
+    <path d="M3,4 L6,4 L6,6 L3,6 z" fill="#000000"/>
+    <path d="M12,4 L21,4 L21,6 L12,6 z" fill="#000000"/>
+    <path d="M8,3 L10,3 C10.552,3 11,3.448 11,4 L11,6 C11,6.552 10.552,7 10,7 L8,7 C7.448,7 7,6.552 7,6 L7,4 C7,3.448 7.448,3 8,3 z" fill="#000000"/>
+    <path d="M3,11 L12,11 L12,13 L3,13 z" fill="#000000"/>
+    <path d="M18,11 L21,11 L21,13 L18,13 z" fill="#000000"/>
+    <path d="M14,10 L16,10 C16.552,10 17,10.448 17,11 L17,13 C17,13.552 16.552,14 16,14 L14,14 C13.448,14 13,13.552 13,13 L13,11 C13,10.448 13.448,10 14,10 z" fill="#000000"/>
+    <path d="M3,18 L9,18 L9,20 L3,20 z" fill="#000000"/>
+    <path d="M15,18 L21,18 L21,20 L15,20 z" fill="#000000"/>
+    <path d="M11,17 L13,17 C13.552,17 14,17.448 14,18 L14,20 C14,20.552 13.552,21 13,21 L11,21 C10.448,21 10,20.552 10,20 L10,18 C10,17.448 10.448,17 11,17 z" fill="#000000"/>
+  </g>
+  <defs/>
+</svg>
diff --git a/resources/oojs-ui/images/icons/tag.png b/resources/oojs-ui/images/icons/tag.png
new file mode 100644 (file)
index 0000000..722f4d7
Binary files /dev/null and b/resources/oojs-ui/images/icons/tag.png differ
diff --git a/resources/oojs-ui/images/icons/tag.svg b/resources/oojs-ui/images/icons/tag.svg
new file mode 100644 (file)
index 0000000..d21e5e3
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="tag" style="opacity:0.75;">
+       <path d="M18.748,11.717c0.389,0.389,0.389,1.025,0,1.414l-4.949,4.95c-0.389,0.389-1.025,0.389-1.414,0l-6.01-6.01
+               c-0.389-0.389-0.707-1.157-0.707-1.707L5.667,6c0-0.55,0.45-1,1-1h4.364c0.55,0,1.318,0.318,1.707,0.707L18.748,11.717z
+                M8.104,7.456C7.525,8.032,7.526,8.97,8.103,9.549c0.578,0.577,1.516,0.577,2.095,0.001c0.576-0.578,0.576-1.517,0-2.095
+               C9.617,6.879,8.68,6.878,8.104,7.456z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/icons/window.png b/resources/oojs-ui/images/icons/window.png
new file mode 100644 (file)
index 0000000..3d48a3c
Binary files /dev/null and b/resources/oojs-ui/images/icons/window.png differ
diff --git a/resources/oojs-ui/images/icons/window.svg b/resources/oojs-ui/images/icons/window.svg
new file mode 100644 (file)
index 0000000..621cf2c
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
+        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<g id="window" style="opacity:0.75;">
+       <rect id="title" x="7" y="10" width="10" height="1"/>
+       <path id="window" d="M16,19H8c-2.206,0-4-1.794-4-4V9c0-2.206,1.794-4,4-4h8c2.206,0,4,1.794,4,4v6C20,17.206,18.206,19,16,19z
+                M8,7C6.897,7,6,7.897,6,9v6c0,1.103,0.897,2,2,2h8c1.103,0,2-0.897,2-2V9c0-1.103-0.897-2-2-2H8z"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/indicators/down.png b/resources/oojs-ui/images/indicators/down.png
new file mode 100644 (file)
index 0000000..47ff54c
Binary files /dev/null and b/resources/oojs-ui/images/indicators/down.png differ
diff --git a/resources/oojs-ui/images/indicators/down.svg b/resources/oojs-ui/images/indicators/down.svg
new file mode 100644 (file)
index 0000000..c871f60
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
+        height="12px" viewBox="0 0 12 12" style="enable-background:new 0 0 12 12;" xml:space="preserve">
+<g id="down" style="opacity:0.75;">
+       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="2.023,3 5.512,8.953 9,3"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/indicators/required.png b/resources/oojs-ui/images/indicators/required.png
new file mode 100644 (file)
index 0000000..aeb35a3
Binary files /dev/null and b/resources/oojs-ui/images/indicators/required.png differ
diff --git a/resources/oojs-ui/images/indicators/required.svg b/resources/oojs-ui/images/indicators/required.svg
new file mode 100644 (file)
index 0000000..7c60ec0
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12" height="12" viewBox="0, 0, 12, 12">
+  <g id="required" opacity="0.75">
+    <path d="M7,0 L7,4.268 L10.696,2.134 L11.696,3.866 L8,6 L11.696,8.134 L10.696,9.866 L7,7.732 L7,12 L5,12 L5,7.732 L1.304,9.866 L0.304,8.134 L4,6 L0.304,3.866 L1.304,2.134 L5,4.268 L5,0 z" fill="#000000"/>
+  </g>
+  <defs/>
+</svg>
diff --git a/resources/oojs-ui/images/indicators/up.png b/resources/oojs-ui/images/indicators/up.png
new file mode 100644 (file)
index 0000000..b827f6d
Binary files /dev/null and b/resources/oojs-ui/images/indicators/up.png differ
diff --git a/resources/oojs-ui/images/indicators/up.svg b/resources/oojs-ui/images/indicators/up.svg
new file mode 100644 (file)
index 0000000..a5d7f38
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
+        height="12px" viewBox="0 0 12 12" style="enable-background:new 0 0 12 12;" xml:space="preserve">
+<g id="up" style="opacity:0.75;">
+       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="5.512,2.006 2,8 9.024,8                "/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/tail.svg b/resources/oojs-ui/images/tail.svg
new file mode 100644 (file)
index 0000000..4df8bb2
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+        width="15px" height="8px" viewBox="0 0 15 8" style="enable-background:new 0 0 15 8;" xml:space="preserve">
+<g id="tail">
+       <polygon id="outline" style="fill-rule:evenodd;clip-rule:evenodd;fill:#808080;" points="7.609,2.499 2.096,8 13.125,8"/>
+       <polygon id="fill" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;" points="7.609,3 2.598,8 12.622,8"/>
+</g>
+</svg>
diff --git a/resources/oojs-ui/images/textures/pending.gif b/resources/oojs-ui/images/textures/pending.gif
new file mode 100644 (file)
index 0000000..1194eed
Binary files /dev/null and b/resources/oojs-ui/images/textures/pending.gif differ
diff --git a/resources/oojs-ui/images/textures/transparency.png b/resources/oojs-ui/images/textures/transparency.png
new file mode 100644 (file)
index 0000000..b8e36d3
Binary files /dev/null and b/resources/oojs-ui/images/textures/transparency.png differ
diff --git a/resources/oojs-ui/images/toolbar-shadow.png b/resources/oojs-ui/images/toolbar-shadow.png
new file mode 100644 (file)
index 0000000..97e8d13
Binary files /dev/null and b/resources/oojs-ui/images/toolbar-shadow.png differ
diff --git a/resources/oojs-ui/oojs-ui.js b/resources/oojs-ui/oojs-ui.js
new file mode 100644 (file)
index 0000000..a58f65d
--- /dev/null
@@ -0,0 +1,7325 @@
+/*!
+ * OOjs UI v0.1.0-pre (a290673bbd)
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: Wed Feb 12 2014 13:52:08 GMT-0800 (PST)
+ */
+( function () {
+
+'use strict';
+/**
+ * Namespace for all classes, static methods and static properties.
+ *
+ * @class
+ * @singleton
+ */
+OO.ui = {};
+
+OO.ui.bind = $.proxy;
+
+/**
+ * Get the user's language and any fallback languages.
+ *
+ * These language codes are used to localize user interface elements in the user's language.
+ *
+ * In environments that provide a localization system, this function should be overridden to
+ * return the user's language(s). The default implementation returns English (en) only.
+ *
+ * @returns {string[]} Language codes, in descending order of priority
+ */
+OO.ui.getUserLanguages = function () {
+       return [ 'en' ];
+};
+
+/**
+ * Get a value in an object keyed by language code.
+ *
+ * @param {Object.<string,Mixed>} obj Object keyed by language code
+ * @param {string|null} [lang] Language code, if omitted or null defaults to any user language
+ * @param {string} [fallback] Fallback code, used if no matching language can be found
+ * @returns {Mixed} Local value
+ */
+OO.ui.getLocalValue = function ( obj, lang, fallback ) {
+       var i, len, langs;
+
+       // Requested language
+       if ( obj[lang] ) {
+               return obj[lang];
+       }
+       // Known user language
+       langs = OO.ui.getUserLanguages();
+       for ( i = 0, len = langs.length; i < len; i++ ) {
+               lang = langs[i];
+               if ( obj[lang] ) {
+                       return obj[lang];
+               }
+       }
+       // Fallback language
+       if ( obj[fallback] ) {
+               return obj[fallback];
+       }
+       // First existing language
+       for ( lang in obj ) {
+               return obj[lang];
+       }
+
+       return undefined;
+};
+
+( function () {
+
+/**
+ * Message store for the default implementation of OO.ui.msg
+ *
+ * Environments that provide a localization system should not use this, but should override
+ * OO.ui.msg altogether.
+ *
+ * @private
+ */
+var messages = {
+       // Label text for button to exit from dialog
+       'ooui-dialog-action-close': 'Close',
+       // Tool tip for a button that moves items in a list down one place
+       'ooui-outline-control-move-down': 'Move item down',
+       // Tool tip for a button that moves items in a list up one place
+       'ooui-outline-control-move-up': 'Move item up',
+       // Label for the toolbar group that contains a list of all other available tools
+       'ooui-toolbar-more': 'More'
+};
+
+/**
+ * Get a localized message.
+ *
+ * In environments that provide a localization system, this function should be overridden to
+ * return the message translated in the user's language. The default implementation always returns
+ * English messages.
+ *
+ * After the message key, message parameters may optionally be passed. In the default implementation,
+ * any occurrences of $1 are replaced with the first parameter, $2 with the second parameter, etc.
+ * Alternative implementations of OO.ui.msg may use any substitution system they like, as long as
+ * they support unnamed, ordered message parameters.
+ *
+ * @abstract
+ * @param {string} key Message key
+ * @param {Mixed...} [params] Message parameters
+ * @returns {string} Translated message with parameters substituted
+ */
+OO.ui.msg = function ( key ) {
+       var message = messages[key], params = Array.prototype.slice.call( arguments, 1 );
+       if ( typeof message === 'string' ) {
+               // Perform $1 substitution
+               message = message.replace( /\$(\d+)/g, function ( unused, n ) {
+                       var i = parseInt( n, 10 );
+                       return params[i - 1] !== undefined ? params[i - 1] : '$' + n;
+               } );
+       } else {
+               // Return placeholder if message not found
+               message = '[' + key + ']';
+       }
+       return message;
+};
+
+OO.ui.deferMsg = function ( key ) {
+       return function () {
+               return OO.ui.msg( key );
+       };
+};
+
+OO.ui.resolveMsg = function ( msg ) {
+       if ( $.isFunction( msg ) ) {
+               return msg();
+       }
+       return msg;
+};
+
+} )();
+
+// Add more as you need
+OO.ui.Keys = {
+       'UNDEFINED': 0,
+       'BACKSPACE': 8,
+       'DELETE': 46,
+       'LEFT': 37,
+       'RIGHT': 39,
+       'UP': 38,
+       'DOWN': 40,
+       'ENTER': 13,
+       'END': 35,
+       'HOME': 36,
+       'TAB': 9,
+       'PAGEUP': 33,
+       'PAGEDOWN': 34,
+       'ESCAPE': 27,
+       'SHIFT': 16,
+       'SPACE': 32
+};
+/**
+ * DOM element abstraction.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Function} [$] jQuery for the frame the widget is in
+ * @cfg {string[]} [classes] CSS class names
+ * @cfg {jQuery} [$content] Content elements to append
+ */
+OO.ui.Element = function OoUiElement( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Properties
+       this.$ = config.$ || OO.ui.Element.getJQuery( document );
+       this.$element = this.$( this.$.context.createElement( this.getTagName() ) );
+
+       // Initialization
+       if ( Array.isArray( config.classes ) ) {
+               this.$element.addClass( config.classes.join( ' ' ) );
+       }
+       if ( config.$content ) {
+               this.$element.append( config.$content );
+       }
+};
+
+/* Static Properties */
+
+/**
+ * @static
+ * @property
+ * @inheritable
+ */
+OO.ui.Element.static = {};
+
+/**
+ * HTML tag name.
+ *
+ * This may be ignored if getTagName is overridden.
+ *
+ * @static
+ * @property {string}
+ * @inheritable
+ */
+OO.ui.Element.static.tagName = 'div';
+
+/* Static Methods */
+
+/**
+ * Gets a jQuery function within a specific document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} context Context to bind the function to
+ * @param {OO.ui.Frame} [frame] Frame of the document context
+ * @returns {Function} Bound jQuery function
+ */
+OO.ui.Element.getJQuery = function ( context, frame ) {
+       function wrapper( selector ) {
+               return $( selector, wrapper.context );
+       }
+
+       wrapper.context = this.getDocument( context );
+
+       if ( frame ) {
+               wrapper.frame = frame;
+       }
+
+       return wrapper;
+};
+
+/**
+ * Get the document of an element.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Object to get the document for
+ * @returns {HTMLDocument} Document object
+ * @throws {Error} If context is invalid
+ */
+OO.ui.Element.getDocument = function ( obj ) {
+       var doc =
+               // jQuery - selections created "offscreen" won't have a context, so .context isn't reliable
+               ( obj[0] && obj[0].ownerDocument ) ||
+               // Empty jQuery selections might have a context
+               obj.context ||
+               // HTMLElement
+               obj.ownerDocument ||
+               // Window
+               obj.document ||
+               // HTMLDocument
+               ( obj.nodeType === 9 && obj );
+
+       if ( doc ) {
+               return doc;
+       }
+
+       throw new Error( 'Invalid context' );
+};
+
+/**
+ * Get the window of an element or document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the window for
+ * @returns {Window} Window object
+ */
+OO.ui.Element.getWindow = function ( obj ) {
+       var doc = this.getDocument( obj );
+       return doc.parentWindow || doc.defaultView;
+};
+
+/**
+ * Get the direction of an element or document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the direction for
+ * @returns {string} Text direction, either `ltr` or `rtl`
+ */
+OO.ui.Element.getDir = function ( obj ) {
+       var isDoc, isWin;
+
+       if ( obj instanceof jQuery ) {
+               obj = obj[0];
+       }
+       isDoc = obj.nodeType === 9;
+       isWin = obj.document !== undefined;
+       if ( isDoc || isWin ) {
+               if ( isWin ) {
+                       obj = obj.document;
+               }
+               obj = obj.body;
+       }
+       return $( obj ).css( 'direction' );
+};
+
+/**
+ * Get the offset between two frames.
+ *
+ * TODO: Make this function not use recursion.
+ *
+ * @static
+ * @param {Window} from Window of the child frame
+ * @param {Window} [to=window] Window of the parent frame
+ * @param {Object} [offset] Offset to start with, used internally
+ * @returns {Object} Offset object, containing left and top properties
+ */
+OO.ui.Element.getFrameOffset = function ( from, to, offset ) {
+       var i, len, frames, frame, rect;
+
+       if ( !to ) {
+               to = window;
+       }
+       if ( !offset ) {
+               offset = { 'top': 0, 'left': 0 };
+       }
+       if ( from.parent === from ) {
+               return offset;
+       }
+
+       // Get iframe element
+       frames = from.parent.document.getElementsByTagName( 'iframe' );
+       for ( i = 0, len = frames.length; i < len; i++ ) {
+               if ( frames[i].contentWindow === from ) {
+                       frame = frames[i];
+                       break;
+               }
+       }
+
+       // Recursively accumulate offset values
+       if ( frame ) {
+               rect = frame.getBoundingClientRect();
+               offset.left += rect.left;
+               offset.top += rect.top;
+               if ( from !== to ) {
+                       this.getFrameOffset( from.parent, offset );
+               }
+       }
+       return offset;
+};
+
+/**
+ * Get the offset between two elements.
+ *
+ * @static
+ * @param {jQuery} $from
+ * @param {jQuery} $to
+ * @returns {Object} Translated position coordinates, containing top and left properties
+ */
+OO.ui.Element.getRelativePosition = function ( $from, $to ) {
+       var from = $from.offset(),
+               to = $to.offset();
+       return { 'top': Math.round( from.top - to.top ), 'left': Math.round( from.left - to.left ) };
+};
+
+/**
+ * Get element border sizes.
+ *
+ * @static
+ * @param {HTMLElement} el Element to measure
+ * @return {Object} Dimensions object with `top`, `left`, `bottom` and `right` properties
+ */
+OO.ui.Element.getBorders = function ( el ) {
+       var doc = el.ownerDocument,
+               win = doc.parentWindow || doc.defaultView,
+               style = win && win.getComputedStyle ?
+                       win.getComputedStyle( el, null ) :
+                       el.currentStyle,
+               $el = $( el ),
+               top = parseFloat( style ? style.borderTopWidth : $el.css( 'borderTopWidth' ) ) || 0,
+               left = parseFloat( style ? style.borderLeftWidth : $el.css( 'borderLeftWidth' ) ) || 0,
+               bottom = parseFloat( style ? style.borderBottomWidth : $el.css( 'borderBottomWidth' ) ) || 0,
+               right = parseFloat( style ? style.borderRightWidth : $el.css( 'borderRightWidth' ) ) || 0;
+
+       return {
+               'top': Math.round( top ),
+               'left': Math.round( left ),
+               'bottom': Math.round( bottom ),
+               'right': Math.round( right )
+       };
+};
+
+/**
+ * Get dimensions of an element or window.
+ *
+ * @static
+ * @param {HTMLElement|Window} el Element to measure
+ * @return {Object} Dimensions object with `borders`, `scroll`, `scrollbar` and `rect` properties
+ */
+OO.ui.Element.getDimensions = function ( el ) {
+       var $el, $win,
+               doc = el.ownerDocument || el.document,
+               win = doc.parentWindow || doc.defaultView;
+
+       if ( win === el || el === doc.documentElement ) {
+               $win = $( win );
+               return {
+                       'borders': { 'top': 0, 'left': 0, 'bottom': 0, 'right': 0 },
+                       'scroll': {
+                               'top': $win.scrollTop(),
+                               'left': $win.scrollLeft()
+                       },
+                       'scrollbar': { 'right': 0, 'bottom': 0 },
+                       'rect': {
+                               'top': 0,
+                               'left': 0,
+                               'bottom': $win.innerHeight(),
+                               'right': $win.innerWidth()
+                       }
+               };
+       } else {
+               $el = $( el );
+               return {
+                       'borders': this.getBorders( el ),
+                       'scroll': {
+                               'top': $el.scrollTop(),
+                               'left': $el.scrollLeft()
+                       },
+                       'scrollbar': {
+                               'right': $el.innerWidth() - el.clientWidth,
+                               'bottom': $el.innerHeight() - el.clientHeight
+                       },
+                       'rect': el.getBoundingClientRect()
+               };
+       }
+};
+
+/**
+ * Get closest scrollable container.
+ *
+ * Traverses up until either a scrollable element or the root is reached, in which case the window
+ * will be returned.
+ *
+ * @static
+ * @param {HTMLElement} el Element to find scrollable container for
+ * @param {string} [dimension] Dimension of scrolling to look for; `x`, `y` or omit for either
+ * @return {HTMLElement|Window} Closest scrollable container
+ */
+OO.ui.Element.getClosestScrollableContainer = function ( el, dimension ) {
+       var i, val,
+               props = [ 'overflow' ],
+               $parent = $( el ).parent();
+
+       if ( dimension === 'x' || dimension === 'y' ) {
+               props.push( 'overflow-' + dimension );
+       }
+
+       while ( $parent.length ) {
+               if ( $parent[0] === el.ownerDocument.body ) {
+                       return $parent[0];
+               }
+               i = props.length;
+               while ( i-- ) {
+                       val = $parent.css( props[i] );
+                       if ( val === 'auto' || val === 'scroll' ) {
+                               return $parent[0];
+                       }
+               }
+               $parent = $parent.parent();
+       }
+       return this.getDocument( el ).body;
+};
+
+/**
+ * Scroll element into view
+ *
+ * @static
+ * @param {HTMLElement} el Element to scroll into view
+ * @param {Object} [config={}] Configuration config
+ * @param {string} [config.duration] jQuery animation duration value
+ * @param {string} [config.direction] Scroll in only one direction, e.g. 'x' or 'y', omit
+ *  to scroll in both directions
+ * @param {Function} [config.complete] Function to call when scrolling completes
+ */
+OO.ui.Element.scrollIntoView = function ( el, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       var anim = {},
+               callback = typeof config.complete === 'function' && config.complete,
+               sc = this.getClosestScrollableContainer( el, config.direction ),
+               $sc = $( sc ),
+               eld = this.getDimensions( el ),
+               scd = this.getDimensions( sc ),
+               rel = {
+                       'top': eld.rect.top - ( scd.rect.top + scd.borders.top ),
+                       'bottom': scd.rect.bottom - scd.borders.bottom - scd.scrollbar.bottom - eld.rect.bottom,
+                       'left': eld.rect.left - ( scd.rect.left + scd.borders.left ),
+                       'right': scd.rect.right - scd.borders.right - scd.scrollbar.right - eld.rect.right
+               };
+
+       if ( !config.direction || config.direction === 'y' ) {
+               if ( rel.top < 0 ) {
+                       anim.scrollTop = scd.scroll.top + rel.top;
+               } else if ( rel.top > 0 && rel.bottom < 0 ) {
+                       anim.scrollTop = scd.scroll.top + Math.min( rel.top, -rel.bottom );
+               }
+       }
+       if ( !config.direction || config.direction === 'x' ) {
+               if ( rel.left < 0 ) {
+                       anim.scrollLeft = scd.scroll.left + rel.left;
+               } else if ( rel.left > 0 && rel.right < 0 ) {
+                       anim.scrollLeft = scd.scroll.left + Math.min( rel.left, -rel.right );
+               }
+       }
+       if ( !$.isEmptyObject( anim ) ) {
+               $sc.stop( true ).animate( anim, config.duration || 'fast' );
+               if ( callback ) {
+                       $sc.queue( function ( next ) {
+                               callback();
+                               next();
+                       } );
+               }
+       } else {
+               if ( callback ) {
+                       callback();
+               }
+       }
+};
+
+/* Methods */
+
+/**
+ * Get the HTML tag name.
+ *
+ * Override this method to base the result on instance information.
+ *
+ * @returns {string} HTML tag name
+ */
+OO.ui.Element.prototype.getTagName = function () {
+       return this.constructor.static.tagName;
+};
+
+/**
+ * Get the DOM document.
+ *
+ * @returns {HTMLDocument} Document object
+ */
+OO.ui.Element.prototype.getElementDocument = function () {
+       return OO.ui.Element.getDocument( this.$element );
+};
+
+/**
+ * Get the DOM window.
+ *
+ * @returns {Window} Window object
+ */
+OO.ui.Element.prototype.getElementWindow = function () {
+       return OO.ui.Element.getWindow( this.$element );
+};
+
+/**
+ * Get closest scrollable container.
+ *
+ * @method
+ * @see #static-method-getClosestScrollableContainer
+ */
+OO.ui.Element.prototype.getClosestScrollableElementContainer = function () {
+       return OO.ui.Element.getClosestScrollableContainer( this.$element[0] );
+};
+
+/**
+ * Scroll element into view
+ *
+ * @method
+ * @see #static-method-scrollIntoView
+ * @param {Object} [config={}]
+ */
+OO.ui.Element.prototype.scrollElementIntoView = function ( config ) {
+       return OO.ui.Element.scrollIntoView( this.$element[0], config );
+};
+
+( function () {
+       // Static
+       var specialFocusin;
+
+       function handler( e ) {
+               jQuery.event.simulate( 'focusin', e.target, jQuery.event.fix( e ), /* bubble = */ true );
+       }
+
+       specialFocusin = {
+               setup: function () {
+                       var doc = this.ownerDocument || this,
+                               attaches = $.data( doc, 'ooui-focusin-attaches' );
+                       if ( !attaches ) {
+                               doc.addEventListener( 'focus', handler, true );
+                       }
+                       $.data( doc, 'ooui-focusin-attaches', ( attaches || 0 ) + 1 );
+               },
+               teardown: function () {
+                       var doc = this.ownerDocument || this,
+                               attaches = $.data( doc, 'ooui-focusin-attaches' ) - 1;
+                       if ( !attaches ) {
+                               doc.removeEventListener( 'focus', handler, true );
+                               $.removeData( doc, 'ooui-focusin-attaches' );
+                       } else {
+                               $.data( doc, 'ooui-focusin-attaches', attaches );
+                       }
+               }
+       };
+
+       /**
+        * Bind a handler for an event on the DOM element.
+        *
+        * Uses jQuery internally for everything except for events which are
+        * known to have issues in the browser or in jQuery. This method
+        * should become obsolete eventually.
+        *
+        * @param {string} event
+        * @param {Function} callback
+        */
+       OO.ui.Element.prototype.onDOMEvent = function ( event, callback ) {
+               var orig;
+
+               if ( event === 'focusin' ) {
+                       // jQuery 1.8.3 has a bug with handling focusin events inside iframes.
+                       // Firefox doesn't support focusin at all, so we listen for 'focus' on the
+                       // document, and simulate a 'focusin' event on the target element and make
+                       // it bubble from there.
+                       //
+                       // - http://jsfiddle.net/sw3hr/
+                       // - http://bugs.jquery.com/ticket/14180
+                       // - https://github.com/jquery/jquery/commit/1cecf64e5aa4153
+
+                       // Replace jQuery's override with our own
+                       orig = $.event.special.focusin;
+                       $.event.special.focusin = specialFocusin;
+
+                       this.$element.on( event, callback );
+
+                       // Restore
+                       $.event.special.focusin = orig;
+
+               } else {
+                       this.$element.on( event, callback );
+               }
+       };
+
+       /**
+        * @param {string} event
+        * @param {Function} callback
+        */
+       OO.ui.Element.prototype.offDOMEvent = function ( event, callback ) {
+               var orig;
+               if ( event === 'focusin' ) {
+                       orig = $.event.special.focusin;
+                       $.event.special.focusin = specialFocusin;
+                       this.$element.off( event, callback );
+                       $.event.special.focusin = orig;
+               } else {
+                       this.$element.off( event, callback );
+               }
+       };
+}() );
+/**
+ * Embedded iframe with the same styles as its parent.
+ *
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.Frame = function OoUiFrame( config ) {
+       // Parent constructor
+       OO.ui.Element.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.initialized = false;
+       this.config = config;
+
+       // Initialize
+       this.$element
+               .addClass( 'oo-ui-frame' )
+               .attr( { 'frameborder': 0, 'scrolling': 'no' } );
+
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.Frame, OO.ui.Element );
+
+OO.mixinClass( OO.ui.Frame, OO.EventEmitter );
+
+/* Static Properties */
+
+OO.ui.Frame.static.tagName = 'iframe';
+
+/* Events */
+
+/**
+ * @event initialize
+ */
+
+/* Static Methods */
+
+/**
+ * Transplant the CSS styles from as parent document to a frame's document.
+ *
+ * This loops over the style sheets in the parent document, and copies their nodes to the
+ * frame's document. It then polls the document to see when all styles have loaded, and once they
+ * have, invokes the callback.
+ *
+ * If the styles still haven't loaded after a long time (5 seconds by default), we give up waiting
+ * and invoke the callback anyway. This protects against cases like a display: none; iframe in
+ * Firefox, where the styles won't load until the iframe becomes visible.
+ *
+ * For details of how we arrived at the strategy used in this function, see #load.
+ *
+ * @static
+ * @method
+ * @inheritable
+ * @param {HTMLDocument} parentDoc Document to transplant styles from
+ * @param {HTMLDocument} frameDoc Document to transplant styles to
+ * @param {Function} [callback] Callback to execute once styles have loaded
+ * @param {number} [timeout=5000] How long to wait before giving up (in ms). If 0, never give up.
+ */
+OO.ui.Frame.static.transplantStyles = function ( parentDoc, frameDoc, callback, timeout ) {
+       var i, numSheets, styleNode, newNode, timeoutID, pollNodeId, $pendingPollNodes,
+               $pollNodes = $( [] ),
+               // Fake font-family value
+               fontFamily = 'oo-ui-frame-transplantStyles-loaded';
+
+       for ( i = 0, numSheets = parentDoc.styleSheets.length; i < numSheets; i++ ) {
+               styleNode = parentDoc.styleSheets[i].ownerNode;
+               if ( callback && styleNode.nodeName.toLowerCase() === 'link' ) {
+                       // External stylesheet
+                       // Create a node with a unique ID that we're going to monitor to see when the CSS
+                       // has loaded
+                       pollNodeId = 'oo-ui-frame-transplantStyles-loaded-' + i;
+                       $pollNodes = $pollNodes.add( $( '<div>', frameDoc )
+                               .attr( 'id', pollNodeId )
+                               .appendTo( frameDoc.body )
+                       );
+
+                       // Add <style>@import url(...); #pollNodeId { font-family: ... }</style>
+                       // The font-family rule will only take effect once the @import finishes
+                       newNode = frameDoc.createElement( 'style' );
+                       newNode.textContent = '@import url(' + styleNode.href + ');\n' +
+                               '#' + pollNodeId + ' { font-family: ' + fontFamily + '; }';
+               } else {
+                       // Not an external stylesheet, or no polling required; just copy the node over
+                       newNode = frameDoc.importNode( styleNode, true );
+               }
+               frameDoc.head.appendChild( newNode );
+       }
+
+       if ( callback ) {
+               // Poll every 100ms until all external stylesheets have loaded
+               $pendingPollNodes = $pollNodes;
+               timeoutID = setTimeout( function pollExternalStylesheets() {
+                       while (
+                               $pendingPollNodes.length > 0 &&
+                               $pendingPollNodes.eq( 0 ).css( 'font-family' ) === fontFamily
+                       ) {
+                               $pendingPollNodes = $pendingPollNodes.slice( 1 );
+                       }
+
+                       if ( $pendingPollNodes.length === 0 ) {
+                               // We're done!
+                               if ( timeoutID !== null ) {
+                                       timeoutID = null;
+                                       $pollNodes.remove();
+                                       callback();
+                               }
+                       } else {
+                               timeoutID = setTimeout( pollExternalStylesheets, 100 );
+                       }
+               }, 100 );
+               // ...but give up after a while
+               if ( timeout !== 0 ) {
+                       setTimeout( function () {
+                               if ( timeoutID ) {
+                                       clearTimeout( timeoutID );
+                                       timeoutID = null;
+                                       $pollNodes.remove();
+                                       callback();
+                               }
+                       }, timeout || 5000 );
+               }
+       }
+};
+
+/* Methods */
+
+/**
+ * Load the frame contents.
+ *
+ * Once the iframe's stylesheets are loaded, the `initialize` event will be emitted.
+ *
+ * Sounds simple right? Read on...
+ *
+ * When you create a dynamic iframe using open/write/close, the window.load event for the
+ * iframe is triggered when you call close, and there's no further load event to indicate that
+ * everything is actually loaded.
+ *
+ * In Chrome, stylesheets don't show up in document.styleSheets until they have loaded, so we could
+ * just poll that array and wait for it to have the right length. However, in Firefox, stylesheets
+ * are added to document.styleSheets immediately, and the only way you can determine whether they've
+ * loaded is to attempt to access .cssRules and wait for that to stop throwing an exception. But
+ * cross-domain stylesheets never allow .cssRules to be accessed even after they have loaded.
+ *
+ * The workaround is to change all `<link href="...">` tags to `<style>@import url(...)</style>` tags.
+ * Because `@import` is blocking, Chrome won't add the stylesheet to document.styleSheets until
+ * the `@import` has finished, and Firefox won't allow .cssRules to be accessed until the `@import`
+ * has finished. And because the contents of the `<style>` tag are from the same origin, accessing
+ * .cssRules is allowed.
+ *
+ * However, now that we control the styles we're injecting, we might as well do away with
+ * browser-specific polling hacks like document.styleSheets and .cssRules, and instead inject
+ * `<style>@import url(...); #foo { font-family: someValue; }</style>`, then create `<div id="foo">`
+ * and wait for its font-family to change to someValue. Because `@import` is blocking, the font-family
+ * rule is not applied until after the `@import` finishes.
+ *
+ * All this stylesheet injection and polling magic is in #transplantStyles.
+ *
+ * @fires initialize
+ */
+OO.ui.Frame.prototype.load = function () {
+       var win = this.$element.prop( 'contentWindow' ),
+               doc = win.document,
+               frame = this;
+
+       // Figure out directionality:
+       this.dir = this.$element.closest( '[dir]' ).prop( 'dir' ) || 'ltr';
+
+       // Initialize contents
+       doc.open();
+       doc.write(
+               '<!doctype html>' +
+               '<html>' +
+                       '<body class="oo-ui-frame-body oo-ui-' + this.dir + '" style="direction:' + this.dir + ';" dir="' + this.dir + '">' +
+                               '<div class="oo-ui-frame-content"></div>' +
+                       '</body>' +
+               '</html>'
+       );
+       doc.close();
+
+       // Properties
+       this.$ = OO.ui.Element.getJQuery( doc, this );
+       this.$content = this.$( '.oo-ui-frame-content' );
+       this.$document = this.$( doc );
+
+       this.constructor.static.transplantStyles( this.getElementDocument(), this.$document[0],
+               function () {
+                       frame.initialized = true;
+                       frame.emit( 'initialize' );
+               }
+       );
+};
+
+/**
+ * Run a callback as soon as the frame has been initialized.
+ *
+ * @param {Function} callback
+ */
+OO.ui.Frame.prototype.run = function ( callback ) {
+       if ( this.initialized ) {
+               callback();
+       } else {
+               this.once( 'initialize', callback );
+       }
+};
+
+/**
+ * Sets the size of the frame.
+ *
+ * @method
+ * @param {number} width Frame width in pixels
+ * @param {number} height Frame height in pixels
+ * @chainable
+ */
+OO.ui.Frame.prototype.setSize = function ( width, height ) {
+       this.$element.css( { 'width': width, 'height': height } );
+       return this;
+};
+/**
+ * Container for elements in a child frame.
+ *
+ * There are two ways to specify a title: set the static `title` property or provide a `title`
+ * property in the configuration options. The latter will override the former.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {OO.ui.WindowSet} windowSet Window set this dialog is part of
+ * @param {Object} [config] Configuration options
+ * @cfg {string|Function} [title] Title string or function that returns a string
+ * @cfg {string} [icon] Symbolic name of icon
+ * @fires initialize
+ */
+OO.ui.Window = function OoUiWindow( windowSet, config ) {
+       // Parent constructor
+       OO.ui.Element.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.windowSet = windowSet;
+       this.visible = false;
+       this.opening = false;
+       this.closing = false;
+       this.title = OO.ui.resolveMsg( config.title || this.constructor.static.title );
+       this.icon = config.icon || this.constructor.static.icon;
+       this.frame = new OO.ui.Frame( { '$': this.$ } );
+       this.$frame = this.$( '<div>' );
+       this.$ = function () {
+               throw new Error( 'this.$() cannot be used until the frame has been initialized.' );
+       };
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-window' )
+               // Hide the window using visibility: hidden; while the iframe is still loading
+               // Can't use display: none; because that prevents the iframe from loading in Firefox
+               .css( 'visibility', 'hidden' )
+               .append( this.$frame );
+       this.$frame
+               .addClass( 'oo-ui-window-frame' )
+               .append( this.frame.$element );
+
+       // Events
+       this.frame.connect( this, { 'initialize': 'initialize' } );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.Window, OO.ui.Element );
+
+OO.mixinClass( OO.ui.Window, OO.EventEmitter );
+
+/* Events */
+
+/**
+ * Initialize contents.
+ *
+ * Fired asynchronously after construction when iframe is ready.
+ *
+ * @event initialize
+ */
+
+/**
+ * Open window.
+ *
+ * Fired after window has been opened.
+ *
+ * @event open
+ * @param {Object} data Window opening data
+ */
+
+/**
+ * Close window.
+ *
+ * Fired after window has been closed.
+ *
+ * @event close
+ * @param {Object} data Window closing data
+ */
+
+/* Static Properties */
+
+/**
+ * Symbolic name of icon.
+ *
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.Window.static.icon = 'window';
+
+/**
+ * Window title.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function} Title string or function that returns a string
+ */
+OO.ui.Window.static.title = null;
+
+/* Methods */
+
+/**
+ * Check if window is visible.
+ *
+ * @method
+ * @returns {boolean} Window is visible
+ */
+OO.ui.Window.prototype.isVisible = function () {
+       return this.visible;
+};
+
+/**
+ * Check if window is opening.
+ *
+ * @method
+ * @returns {boolean} Window is opening
+ */
+OO.ui.Window.prototype.isOpening = function () {
+       return this.opening;
+};
+
+/**
+ * Check if window is closing.
+ *
+ * @method
+ * @returns {boolean} Window is closing
+ */
+OO.ui.Window.prototype.isClosing = function () {
+       return this.closing;
+};
+
+/**
+ * Get the window frame.
+ *
+ * @method
+ * @returns {OO.ui.Frame} Frame of window
+ */
+OO.ui.Window.prototype.getFrame = function () {
+       return this.frame;
+};
+
+/**
+ * Get the window set.
+ *
+ * @method
+ * @returns {OO.ui.WindowSet} Window set
+ */
+OO.ui.Window.prototype.getWindowSet = function () {
+       return this.windowSet;
+};
+
+/**
+ * Get the window title.
+ *
+ * @returns {string} Title text
+ */
+OO.ui.Window.prototype.getTitle = function () {
+       return this.title;
+};
+
+/**
+ * Get the window icon.
+ *
+ * @returns {string} Symbolic name of icon
+ */
+OO.ui.Window.prototype.getIcon = function () {
+       return this.icon;
+};
+
+/**
+ * Set the size of window frame.
+ *
+ * @param {number} [width=auto] Custom width
+ * @param {number} [height=auto] Custom height
+ * @chainable
+ */
+OO.ui.Window.prototype.setSize = function ( width, height ) {
+       if ( !this.frame.$content ) {
+               return;
+       }
+
+       this.frame.$element.css( {
+               'width': width === undefined ? 'auto' : width,
+               'height': height === undefined ? 'auto' : height
+       } );
+
+       return this;
+};
+
+/**
+ * Set the title of the window.
+ *
+ * @param {string|Function} title Title text or a function that returns text
+ * @chainable
+ */
+OO.ui.Window.prototype.setTitle = function ( title ) {
+       this.title = OO.ui.resolveMsg( title );
+       if ( this.$title ) {
+               this.$title.text( title );
+       }
+       return this;
+};
+
+/**
+ * Set the icon of the window.
+ *
+ * @param {string} icon Symbolic name of icon
+ * @chainable
+ */
+OO.ui.Window.prototype.setIcon = function ( icon ) {
+       if ( this.$icon ) {
+               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
+       }
+       this.icon = icon;
+       if ( this.$icon ) {
+               this.$icon.addClass( 'oo-ui-icon-' + this.icon );
+       }
+
+       return this;
+};
+
+/**
+ * Set the position of window to fit with contents..
+ *
+ * @param {string} left Left offset
+ * @param {string} top Top offset
+ * @chainable
+ */
+OO.ui.Window.prototype.setPosition = function ( left, top ) {
+       this.$element.css( { 'left': left, 'top': top } );
+       return this;
+};
+
+/**
+ * Set the height of window to fit with contents.
+ *
+ * @param {number} [min=0] Min height
+ * @param {number} [max] Max height (defaults to content's outer height)
+ * @chainable
+ */
+OO.ui.Window.prototype.fitHeightToContents = function ( min, max ) {
+       var height = this.frame.$content.outerHeight();
+
+       this.frame.$element.css(
+               'height', Math.max( min || 0, max === undefined ? height : Math.min( max, height ) )
+       );
+
+       return this;
+};
+
+/**
+ * Set the width of window to fit with contents.
+ *
+ * @param {number} [min=0] Min height
+ * @param {number} [max] Max height (defaults to content's outer width)
+ * @chainable
+ */
+OO.ui.Window.prototype.fitWidthToContents = function ( min, max ) {
+       var width = this.frame.$content.outerWidth();
+
+       this.frame.$element.css(
+               'width', Math.max( min || 0, max === undefined ? width : Math.min( max, width ) )
+       );
+
+       return this;
+};
+
+/**
+ * Initialize window contents.
+ *
+ * The first time the window is opened, #initialize is called when it's safe to begin populating
+ * its contents. See #setup for a way to make changes each time the window opens.
+ *
+ * Once this method is called, this.$$ can be used to create elements within the frame.
+ *
+ * @method
+ * @fires initialize
+ * @chainable
+ */
+OO.ui.Window.prototype.initialize = function () {
+       // Properties
+       this.$ = this.frame.$;
+       this.$title = this.$( '<div class="oo-ui-window-title"></div>' )
+               .text( this.title );
+       this.$icon = this.$( '<div class="oo-ui-window-icon"></div>' )
+               .addClass( 'oo-ui-icon-' + this.icon );
+       this.$head = this.$( '<div class="oo-ui-window-head"></div>' );
+       this.$body = this.$( '<div class="oo-ui-window-body"></div>' );
+       this.$foot = this.$( '<div class="oo-ui-window-foot"></div>' );
+       this.$overlay = this.$( '<div class="oo-ui-window-overlay"></div>' );
+
+       // Initialization
+       this.frame.$content.append(
+               this.$head.append( this.$icon, this.$title ),
+               this.$body,
+               this.$foot,
+               this.$overlay
+       );
+
+       // Undo the visibility: hidden; hack from the constructor and apply display: none;
+       // We can do this safely now that the iframe has initialized
+       this.$element.hide().css( 'visibility', '' );
+
+       this.emit( 'initialize' );
+
+       return this;
+};
+
+/**
+ * Setup window for use.
+ *
+ * Each time the window is opened, once it's ready to be interacted with, this will set it up for
+ * use in a particular context, based on the `data` argument.
+ *
+ * When you override this method, you must call the parent method at the very beginning.
+ *
+ * @method
+ * @abstract
+ * @param {Object} [data] Window opening data
+ */
+OO.ui.Window.prototype.setup = function () {
+       // Override to do something
+};
+
+/**
+ * Tear down window after use.
+ *
+ * Each time the window is closed, and it's done being interacted with, this will tear it down and
+ * do something with the user's interactions within the window, based on the `data` argument.
+ *
+ * When you override this method, you must call the parent method at the very end.
+ *
+ * @method
+ * @abstract
+ * @param {Object} [data] Window closing data
+ */
+OO.ui.Window.prototype.teardown = function () {
+       // Override to do something
+};
+
+/**
+ * Open window.
+ *
+ * Do not override this method. See #setup for a way to make changes each time the window opens.
+ *
+ * @method
+ * @param {Object} [data] Window opening data
+ * @fires open
+ * @chainable
+ */
+OO.ui.Window.prototype.open = function ( data ) {
+       if ( !this.opening && !this.closing && !this.visible ) {
+               this.opening = true;
+               this.frame.run( OO.ui.bind( function () {
+                       this.$element.show();
+                       this.visible = true;
+                       this.frame.$element.focus();
+                       this.emit( 'opening', data );
+                       this.setup( data );
+                       this.emit( 'open', data );
+                       this.opening = false;
+               }, this ) );
+       }
+
+       return this;
+};
+
+/**
+ * Close window.
+ *
+ * See #teardown for a way to do something each time the window closes.
+ *
+ * @method
+ * @param {Object} [data] Window closing data
+ * @fires close
+ * @chainable
+ */
+OO.ui.Window.prototype.close = function ( data ) {
+       if ( !this.opening && !this.closing && this.visible ) {
+               this.frame.$content.find( ':focus' ).blur();
+               this.closing = true;
+               this.$element.hide();
+               this.visible = false;
+               this.emit( 'closing', data );
+               this.teardown( data );
+               this.emit( 'close', data );
+               this.closing = false;
+       }
+
+       return this;
+};
+/**
+ * Set of mutually exclusive windows.
+ *
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {OO.Factory} factory Window factory
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.WindowSet = function OoUiWindowSet( factory, config ) {
+       // Parent constructor
+       OO.ui.Element.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.factory = factory;
+       this.windows = {};
+       this.currentWindow = null;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-windowSet' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.WindowSet, OO.ui.Element );
+
+OO.mixinClass( OO.ui.WindowSet, OO.EventEmitter );
+
+/* Events */
+
+/**
+ * @event opening
+ * @param {OO.ui.Window} win Window that's being opened
+ * @param {Object} config Window opening information
+ */
+
+/**
+ * @event open
+ * @param {OO.ui.Window} win Window that's been opened
+ * @param {Object} config Window opening information
+ */
+
+/**
+ * @event closing
+ * @param {OO.ui.Window} win Window that's being closed
+ * @param {Object} config Window closing information
+ */
+
+/**
+ * @event close
+ * @param {OO.ui.Window} win Window that's been closed
+ * @param {Object} config Window closing information
+ */
+
+/* Methods */
+
+/**
+ * Handle a window that's being opened.
+ *
+ * @method
+ * @param {OO.ui.Window} win Window that's being opened
+ * @param {Object} [config] Window opening information
+ * @fires opening
+ */
+OO.ui.WindowSet.prototype.onWindowOpening = function ( win, config ) {
+       if ( this.currentWindow && this.currentWindow !== win ) {
+               this.currentWindow.close();
+       }
+       this.currentWindow = win;
+       this.emit( 'opening', win, config );
+};
+
+/**
+ * Handle a window that's been opened.
+ *
+ * @method
+ * @param {OO.ui.Window} win Window that's been opened
+ * @param {Object} [config] Window opening information
+ * @fires open
+ */
+OO.ui.WindowSet.prototype.onWindowOpen = function ( win, config ) {
+       this.emit( 'open', win, config );
+};
+
+/**
+ * Handle a window that's being closed.
+ *
+ * @method
+ * @param {OO.ui.Window} win Window that's being closed
+ * @param {Object} [config] Window closing information
+ * @fires closing
+ */
+OO.ui.WindowSet.prototype.onWindowClosing = function ( win, config ) {
+       this.currentWindow = null;
+       this.emit( 'closing', win, config );
+};
+
+/**
+ * Handle a window that's been closed.
+ *
+ * @method
+ * @param {OO.ui.Window} win Window that's been closed
+ * @param {Object} [config] Window closing information
+ * @fires close
+ */
+OO.ui.WindowSet.prototype.onWindowClose = function ( win, config ) {
+       this.emit( 'close', win, config );
+};
+
+/**
+ * Get the current window.
+ *
+ * @method
+ * @returns {OO.ui.Window} Current window
+ */
+OO.ui.WindowSet.prototype.getCurrentWindow = function () {
+       return this.currentWindow;
+};
+
+/**
+ * Return a given window.
+ *
+ * @param {string} name Symbolic name of window
+ * @return {OO.ui.Window} Window with specified name
+ */
+OO.ui.WindowSet.prototype.getWindow = function ( name ) {
+       var win;
+
+       if ( !this.factory.lookup( name ) ) {
+               throw new Error( 'Unknown window: ' + name );
+       }
+       if ( !( name in this.windows ) ) {
+               win = this.windows[name] = this.factory.create( name, this, { '$': this.$ } );
+               win.connect( this, {
+                       'opening': [ 'onWindowOpening', win ],
+                       'open': [ 'onWindowOpen', win ],
+                       'closing': [ 'onWindowClosing', win ],
+                       'close': [ 'onWindowClose', win ]
+               } );
+               this.$element.append( win.$element );
+               win.getFrame().load();
+       }
+       return this.windows[name];
+};
+/**
+ * Modal dialog box.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Window
+ *
+ * @constructor
+ * @param {OO.ui.WindowSet} windowSet Window set this dialog is part of
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [footless] Hide foot
+ * @cfg {boolean} [small] Make the dialog small
+ */
+OO.ui.Dialog = function OoUiDialog( windowSet, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Window.call( this, windowSet, config );
+
+       // Properties
+       this.visible = false;
+       this.footless = !!config.footless;
+       this.small = !!config.small;
+       this.onWindowMouseWheelHandler = OO.ui.bind( this.onWindowMouseWheel, this );
+       this.onDocumentKeyDownHandler = OO.ui.bind( this.onDocumentKeyDown, this );
+
+       // Events
+       this.$element.on( 'mousedown', false );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-dialog' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.Dialog, OO.ui.Window );
+
+/* Static Properties */
+
+/**
+ * Symbolic name of dialog.
+ *
+ * @abstract
+ * @static
+ * @property {string}
+ * @inheritable
+ */
+OO.ui.Dialog.static.name = '';
+
+/* Methods */
+
+/**
+ * Handle close button click events.
+ *
+ * @method
+ */
+OO.ui.Dialog.prototype.onCloseButtonClick = function () {
+       this.close( { 'action': 'cancel' } );
+};
+
+/**
+ * Handle window mouse wheel events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse wheel event
+ */
+OO.ui.Dialog.prototype.onWindowMouseWheel = function () {
+       return false;
+};
+
+/**
+ * Handle document key down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.Dialog.prototype.onDocumentKeyDown = function ( e ) {
+       switch ( e.which ) {
+               case OO.ui.Keys.PAGEUP:
+               case OO.ui.Keys.PAGEDOWN:
+               case OO.ui.Keys.END:
+               case OO.ui.Keys.HOME:
+               case OO.ui.Keys.LEFT:
+               case OO.ui.Keys.UP:
+               case OO.ui.Keys.RIGHT:
+               case OO.ui.Keys.DOWN:
+                       // Prevent any key events that might cause scrolling
+                       return false;
+       }
+};
+
+/**
+ * Handle frame document key down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.Dialog.prototype.onFrameDocumentKeyDown = function ( e ) {
+       if ( e.which === OO.ui.Keys.ESCAPE ) {
+               this.close( { 'action': 'cancel' } );
+               return false;
+       }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.Dialog.prototype.initialize = function () {
+       // Parent method
+       OO.ui.Window.prototype.initialize.call( this );
+
+       // Properties
+       this.closeButton = new OO.ui.ButtonWidget( {
+               '$': this.$,
+               'frameless': true,
+               'icon': 'close',
+               'title': OO.ui.msg( 'ooui-dialog-action-close' )
+       } );
+
+       // Events
+       this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
+       this.frame.$document.on( 'keydown', OO.ui.bind( this.onFrameDocumentKeyDown, this ) );
+
+       // Initialization
+       this.frame.$content.addClass( 'oo-ui-dialog-content' );
+       if ( this.footless ) {
+               this.frame.$content.addClass( 'oo-ui-dialog-content-footless' );
+       }
+       if ( this.small ) {
+               this.$frame.addClass( 'oo-ui-window-frame-small' );
+       }
+       this.closeButton.$element.addClass( 'oo-ui-window-closeButton' );
+       this.$head.append( this.closeButton.$element );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.Dialog.prototype.setup = function ( data ) {
+       // Parent method
+       OO.ui.Window.prototype.setup.call( this, data );
+
+       // Prevent scrolling in top-level window
+       this.$( window ).on( 'mousewheel', this.onWindowMouseWheelHandler );
+       this.$( document ).on( 'keydown', this.onDocumentKeyDownHandler );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.Dialog.prototype.teardown = function ( data ) {
+       // Parent method
+       OO.ui.Window.prototype.teardown.call( this, data );
+
+       // Allow scrolling in top-level window
+       this.$( window ).off( 'mousewheel', this.onWindowMouseWheelHandler );
+       this.$( document ).off( 'keydown', this.onDocumentKeyDownHandler );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.Dialog.prototype.close = function ( data ) {
+       if ( !this.opening && !this.closing && this.visible ) {
+               // Trigger transition
+               this.$element.addClass( 'oo-ui-dialog-closing' );
+               // Allow transition to complete before actually closing
+               setTimeout( OO.ui.bind( function () {
+                       this.$element.removeClass( 'oo-ui-dialog-closing' );
+                       // Parent method
+                       OO.ui.Window.prototype.close.call( this, data );
+               }, this ), 250 );
+       }
+};
+/**
+ * Container for elements.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Element
+ * @mixin OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.Layout = function OoUiLayout( config ) {
+       // Initialize config
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Element.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-layout' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.Layout, OO.ui.Element );
+
+OO.mixinClass( OO.ui.Layout, OO.EventEmitter );
+/**
+ * User interface control.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Element
+ * @mixin OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [disabled=false] Disable
+ */
+OO.ui.Widget = function OoUiWidget( config ) {
+       // Initialize config
+       config = $.extend( { 'disabled': false }, config );
+
+       // Parent constructor
+       OO.ui.Element.call( this, config );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+
+       // Properties
+       this.disabled = config.disabled;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-widget' );
+       this.setDisabled( this.disabled );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.Widget, OO.ui.Element );
+
+OO.mixinClass( OO.ui.Widget, OO.EventEmitter );
+
+/* Methods */
+
+/**
+ * Check if the widget is disabled.
+ *
+ * @method
+ * @param {boolean} Button is disabled
+ */
+OO.ui.Widget.prototype.isDisabled = function () {
+       return this.disabled;
+};
+
+/**
+ * Set the disabled state of the widget.
+ *
+ * This should probably change the widgets's appearance and prevent it from being used.
+ *
+ * @method
+ * @param {boolean} disabled Disable button
+ * @chainable
+ */
+OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
+       this.disabled = !!disabled;
+       if ( this.disabled ) {
+               this.$element.addClass( 'oo-ui-widget-disabled' );
+       } else {
+               this.$element.removeClass( 'oo-ui-widget-disabled' );
+       }
+       return this;
+};
+/**
+ * Element with a button.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $button Button node, assigned to #$button
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [frameless] Render button without a frame
+ * @cfg {number} [tabIndex] Button's tab index
+ */
+OO.ui.ButtonedElement = function OoUiButtonedElement( $button, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Properties
+       this.$button = $button;
+       this.tabIndex = null;
+       this.active = false;
+       this.onMouseUpHandler = OO.ui.bind( this.onMouseUp, this );
+
+       // Events
+       this.$button.on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-buttonedElement' );
+       this.$button
+               .addClass( 'oo-ui-buttonedElement-button' )
+               .attr( 'role', 'button' )
+               .prop( 'tabIndex', config.tabIndex || 0 );
+       if ( config.frameless ) {
+               this.$element.addClass( 'oo-ui-buttonedElement-frameless' );
+       } else {
+               this.$element.addClass( 'oo-ui-buttonedElement-framed' );
+       }
+};
+
+/* Methods */
+
+/**
+ * Handles mouse down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.ButtonedElement.prototype.onMouseDown = function () {
+       this.tabIndex = this.$button.attr( 'tabIndex' );
+       // Remove the tab-index while the button is down to prevent the button from stealing focus
+       this.$button.removeAttr( 'tabIndex' );
+       this.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true );
+};
+
+/**
+ * Handles mouse up events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse up event
+ */
+OO.ui.ButtonedElement.prototype.onMouseUp = function () {
+       // Restore the tab-index after the button is up to restore the button's accesssibility
+       this.$button.attr( 'tabIndex', this.tabIndex );
+       this.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true );
+};
+
+/**
+ * Set active state.
+ *
+ * @method
+ * @param {boolean} [value] Make button active
+ * @chainable
+ */
+OO.ui.ButtonedElement.prototype.setActive = function ( value ) {
+       this.$element.toggleClass( 'oo-ui-buttonedElement-active', !!value );
+       return this;
+};
+/**
+ * Element that can be automatically clipped to visible boundaies.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $clippable Nodes to clip, assigned to #$clippable
+ */
+OO.ui.ClippableElement = function OoUiClippableElement( $clippable ) {
+       // Properties
+       this.$clippable = $clippable;
+       this.clipping = false;
+       this.clipped = false;
+       this.$clippableContainer = null;
+       this.$clippableScroller = null;
+       this.$clippableWindow = null;
+       this.idealWidth = null;
+       this.idealHeight = null;
+       this.onClippableContainerScrollHandler = OO.ui.bind( this.clip, this );
+       this.onClippableWindowResizeHandler = OO.ui.bind( this.clip, this );
+
+       // Initialization
+       this.$clippable.addClass( 'oo-ui-clippableElement-clippable' );
+};
+
+/* Methods */
+
+/**
+ * Set clipping.
+ *
+ * @method
+ * @param {boolean} value Enable clipping
+ * @chainable
+ */
+OO.ui.ClippableElement.prototype.setClipping = function ( value ) {
+       value = !!value;
+
+       if ( this.clipping !== value ) {
+               this.clipping = value;
+               if ( this.clipping ) {
+                       this.$clippableContainer = this.$( this.getClosestScrollableElementContainer() );
+                       // If the clippable container is the body, we have to listen to scroll events and check
+                       // jQuery.scrollTop on the window because of browser inconsistencies
+                       this.$clippableScroller = this.$clippableContainer.is( 'body' ) ?
+                               this.$( OO.ui.Element.getWindow( this.$clippableContainer ) ) :
+                               this.$clippableContainer;
+                       this.$clippableScroller.on( 'scroll', this.onClippableContainerScrollHandler );
+                       this.$clippableWindow = this.$( this.getElementWindow() )
+                               .on( 'resize', this.onClippableWindowResizeHandler );
+                       // Initial clip after visible
+                       setTimeout( OO.ui.bind( this.clip, this ) );
+               } else {
+                       this.$clippableContainer = null;
+                       this.$clippableScroller.off( 'scroll', this.onClippableContainerScrollHandler );
+                       this.$clippableScroller = null;
+                       this.$clippableWindow.off( 'resize', this.onClippableWindowResizeHandler );
+                       this.$clippableWindow = null;
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Check if the element will be clipped to fit the visible area of the nearest scrollable container.
+ *
+ * @method
+ * @return {boolean} Element will be clipped to the visible area
+ */
+OO.ui.ClippableElement.prototype.isClipping = function () {
+       return this.clipping;
+};
+
+/**
+ * Check if the bottom or right of the element is being clipped by the nearest scrollable container.
+ *
+ * @method
+ * @return {boolean} Part of the element is being clipped
+ */
+OO.ui.ClippableElement.prototype.isClipped = function () {
+       return this.clipped;
+};
+
+/**
+ * Set the ideal size.
+ *
+ * @method
+ * @param {number|string} [width] Width as a number of pixels or CSS string with unit suffix
+ * @param {number|string} [height] Height as a number of pixels or CSS string with unit suffix
+ */
+OO.ui.ClippableElement.prototype.setIdealSize = function ( width, height ) {
+       this.idealWidth = width;
+       this.idealHeight = height;
+};
+
+/**
+ * Clip element to visible boundaries and allow scrolling when needed.
+ *
+ * Element will be clipped the bottom or right of the element is within 10px of the edge of, or
+ * overlapped by, the visible area of the nearest scrollable container.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.ClippableElement.prototype.clip = function () {
+       if ( !this.clipping ) {
+               // this.$clippableContainer and this.$clippableWindow are null, so the below will fail
+               return this;
+       }
+
+       var buffer = 10,
+               cOffset = this.$clippable.offset(),
+               ccOffset = this.$clippableContainer.offset() || { 'top': 0, 'left': 0 },
+               ccHeight = this.$clippableContainer.innerHeight() - buffer,
+               ccWidth = this.$clippableContainer.innerWidth() - buffer,
+               scrollTop = this.$clippableScroller.scrollTop(),
+               scrollLeft = this.$clippableScroller.scrollLeft(),
+               desiredWidth = ( ccOffset.left + scrollLeft + ccWidth ) - cOffset.left,
+               desiredHeight = ( ccOffset.top + scrollTop + ccHeight ) - cOffset.top,
+               naturalWidth = this.$clippable.prop( 'scrollWidth' ),
+               naturalHeight = this.$clippable.prop( 'scrollHeight' ),
+               clipWidth = desiredWidth < naturalWidth,
+               clipHeight = desiredHeight < naturalHeight;
+
+       if ( clipWidth ) {
+               this.$clippable.css( { 'overflow-x': 'auto', 'width': desiredWidth } );
+       } else {
+               this.$clippable.css( { 'overflow-x': '', 'width': this.idealWidth || '' } );
+       }
+       if ( clipHeight ) {
+               this.$clippable.css( { 'overflow-y': 'auto', 'height': desiredHeight } );
+       } else {
+               this.$clippable.css( { 'overflow-y': '', 'height': this.idealHeight || '' } );
+       }
+
+       this.clipped = clipWidth || clipHeight;
+
+       return this;
+};
+/**
+ * Element with named flags, used for styling, that can be added, removed and listed and checked.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string[]} [flags=[]] Styling flags, e.g. 'primary', 'destructive' or 'constructive'
+ */
+OO.ui.FlaggableElement = function OoUiFlaggableElement( config ) {
+       // Config initialization
+       config = config || {};
+
+       // Properties
+       this.flags = {};
+
+       // Initialization
+       this.setFlags( config.flags );
+};
+
+/* Methods */
+
+/**
+ * Check if a flag is set.
+ *
+ * @method
+ * @param {string} flag Flag name to check
+ * @returns {boolean} Has flag
+ */
+OO.ui.FlaggableElement.prototype.hasFlag = function ( flag ) {
+       return flag in this.flags;
+};
+
+/**
+ * Get the names of all flags.
+ *
+ * @method
+ * @returns {string[]} flags Flag names
+ */
+OO.ui.FlaggableElement.prototype.getFlags = function () {
+       return Object.keys( this.flags );
+};
+
+/**
+ * Add one or more flags.
+ *
+ * @method
+ * @param {string[]|Object.<string, boolean>} flags List of flags to add, or list of set/remove
+ *  values, keyed by flag name
+ * @chainable
+ */
+OO.ui.FlaggableElement.prototype.setFlags = function ( flags ) {
+       var i, len, flag,
+               classPrefix = 'oo-ui-flaggableElement-';
+
+       if ( Array.isArray( flags ) ) {
+               for ( i = 0, len = flags.length; i < len; i++ ) {
+                       flag = flags[i];
+                       // Set
+                       this.flags[flag] = true;
+                       this.$element.addClass( classPrefix + flag );
+               }
+       } else if ( OO.isPlainObject( flags ) ) {
+               for ( flag in flags ) {
+                       if ( flags[flags] ) {
+                               // Set
+                               this.flags[flag] = true;
+                               this.$element.addClass( classPrefix + flag );
+                       } else {
+                               // Remove
+                               delete this.flags[flag];
+                               this.$element.removeClass( classPrefix + flag );
+                       }
+               }
+       }
+       return this;
+};
+/**
+ * Element containing a sequence of child elements.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $group Container node, assigned to #$group
+ * @param {Object} [config] Configuration options
+ * @cfg {Object.<string,string>} [aggregations] Events to aggregate, keyed by item event name
+ */
+OO.ui.GroupElement = function OoUiGroupElement( $group, config ) {
+       // Configuration
+       config = config || {};
+
+       // Properties
+       this.$group = $group;
+       this.items = [];
+       this.$items = this.$( [] );
+       this.aggregate = !$.isEmptyObject( config.aggregations );
+       this.aggregations = config.aggregations || {};
+};
+
+/* Methods */
+
+/**
+ * Get items.
+ *
+ * @method
+ * @returns {OO.ui.Element[]} Items
+ */
+OO.ui.GroupElement.prototype.getItems = function () {
+       return this.items.slice( 0 );
+};
+
+/**
+ * Add items.
+ *
+ * @method
+ * @param {OO.ui.Element[]} items Item
+ * @param {number} [index] Index to insert items at
+ * @chainable
+ */
+OO.ui.GroupElement.prototype.addItems = function ( items, index ) {
+       var i, len, item, event, events, currentIndex,
+               $items = this.$( [] );
+
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+
+               // Check if item exists then remove it first, effectively "moving" it
+               currentIndex = this.items.indexOf( item );
+               if ( currentIndex >= 0 ) {
+                       this.removeItems( [ item ] );
+                       // Adjust index to compensate for removal
+                       if ( currentIndex < index ) {
+                               index--;
+                       }
+               }
+               // Add the item
+               if ( this.aggregate ) {
+                       events = {};
+                       for ( event in this.aggregations ) {
+                               events[event] = [ 'emit', this.aggregations[event], item ];
+                       }
+                       item.connect( this, events );
+               }
+               $items = $items.add( item.$element );
+       }
+
+       if ( index === undefined || index < 0 || index >= this.items.length ) {
+               this.$group.append( $items );
+               this.items.push.apply( this.items, items );
+       } else if ( index === 0 ) {
+               this.$group.prepend( $items );
+               this.items.unshift.apply( this.items, items );
+       } else {
+               this.$items.eq( index ).before( $items );
+               this.items.splice.apply( this.items, [ index, 0 ].concat( items ) );
+       }
+
+       this.$items = this.$items.add( $items );
+
+       return this;
+};
+
+/**
+ * Remove items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @param {OO.ui.Element[]} items Items to remove
+ * @chainable
+ */
+OO.ui.GroupElement.prototype.removeItems = function ( items ) {
+       var i, len, item, index;
+
+       // Remove specific items
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               index = this.items.indexOf( item );
+               if ( index !== -1 ) {
+                       if ( this.aggregate ) {
+                               item.disconnect( this );
+                       }
+                       this.items.splice( index, 1 );
+                       item.$element.detach();
+                       this.$items = this.$items.not( item.$element );
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Clear all items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.GroupElement.prototype.clearItems = function () {
+       var i, len, item;
+
+       // Remove all items
+       if ( this.aggregate ) {
+               for ( i = 0, len = this.items.length; i < len; i++ ) {
+                       item.disconnect( this );
+               }
+       }
+       this.items = [];
+       this.$items.detach();
+       this.$items = this.$( [] );
+};
+/**
+ * Element containing an icon.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $icon Icon node, assigned to #$icon
+ * @param {Object} [config] Configuration options
+ * @cfg {Object|string} [icon=''] Symbolic icon name, or map of icon names keyed by language ID;
+ *  use the 'default' key to specify the icon to be used when there is no icon in the user's
+ *  language
+ */
+OO.ui.IconedElement = function OoUiIconedElement( $icon, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.$icon = $icon;
+       this.icon = null;
+
+       // Initialization
+       this.$icon.addClass( 'oo-ui-iconedElement-icon' );
+       this.setIcon( config.icon || this.constructor.static.icon );
+};
+
+/* Static Properties */
+
+OO.ui.IconedElement.static = {};
+
+/**
+ * Icon.
+ *
+ * Value should be the unique portion of an icon CSS class name, such as 'up' for 'oo-ui-icon-up'.
+ *
+ * For i18n purposes, this property can be an object containing a `default` icon name property and
+ * additional icon names keyed by language code.
+ *
+ * Example of i18n icon definition:
+ *     { 'default': 'bold-a', 'en': 'bold-b', 'de': 'bold-f' }
+ *
+ * @static
+ * @inheritable
+ * @property {Object|string} Symbolic icon name, or map of icon names keyed by language ID;
+ *  use the 'default' key to specify the icon to be used when there is no icon in the user's
+ *  language
+ */
+OO.ui.IconedElement.static.icon = null;
+
+/* Methods */
+
+/**
+ * Set icon.
+ *
+ * @method
+ * @param {Object|string} icon Symbolic icon name, or map of icon names keyed by language ID;
+ *  use the 'default' key to specify the icon to be used when there is no icon in the user's
+ *  language
+ * @chainable
+ */
+OO.ui.IconedElement.prototype.setIcon = function ( icon ) {
+       icon = OO.isPlainObject( icon ) ? OO.ui.getLocalValue( icon, null, 'default' ) : icon;
+
+       if ( this.icon ) {
+               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
+       }
+       if ( typeof icon === 'string' ) {
+               icon = icon.trim();
+               if ( icon.length ) {
+                       this.$icon.addClass( 'oo-ui-icon-' + icon );
+                       this.icon = icon;
+               }
+       }
+       this.$element.toggleClass( 'oo-ui-iconedElement', !!this.icon );
+
+       return this;
+};
+
+/**
+ * Get icon.
+ *
+ * @method
+ * @returns {string} Icon
+ */
+OO.ui.IconedElement.prototype.getIcon = function () {
+       return this.icon;
+};
+/**
+ * Element containing an indicator.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $indicator Indicator node, assigned to #$indicator
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [indicator] Symbolic indicator name
+ * @cfg {string} [indicatorTitle] Indicator title text or a function that return text
+ */
+OO.ui.IndicatedElement = function OoUiIndicatedElement( $indicator, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.$indicator = $indicator;
+       this.indicator = null;
+       this.indicatorLabel = null;
+
+       // Initialization
+       this.$indicator.addClass( 'oo-ui-indicatedElement-indicator' );
+       this.setIndicator( config.indicator || this.constructor.static.indicator );
+       this.setIndicatorTitle( config.indicatorTitle  || this.constructor.static.indicatorTitle );
+};
+
+/* Static Properties */
+
+OO.ui.IndicatedElement.static = {};
+
+/**
+ * indicator.
+ *
+ * @static
+ * @inheritable
+ * @property {string|null} Symbolic indicator name or null for no indicator
+ */
+OO.ui.IndicatedElement.static.indicator = null;
+
+/**
+ * Indicator title.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null} Indicator title text, a function that return text or null for no
+ *  indicator title
+ */
+OO.ui.IndicatedElement.static.indicatorTitle = null;
+
+/* Methods */
+
+/**
+ * Set indicator.
+ *
+ * @method
+ * @param {string|null} indicator Symbolic name of indicator to use or null for no indicator
+ * @chainable
+ */
+OO.ui.IndicatedElement.prototype.setIndicator = function ( indicator ) {
+       if ( this.indicator ) {
+               this.$indicator.removeClass( 'oo-ui-indicator-' + this.indicator );
+               this.indicator = null;
+       }
+       if ( typeof indicator === 'string' ) {
+               indicator = indicator.trim();
+               if ( indicator.length ) {
+                       this.$indicator.addClass( 'oo-ui-indicator-' + indicator );
+                       this.indicator = indicator;
+               }
+       }
+       this.$element.toggleClass( 'oo-ui-indicatedElement', !!this.indicator );
+
+       return this;
+};
+
+/**
+ * Set indicator label.
+ *
+ * @method
+ * @param {string|Function|null} indicator Indicator title text, a function that return text or null
+ *  for no indicator title
+ * @chainable
+ */
+OO.ui.IndicatedElement.prototype.setIndicatorTitle = function ( indicatorTitle ) {
+       this.indicatorTitle = indicatorTitle = OO.ui.resolveMsg( indicatorTitle );
+
+       if ( typeof indicatorTitle === 'string' && indicatorTitle.length ) {
+               this.$indicator.attr( 'title', indicatorTitle );
+       } else {
+               this.$indicator.removeAttr( 'title' );
+       }
+
+       return this;
+};
+
+/**
+ * Get indicator.
+ *
+ * @method
+ * @returns {string} title Symbolic name of indicator
+ */
+OO.ui.IndicatedElement.prototype.getIndicator = function () {
+       return this.indicator;
+};
+
+/**
+ * Get indicator title.
+ *
+ * @method
+ * @returns {string} Indicator title text
+ */
+OO.ui.IndicatedElement.prototype.getIndicatorTitle = function () {
+       return this.indicatorTitle;
+};
+/**
+ * Element containing a label.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $label Label node, assigned to #$label
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery|string|Function} [label] Label nodes, text or a function that returns nodes or text
+ */
+OO.ui.LabeledElement = function OoUiLabeledElement( $label, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.$label = $label;
+       this.label = null;
+
+       // Initialization
+       this.$label.addClass( 'oo-ui-labeledElement-label' );
+       this.setLabel( config.label || this.constructor.static.label );
+};
+
+/* Static Properties */
+
+OO.ui.LabeledElement.static = {};
+
+/**
+ * Label.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null} Label text; a function that returns a nodes or text; or null for
+ *  no label
+ */
+OO.ui.LabeledElement.static.label = null;
+
+/* Methods */
+
+/**
+ * Set the label.
+ *
+ * @method
+ * @param {jQuery|string|Function|null} label Label nodes; text; a function that retuns nodes or
+ *  text; or null for no label
+ * @chainable
+ */
+OO.ui.LabeledElement.prototype.setLabel = function ( label ) {
+       var empty = false;
+
+       this.label = label = OO.ui.resolveMsg( label ) || null;
+       if ( typeof label === 'string' && label.trim() ) {
+               this.$label.text( label );
+       } else if ( label instanceof jQuery ) {
+               this.$label.empty().append( label );
+       } else {
+               this.$label.empty();
+               empty = true;
+       }
+       this.$element.toggleClass( 'oo-ui-labeledElement', !empty );
+       this.$label.css( 'display', empty ? 'none' : '' );
+
+       return this;
+};
+
+/**
+ * Get the label.
+ *
+ * @method
+ * @returns {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
+ *  text; or null for no label
+ */
+OO.ui.LabeledElement.prototype.getLabel = function () {
+       return this.label;
+};
+
+/**
+ * Fit the label.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.LabeledElement.prototype.fitLabel = function () {
+       if ( this.$label.autoEllipsis ) {
+               this.$label.autoEllipsis( { 'hasSpan': false, 'tooltip': true } );
+       }
+       return this;
+};
+/**
+ * Popuppable element.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [popupWidth=320] Width of popup
+ * @cfg {number} [popupHeight] Height of popup
+ * @cfg {Object} [popup] Configuration to pass to popup
+ */
+OO.ui.PopuppableElement = function OoUiPopuppableElement( config ) {
+       // Configuration initialization
+       config = $.extend( { 'popupWidth': 320 }, config );
+
+       // Properties
+       this.popup = new OO.ui.PopupWidget( $.extend(
+               { 'align': 'center', 'autoClose': true },
+               config.popup,
+               { '$': this.$, '$autoCloseIgnore': this.$element }
+       ) );
+       this.popupWidth = config.popupWidth;
+       this.popupHeight = config.popupHeight;
+};
+
+/* Methods */
+
+/**
+ * Get popup.
+ *
+ * @method
+ * @returns {OO.ui.PopupWidget} Popup widget
+ */
+OO.ui.PopuppableElement.prototype.getPopup = function () {
+       return this.popup;
+};
+
+/**
+ * Show popup.
+ *
+ * @method
+ */
+OO.ui.PopuppableElement.prototype.showPopup = function () {
+       this.popup.show().display( this.popupWidth, this.popupHeight );
+};
+
+/**
+ * Hide popup.
+ *
+ * @method
+ */
+OO.ui.PopuppableElement.prototype.hidePopup = function () {
+       this.popup.hide();
+};
+/**
+ * Element with a title.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {jQuery} $label Titled node, assigned to #$titled
+ * @param {Object} [config] Configuration options
+ * @cfg {string|Function} [title] Title text or a function that returns text
+ */
+OO.ui.TitledElement = function OoUiTitledElement( $titled, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.$titled = $titled;
+       this.title = null;
+
+       // Initialization
+       this.setTitle( config.title || this.constructor.static.title );
+};
+
+/* Static Properties */
+
+OO.ui.TitledElement.static = {};
+
+/**
+ * Title.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function} Title text or a function that returns text
+ */
+OO.ui.TitledElement.static.title = null;
+
+/* Methods */
+
+/**
+ * Set title.
+ *
+ * @method
+ * @param {string|Function|null} title Title text, a function that returns text or null for no title
+ * @chainable
+ */
+OO.ui.TitledElement.prototype.setTitle = function ( title ) {
+       this.title = title = OO.ui.resolveMsg( title ) || null;
+
+       if ( typeof title === 'string' && title.length ) {
+               this.$titled.attr( 'title', title );
+       } else {
+               this.$titled.removeAttr( 'title' );
+       }
+
+       return this;
+};
+
+/**
+ * Get title.
+ *
+ * @method
+ * @returns {string} Title string
+ */
+OO.ui.TitledElement.prototype.getTitle = function () {
+       return this.title;
+};
+/**
+ * Generic toolbar tool.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.IconedElement
+ *
+ * @constructor
+ * @param {OO.ui.ToolGroup} toolGroup
+ * @param {Object} [config] Configuration options
+ * @cfg {string|Function} [title] Title text or a function that returns text
+ */
+OO.ui.Tool = function OoUiTool( toolGroup, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
+
+       // Properties
+       this.toolGroup = toolGroup;
+       this.toolbar = this.toolGroup.getToolbar();
+       this.active = false;
+       this.$title = this.$( '<span>' );
+       this.$link = this.$( '<a>' );
+       this.title = null;
+
+       // Events
+       this.toolbar.connect( this, { 'updateState': 'onUpdateState' } );
+
+       // Initialization
+       this.$title.addClass( 'oo-ui-tool-title' );
+       this.$link
+               .addClass( 'oo-ui-tool-link' )
+               .append( this.$icon, this.$title );
+       this.$element
+               .data( 'oo-ui-tool', this )
+               .addClass(
+                       'oo-ui-tool ' + 'oo-ui-tool-name-' +
+                       this.constructor.static.name.replace( /^([^\/]+)\/([^\/]+).*$/, '$1-$2' )
+               )
+               .append( this.$link );
+       this.setTitle( config.title || this.constructor.static.title );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.Tool, OO.ui.Widget );
+
+OO.mixinClass( OO.ui.Tool, OO.ui.IconedElement );
+
+/* Events */
+
+/**
+ * @event select
+ */
+
+/* Static Properties */
+
+OO.ui.Tool.static.tagName = 'span';
+
+/**
+ * Symbolic name of tool.
+ *
+ * @abstract
+ * @static
+ * @property {string}
+ * @inheritable
+ */
+OO.ui.Tool.static.name = '';
+
+/**
+ * Tool group.
+ *
+ * @abstract
+ * @static
+ * @property {string}
+ * @inheritable
+ */
+OO.ui.Tool.static.group = '';
+
+/**
+ * Tool title.
+ *
+ * Title is used as a tooltip when the tool is part of a bar tool group, or a label when the tool
+ * is part of a list or menu tool group. If a trigger is associated with an action by the same name
+ * as the tool, a description of its keyboard shortcut for the appropriate platform will be
+ * appended to the title if the tool is part of a bar tool group.
+ *
+ * @abstract
+ * @static
+ * @property {string|Function} Title text or a function that returns text
+ * @inheritable
+ */
+OO.ui.Tool.static.title = '';
+
+/**
+ * Tool can be automatically added to tool groups.
+ *
+ * @static
+ * @property {boolean}
+ * @inheritable
+ */
+OO.ui.Tool.static.autoAdd = true;
+
+/**
+ * Check if this tool is compatible with given data.
+ *
+ * @method
+ * @static
+ * @inheritable
+ * @param {Mixed} data Data to check
+ * @returns {boolean} Tool can be used with data
+ */
+OO.ui.Tool.static.isCompatibleWith = function () {
+       return false;
+};
+
+/* Methods */
+
+/**
+ * Handle the toolbar state being updated.
+ *
+ * This is an abstract method that must be overridden in a concrete subclass.
+ *
+ * @abstract
+ * @method
+ */
+OO.ui.Tool.prototype.onUpdateState = function () {
+       throw new Error(
+               'OO.ui.Tool.onUpdateState not implemented in this subclass:' + this.constructor
+       );
+};
+
+/**
+ * Handle the tool being selected.
+ *
+ * This is an abstract method that must be overridden in a concrete subclass.
+ *
+ * @abstract
+ * @method
+ */
+OO.ui.Tool.prototype.onSelect = function () {
+       throw new Error(
+               'OO.ui.Tool.onSelect not implemented in this subclass:' + this.constructor
+       );
+};
+
+/**
+ * Check if the button is active.
+ *
+ * @method
+ * @param {boolean} Button is active
+ */
+OO.ui.Tool.prototype.isActive = function () {
+       return this.active;
+};
+
+/**
+ * Make the button appear active or inactive.
+ *
+ * @method
+ * @param {boolean} state Make button appear active
+ */
+OO.ui.Tool.prototype.setActive = function ( state ) {
+       this.active = !!state;
+       if ( this.active ) {
+               this.$element.addClass( 'oo-ui-tool-active' );
+       } else {
+               this.$element.removeClass( 'oo-ui-tool-active' );
+       }
+};
+
+/**
+ * Get the tool title.
+ *
+ * @method
+ * @param {string|Function} title Title text or a function that returns text
+ * @chainable
+ */
+OO.ui.Tool.prototype.setTitle = function ( title ) {
+       this.title = OO.ui.resolveMsg( title );
+       this.updateTitle();
+       return this;
+};
+
+/**
+ * Get the tool title.
+ *
+ * @method
+ * @returns {string} Title text
+ */
+OO.ui.Tool.prototype.getTitle = function () {
+       return this.title;
+};
+
+/**
+ * Get the tool's symbolic name.
+ *
+ * @method
+ * @returns {string} Symbolic name of tool
+ */
+OO.ui.Tool.prototype.getName = function () {
+       return this.constructor.static.name;
+};
+
+/**
+ * Update the title.
+ *
+ * @method
+ */
+OO.ui.Tool.prototype.updateTitle = function () {
+       var titleTooltips = this.toolGroup.constructor.static.titleTooltips,
+               accelTooltips = this.toolGroup.constructor.static.accelTooltips,
+               accel = this.toolbar.getToolAccelerator( this.constructor.static.name ),
+               tooltipParts = [];
+
+       this.$title.empty()
+               .text( this.title )
+               .append(
+                       this.$( '<span>' )
+                               .addClass( 'oo-ui-tool-accel' )
+                               .text( accel )
+               );
+
+       if ( titleTooltips && typeof this.title === 'string' && this.title.length ) {
+               tooltipParts.push( this.title );
+       }
+       if ( accelTooltips && typeof accel === 'string' && accel.length ) {
+               tooltipParts.push( accel );
+       }
+       if ( tooltipParts.length ) {
+               this.$link.attr( 'title', tooltipParts.join( ' ' ) );
+       } else {
+               this.$link.removeAttr( 'title' );
+       }
+};
+
+/**
+ * Destroy tool.
+ *
+ * @method
+ */
+OO.ui.Tool.prototype.destroy = function () {
+       this.toolbar.disconnect( this );
+       this.$element.remove();
+};
+/**
+ * Collection of tool groups.
+ *
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ * @mixins OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {OO.Factory} toolFactory Factory for creating tools
+ * @param {Object} [options] Configuration options
+ * @cfg {boolean} [actions] Add an actions section opposite to the tools
+ * @cfg {boolean} [shadow] Add a shadow below the toolbar
+ */
+OO.ui.Toolbar = function OoUiToolbar( toolFactory, options ) {
+       // Configuration initialization
+       options = options || {};
+
+       // Parent constructor
+       OO.ui.Element.call( this, options );
+
+       // Mixin constructors
+       OO.EventEmitter.call( this );
+       OO.ui.GroupElement.call( this, this.$( '<div>' ) );
+
+       // Properties
+       this.toolFactory = toolFactory;
+       this.groups = [];
+       this.tools = {};
+       this.$bar = this.$( '<div>' );
+       this.$actions = this.$( '<div>' );
+       this.initialized = false;
+
+       // Events
+       this.$element
+               .add( this.$bar ).add( this.$group ).add( this.$actions )
+               .on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
+
+       // Initialization
+       this.$group.addClass( 'oo-ui-toolbar-tools' );
+       this.$bar.addClass( 'oo-ui-toolbar-bar' ).append( this.$group );
+       if ( options.actions ) {
+               this.$actions.addClass( 'oo-ui-toolbar-actions' );
+               this.$bar.append( this.$actions );
+       }
+       this.$bar.append( '<div style="clear:both"></div>' );
+       if ( options.shadow ) {
+               this.$bar.append( '<div class="oo-ui-toolbar-shadow"></div>' );
+       }
+       this.$element.addClass( 'oo-ui-toolbar' ).append( this.$bar );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.Toolbar, OO.ui.Element );
+
+OO.mixinClass( OO.ui.Toolbar, OO.EventEmitter );
+OO.mixinClass( OO.ui.Toolbar, OO.ui.GroupElement );
+
+/* Methods */
+
+/**
+ * Get the tool factory.
+ *
+ * @method
+ * @returns {OO.Factory} Tool factory
+ */
+OO.ui.Toolbar.prototype.getToolFactory = function () {
+       return this.toolFactory;
+};
+
+/**
+ * Handles mouse down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.Toolbar.prototype.onMouseDown = function ( e ) {
+       var $closestWidgetToEvent = this.$( e.target ).closest( '.oo-ui-widget' ),
+               $closestWidgetToToolbar = this.$element.closest( '.oo-ui-widget' );
+       if ( !$closestWidgetToEvent.length || $closestWidgetToEvent[0] === $closestWidgetToToolbar[0] ) {
+               return false;
+       }
+};
+
+/**
+ * Sets up handles and preloads required information for the toolbar to work.
+ * This must be called immediately after it is attached to a visible document.
+ */
+OO.ui.Toolbar.prototype.initialize = function () {
+       this.initialized = true;
+};
+
+/**
+ * Setup toolbar.
+ *
+ * Tools can be specified in the following ways:
+ *  - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
+ *  - All tools in a group: `{ 'group': 'group-name' }`
+ *  - All tools: `'*'` - Using this will make the group a list with a "More" label by default
+ *
+ * @method
+ * @param {Object.<string,Array>} groups List of tool group configurations
+ * @param {Array|string} [groups.include] Tools to include
+ * @param {Array|string} [groups.exclude] Tools to exclude
+ * @param {Array|string} [groups.promote] Tools to promote to the beginning
+ * @param {Array|string} [groups.demote] Tools to demote to the end
+ */
+OO.ui.Toolbar.prototype.setup = function ( groups ) {
+       var i, len, type, group,
+               items = [],
+               // TODO: Use a registry instead
+               defaultType = 'bar',
+               constructors = {
+                       'bar': OO.ui.BarToolGroup,
+                       'list': OO.ui.ListToolGroup,
+                       'menu': OO.ui.MenuToolGroup
+               };
+
+       // Cleanup previous groups
+       this.reset();
+
+       // Build out new groups
+       for ( i = 0, len = groups.length; i < len; i++ ) {
+               group = groups[i];
+               if ( group.include === '*' ) {
+                       // Apply defaults to catch-all groups
+                       if ( group.type === undefined ) {
+                               group.type = 'list';
+                       }
+                       if ( group.label === undefined ) {
+                               group.label = 'ooui-toolbar-more';
+                       }
+               }
+               type = constructors[group.type] ? group.type : defaultType;
+               items.push(
+                       new constructors[type]( this, $.extend( { '$': this.$ }, group ) )
+               );
+       }
+       this.addItems( items );
+};
+
+/**
+ * Remove all tools and groups from the toolbar.
+ */
+OO.ui.Toolbar.prototype.reset = function () {
+       var i, len;
+
+       this.groups = [];
+       this.tools = {};
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               this.items[i].destroy();
+       }
+       this.clearItems();
+};
+
+/**
+ * Destroys toolbar, removing event handlers and DOM elements.
+ *
+ * Call this whenever you are done using a toolbar.
+ */
+OO.ui.Toolbar.prototype.destroy = function () {
+       this.reset();
+       this.$element.remove();
+};
+
+/**
+ * Check if tool has not been used yet.
+ *
+ * @param {string} name Symbolic name of tool
+ * @return {boolean} Tool is available
+ */
+OO.ui.Toolbar.prototype.isToolAvailable = function ( name ) {
+       return !this.tools[name];
+};
+
+/**
+ * Prevent tool from being used again.
+ *
+ * @param {OO.ui.Tool} tool Tool to reserve
+ */
+OO.ui.Toolbar.prototype.reserveTool = function ( tool ) {
+       this.tools[tool.getName()] = tool;
+};
+
+/**
+ * Allow tool to be used again.
+ *
+ * @param {OO.ui.Tool} tool Tool to release
+ */
+OO.ui.Toolbar.prototype.releaseTool = function ( tool ) {
+       delete this.tools[tool.getName()];
+};
+
+/**
+ * Get accelerator label for tool.
+ *
+ * This is a stub that should be overridden to provide access to accelerator information.
+ *
+ * @param {string} name Symbolic name of tool
+ * @returns {string|undefined} Tool accelerator label if available
+ */
+OO.ui.Toolbar.prototype.getToolAccelerator = function () {
+       return undefined;
+};
+/**
+ * Factory for tools.
+ *
+ * @class
+ * @extends OO.Factory
+ * @constructor
+ */
+OO.ui.ToolFactory = function OoUiToolFactory() {
+       // Parent constructor
+       OO.Factory.call( this );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.ToolFactory, OO.Factory );
+
+/* Methods */
+
+OO.ui.ToolFactory.prototype.getTools = function ( include, exclude, promote, demote ) {
+       var i, len, included, promoted, demoted,
+               auto = [],
+               used = {};
+
+       // Collect included and not excluded tools
+       included = OO.simpleArrayDifference( this.extract( include ), this.extract( exclude ) );
+
+       // Promotion
+       promoted = this.extract( promote, used );
+       demoted = this.extract( demote, used );
+
+       // Auto
+       for ( i = 0, len = included.length; i < len; i++ ) {
+               if ( !used[included[i]] ) {
+                       auto.push( included[i] );
+               }
+       }
+
+       return promoted.concat( auto ).concat( demoted );
+};
+
+/**
+ * Get a flat list of names from a list of names or groups.
+ *
+ * Tools can be specified in the following ways:
+ *  - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
+ *  - All tools in a group: `{ 'group': 'group-name' }`
+ *  - All tools: `'*'`
+ *
+ * @private
+ * @param {Array|string} collection List of tools
+ * @param {Object} [used] Object with names that should be skipped as properties; extracted
+ *   names will be added as properties
+ * @return {string[]} List of extracted names
+ */
+OO.ui.ToolFactory.prototype.extract = function ( collection, used ) {
+       var i, len, item, name, tool,
+               names = [];
+
+       if ( collection === '*' ) {
+               for ( name in this.registry ) {
+                       tool = this.registry[name];
+                       if (
+                               // Only add tools by group name when auto-add is enabled
+                               tool.static.autoAdd &&
+                               // Exclude already used tools
+                               ( !used || !used[name] )
+                       ) {
+                               names.push( name );
+                               if ( used ) {
+                                       used[name] = true;
+                               }
+                       }
+               }
+       } else if ( Array.isArray( collection ) ) {
+               for ( i = 0, len = collection.length; i < len; i++ ) {
+                       item = collection[i];
+                       // Allow plain strings as shorthand for named tools
+                       if ( typeof item === 'string' ) {
+                               item = { 'name': item };
+                       }
+                       if ( OO.isPlainObject( item ) ) {
+                               if ( item.group ) {
+                                       for ( name in this.registry ) {
+                                               tool = this.registry[name];
+                                               if (
+                                                       // Include tools with matching group
+                                                       tool.static.group === item.group &&
+                                                       // Only add tools by group name when auto-add is enabled
+                                                       tool.static.autoAdd &&
+                                                       // Exclude already used tools
+                                                       ( !used || !used[name] )
+                                               ) {
+                                                       names.push( name );
+                                                       if ( used ) {
+                                                               used[name] = true;
+                                                       }
+                                               }
+                                       }
+                               }
+                               // Include tools with matching name and exclude already used tools
+                               else if ( item.name && ( !used || !used[item.name] ) ) {
+                                       names.push( item.name );
+                                       if ( used ) {
+                                               used[item.name] = true;
+                                       }
+                               }
+                       }
+               }
+       }
+       return names;
+};
+/**
+ * Collection of tools.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.GroupElement
+ *
+ * Tools can be specified in the following ways:
+ *  - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
+ *  - All tools in a group: `{ 'group': 'group-name' }`
+ *  - All tools: `'*'`
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ * @cfg {Array|string} [include=[]] List of tools to include
+ * @cfg {Array|string} [exclude=[]] List of tools to exclude
+ * @cfg {Array|string} [promote=[]] List of tools to promote to the beginning
+ * @cfg {Array|string} [demote=[]] List of tools to demote to the end
+ */
+OO.ui.ToolGroup = function OoUiToolGroup( toolbar, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.GroupElement.call( this, this.$( '<div>' ) );
+
+       // Properties
+       this.toolbar = toolbar;
+       this.tools = {};
+       this.pressed = null;
+       this.include = config.include || [];
+       this.exclude = config.exclude || [];
+       this.promote = config.promote || [];
+       this.demote = config.demote || [];
+       this.onCapturedMouseUpHandler = OO.ui.bind( this.onCapturedMouseUp, this );
+
+       // Events
+       this.$element.on( {
+               'mousedown': OO.ui.bind( this.onMouseDown, this ),
+               'mouseup': OO.ui.bind( this.onMouseUp, this ),
+               'mouseover': OO.ui.bind( this.onMouseOver, this ),
+               'mouseout': OO.ui.bind( this.onMouseOut, this )
+       } );
+       this.toolbar.getToolFactory().connect( this, { 'register': 'onToolFactoryRegister' } );
+
+       // Initialization
+       this.$group.addClass( 'oo-ui-toolGroup-tools' );
+       this.$element
+               .addClass( 'oo-ui-toolGroup' )
+               .append( this.$group );
+       this.populate();
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.ToolGroup, OO.ui.Widget );
+
+OO.mixinClass( OO.ui.ToolGroup, OO.ui.GroupElement );
+
+/* Events */
+
+/**
+ * @event update
+ */
+
+/* Static Properties */
+
+/**
+ * Show labels in tooltips.
+ *
+ * @static
+ * @property {boolean}
+ * @inheritable
+ */
+OO.ui.ToolGroup.static.titleTooltips = false;
+
+/**
+ * Show acceleration labels in tooltips.
+ *
+ * @static
+ * @property {boolean}
+ * @inheritable
+ */
+OO.ui.ToolGroup.static.accelTooltips = false;
+
+/* Methods */
+
+/**
+ * Handle mouse down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.ToolGroup.prototype.onMouseDown = function ( e ) {
+       if ( !this.disabled && e.which === 1 ) {
+               this.pressed = this.getTargetTool( e );
+               if ( this.pressed ) {
+                       this.pressed.setActive( true );
+                       this.getElementDocument().addEventListener(
+                               'mouseup', this.onCapturedMouseUpHandler, true
+                       );
+                       return false;
+               }
+       }
+};
+
+/**
+ * Handle captured mouse up events.
+ *
+ * @method
+ * @param {Event} e Mouse up event
+ */
+OO.ui.ToolGroup.prototype.onCapturedMouseUp = function ( e ) {
+       this.getElementDocument().removeEventListener( 'mouseup', this.onCapturedMouseUpHandler, true );
+       // onMouseUp may be called a second time, depending on where the mouse is when the button is
+       // released, but since `this.pressed` will no longer be true, the second call will be ignored.
+       this.onMouseUp( e );
+};
+
+/**
+ * Handle mouse up events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse up event
+ */
+OO.ui.ToolGroup.prototype.onMouseUp = function ( e ) {
+       var tool = this.getTargetTool( e );
+
+       if ( !this.disabled && e.which === 1 && this.pressed && this.pressed === tool ) {
+               this.pressed.onSelect();
+       }
+
+       this.pressed = null;
+       return false;
+};
+
+/**
+ * Handle mouse over events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse over event
+ */
+OO.ui.ToolGroup.prototype.onMouseOver = function ( e ) {
+       var tool = this.getTargetTool( e );
+
+       if ( this.pressed && this.pressed === tool ) {
+               this.pressed.setActive( true );
+       }
+};
+
+/**
+ * Handle mouse out events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse out event
+ */
+OO.ui.ToolGroup.prototype.onMouseOut = function ( e ) {
+       var tool = this.getTargetTool( e );
+
+       if ( this.pressed && this.pressed === tool ) {
+               this.pressed.setActive( false );
+       }
+};
+
+/**
+ * Get the closest tool to a jQuery.Event.
+ *
+ * Only tool links are considered, which prevents other elements in the tool such as popups from
+ * triggering tool group interactions.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e
+ * @returns {OO.ui.Tool|null} Tool, `null` if none was found
+ */
+OO.ui.ToolGroup.prototype.getTargetTool = function ( e ) {
+       var tool,
+               $item = this.$( e.target ).closest( '.oo-ui-tool-link' );
+
+       if ( $item.length ) {
+               tool = $item.parent().data( 'oo-ui-tool' );
+       }
+
+       return tool && !tool.isDisabled() ? tool : null;
+};
+
+/**
+ * Handle tool registry register events.
+ *
+ * If a tool is registered after the group is created, we must repopulate the list to account for:
+ * - a tool being added that may be included
+ * - a tool already included being overridden
+ *
+ * @param {string} name Symbolic name of tool
+ */
+OO.ui.ToolGroup.prototype.onToolFactoryRegister = function () {
+       this.populate();
+};
+
+/**
+ * Get the toolbar this group is in.
+ *
+ * @return {OO.ui.Toolbar} Toolbar of group
+ */
+OO.ui.ToolGroup.prototype.getToolbar = function () {
+       return this.toolbar;
+};
+
+/**
+ * Add and remove tools based on configuration.
+ *
+ * @method
+ */
+OO.ui.ToolGroup.prototype.populate = function () {
+       var i, len, name, tool,
+               toolFactory = this.toolbar.getToolFactory(),
+               names = {},
+               add = [],
+               remove = [],
+               list = this.toolbar.getToolFactory().getTools(
+                       this.include, this.exclude, this.promote, this.demote
+               );
+
+       // Build a list of needed tools
+       for ( i = 0, len = list.length; i < len; i++ ) {
+               name = list[i];
+               if (
+                       // Tool exists
+                       toolFactory.lookup( name ) &&
+                       // Tool is available or is already in this group
+                       ( this.toolbar.isToolAvailable( name ) || this.tools[name] )
+               ) {
+                       tool = this.tools[name];
+                       if ( !tool ) {
+                               // Auto-initialize tools on first use
+                               this.tools[name] = tool = toolFactory.create( name, this );
+                               tool.updateTitle();
+                       }
+                       this.toolbar.reserveTool( tool );
+                       add.push( tool );
+                       names[name] = true;
+               }
+       }
+       // Remove tools that are no longer needed
+       for ( name in this.tools ) {
+               if ( !names[name] ) {
+                       this.tools[name].destroy();
+                       this.toolbar.releaseTool( this.tools[name] );
+                       remove.push( this.tools[name] );
+                       delete this.tools[name];
+               }
+       }
+       if ( remove.length ) {
+               this.removeItems( remove );
+       }
+       // Update emptiness state
+       if ( add.length ) {
+               this.$element.removeClass( 'oo-ui-toolGroup-empty' );
+       } else {
+               this.$element.addClass( 'oo-ui-toolGroup-empty' );
+       }
+       // Re-add tools (moving existing ones to new locations)
+       this.addItems( add );
+};
+
+/**
+ * Destroy tool group.
+ *
+ * @method
+ */
+OO.ui.ToolGroup.prototype.destroy = function () {
+       var name;
+
+       this.clearItems();
+       this.toolbar.getToolFactory().disconnect( this );
+       for ( name in this.tools ) {
+               this.toolbar.releaseTool( this.tools[name] );
+               this.tools[name].disconnect( this ).destroy();
+               delete this.tools[name];
+       }
+       this.$element.remove();
+};
+/**
+ * Layout made of a fieldset and optional legend.
+ *
+ * @class
+ * @extends OO.ui.Layout
+ * @mixins OO.ui.LabeledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [icon] Symbolic icon name
+ */
+OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {
+       // Config initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Layout.call( this, config );
+
+       // Mixin constructors
+       OO.ui.LabeledElement.call( this, this.$( '<legend>' ), config );
+
+       // Initialization
+       if ( config.icon ) {
+               this.$element.addClass( 'oo-ui-fieldsetLayout-decorated' );
+               this.$label.addClass( 'oo-ui-icon-' + config.icon );
+       }
+       this.$element.addClass( 'oo-ui-fieldsetLayout' );
+       if ( config.icon || config.label ) {
+               this.$element
+                       .addClass( 'oo-ui-fieldsetLayout-labeled' )
+                       .append( this.$label );
+       }
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.FieldsetLayout, OO.ui.Layout );
+
+OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.LabeledElement );
+
+/* Static Properties */
+
+OO.ui.FieldsetLayout.static.tagName = 'fieldset';
+/**
+ * Layout made of proportionally sized columns and rows.
+ *
+ * @class
+ * @extends OO.ui.Layout
+ *
+ * @constructor
+ * @param {OO.ui.PanelLayout[]} panels Panels in the grid
+ * @param {Object} [config] Configuration options
+ * @cfg {number[]} [widths] Widths of columns as ratios
+ * @cfg {number[]} [heights] Heights of columns as ratios
+ */
+OO.ui.GridLayout = function OoUiGridLayout( panels, config ) {
+       var i, len, widths;
+
+       // Config initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Layout.call( this, config );
+
+       // Properties
+       this.panels = [];
+       this.widths = [];
+       this.heights = [];
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-gridLayout' );
+       for ( i = 0, len = panels.length; i < len; i++ ) {
+               this.panels.push( panels[i] );
+               this.$element.append( panels[i].$element );
+       }
+       if ( config.widths || config.heights ) {
+               this.layout( config.widths || [1], config.heights || [1] );
+       } else {
+               // Arrange in columns by default
+               widths = [];
+               for ( i = 0, len = this.panels.length; i < len; i++ ) {
+                       widths[i] = 1;
+               }
+               this.layout( widths, [1] );
+       }
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.GridLayout, OO.ui.Layout );
+
+/* Events */
+
+/**
+ * @event layout
+ */
+
+/**
+ * @event update
+ */
+
+/* Static Properties */
+
+OO.ui.GridLayout.static.tagName = 'div';
+
+/* Methods */
+
+/**
+ * Set grid dimensions.
+ *
+ * @method
+ * @param {number[]} widths Widths of columns as ratios
+ * @param {number[]} heights Heights of rows as ratios
+ * @fires layout
+ * @throws {Error} If grid is not large enough to fit all panels
+ */
+OO.ui.GridLayout.prototype.layout = function ( widths, heights ) {
+       var x, y,
+               xd = 0,
+               yd = 0,
+               cols = widths.length,
+               rows = heights.length;
+
+       // Verify grid is big enough to fit panels
+       if ( cols * rows < this.panels.length ) {
+               throw new Error( 'Grid is not large enough to fit ' + this.panels.length + 'panels' );
+       }
+
+       // Sum up denominators
+       for ( x = 0; x < cols; x++ ) {
+               xd += widths[x];
+       }
+       for ( y = 0; y < rows; y++ ) {
+               yd += heights[y];
+       }
+       // Store factors
+       this.widths = [];
+       this.heights = [];
+       for ( x = 0; x < cols; x++ ) {
+               this.widths[x] = widths[x] / xd;
+       }
+       for ( y = 0; y < rows; y++ ) {
+               this.heights[y] = heights[y] / yd;
+       }
+       // Synchronize view
+       this.update();
+       this.emit( 'layout' );
+};
+
+/**
+ * Update panel positions and sizes.
+ *
+ * @method
+ * @fires update
+ */
+OO.ui.GridLayout.prototype.update = function () {
+       var x, y, panel,
+               i = 0,
+               left = 0,
+               top = 0,
+               dimensions,
+               width = 0,
+               height = 0,
+               cols = this.widths.length,
+               rows = this.heights.length;
+
+       for ( y = 0; y < rows; y++ ) {
+               for ( x = 0; x < cols; x++ ) {
+                       panel = this.panels[i];
+                       width = this.widths[x];
+                       height = this.heights[y];
+                       dimensions = {
+                               'width': Math.round( width * 100 ) + '%',
+                               'height': Math.round( height * 100 ) + '%',
+                               'top': Math.round( top * 100 ) + '%'
+                       };
+                       // If RTL, reverse:
+                       if ( OO.ui.Element.getDir( this.$.context ) === 'rtl' ) {
+                               dimensions.right = Math.round( left * 100 ) + '%';
+                       } else {
+                               dimensions.left = Math.round( left * 100 ) + '%';
+                       }
+                       panel.$element.css( dimensions );
+                       i++;
+                       left += width;
+               }
+               top += height;
+               left = 0;
+       }
+
+       this.emit( 'update' );
+};
+
+/**
+ * Get a panel at a given position.
+ *
+ * The x and y position is affected by the current grid layout.
+ *
+ * @method
+ * @param {number} x Horizontal position
+ * @param {number} y Vertical position
+ * @returns {OO.ui.PanelLayout} The panel at the given postion
+ */
+OO.ui.GridLayout.prototype.getPanel = function ( x, y ) {
+       return this.panels[( x * this.widths.length ) + y];
+};
+/**
+ * Layout containing a series of pages.
+ *
+ * @class
+ * @extends OO.ui.Layout
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [continuous=false] Show all pages, one after another
+ * @cfg {boolean} [autoFocus=false] Focus on the first focusable element when changing to a page
+ * @cfg {boolean} [outlined=false] Show an outline
+ * @cfg {boolean} [editable=false] Show controls for adding, removing and reordering pages
+ * @cfg {Object[]} [adders] List of adders for controls, each with name, icon and title properties
+ */
+OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
+       // Initialize configuration
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Layout.call( this, config );
+
+       // Properties
+       this.currentPageName = null;
+       this.pages = {};
+       this.ignoreFocus = false;
+       this.stackLayout = new OO.ui.StackLayout( { '$': this.$, 'continuous': !!config.continuous } );
+       this.autoFocus = !!config.autoFocus;
+       this.outlined = !!config.outlined;
+       if ( this.outlined ) {
+               this.editable = !!config.editable;
+               this.adders = config.adders || null;
+               this.outlineControlsWidget = null;
+               this.outlineWidget = new OO.ui.OutlineWidget( { '$': this.$ } );
+               this.outlinePanel = new OO.ui.PanelLayout( { '$': this.$, 'scrollable': true } );
+               this.gridLayout = new OO.ui.GridLayout(
+                       [this.outlinePanel, this.stackLayout], { '$': this.$, 'widths': [1, 2] }
+               );
+               if ( this.editable ) {
+                       this.outlineControlsWidget = new OO.ui.OutlineControlsWidget(
+                               this.outlineWidget,
+                               { '$': this.$, 'adders': this.adders }
+                       );
+               }
+       }
+
+       // Events
+       this.stackLayout.connect( this, { 'set': 'onStackLayoutSet' } );
+       if ( this.outlined ) {
+               this.outlineWidget.connect( this, { 'select': 'onOutlineWidgetSelect' } );
+               // Event 'focus' does not bubble, but 'focusin' does
+               this.stackLayout.onDOMEvent( 'focusin', OO.ui.bind( this.onStackLayoutFocus, this ) );
+       }
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-bookletLayout' );
+       this.stackLayout.$element.addClass( 'oo-ui-bookletLayout-stackLayout' );
+       if ( this.outlined ) {
+               this.outlinePanel.$element
+                       .addClass( 'oo-ui-bookletLayout-outlinePanel' )
+                       .append( this.outlineWidget.$element );
+               if ( this.editable ) {
+                       this.outlinePanel.$element
+                               .addClass( 'oo-ui-bookletLayout-outlinePanel-editable' )
+                               .append( this.outlineControlsWidget.$element );
+               }
+               this.$element.append( this.gridLayout.$element );
+       } else {
+               this.$element.append( this.stackLayout.$element );
+       }
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.BookletLayout, OO.ui.Layout );
+
+/* Events */
+
+/**
+ * @event set
+ * @param {OO.ui.PageLayout} page Current page
+ */
+
+/**
+ * @event add
+ * @param {OO.ui.PageLayout[]} page Added pages
+ * @param {number} index Index pages were added at
+ */
+
+/**
+ * @event remove
+ * @param {OO.ui.PageLayout[]} pages Removed pages
+ */
+
+/* Methods */
+
+/**
+ * Handle stack layout focus.
+ *
+ * @method
+ * @param {jQuery.Event} e Focusin event
+ */
+OO.ui.BookletLayout.prototype.onStackLayoutFocus = function ( e ) {
+       var name, $target;
+
+       if ( this.ignoreFocus ) {
+               // Avoid recursion from programmatic focus trigger in #onStackLayoutSet
+               return;
+       }
+
+       $target = $( e.target ).closest( '.oo-ui-pageLayout' );
+       for ( name in this.pages ) {
+               if ( this.pages[ name ].$element[0] === $target[0] ) {
+                       this.setPage( name );
+                       break;
+               }
+       }
+};
+
+/**
+ * Handle stack layout set events.
+ *
+ * @method
+ * @param {OO.ui.PanelLayout|null} page The page panel that is now the current panel
+ */
+OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {
+       if ( page ) {
+               page.scrollElementIntoView( { 'complete': OO.ui.bind( function () {
+                       this.ignoreFocus = true;
+                       if ( this.autoFocus ) {
+                               page.$element.find( ':input:first' ).focus();
+                       }
+                       this.ignoreFocus = false;
+               }, this ) } );
+       }
+};
+
+/**
+ * Handle outline widget select events.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget|null} item Selected item
+ */
+OO.ui.BookletLayout.prototype.onOutlineWidgetSelect = function ( item ) {
+       if ( item ) {
+               this.setPage( item.getData() );
+       }
+};
+
+/**
+ * Check if booklet has an outline.
+ *
+ * @method
+ * @returns {boolean} Booklet is outlined
+ */
+OO.ui.BookletLayout.prototype.isOutlined = function () {
+       return this.outlined;
+};
+
+/**
+ * Check if booklet has editing controls.
+ *
+ * @method
+ * @returns {boolean} Booklet is outlined
+ */
+OO.ui.BookletLayout.prototype.isEditable = function () {
+       return this.editable;
+};
+
+/**
+ * Get the outline widget.
+ *
+ * @method
+ * @returns {OO.ui.OutlineWidget|null} Outline widget, or null if boolet has no outline
+ */
+OO.ui.BookletLayout.prototype.getOutline = function () {
+       return this.outlineWidget;
+};
+
+/**
+ * Get the outline controls widget. If the outline is not editable, null is returned.
+ *
+ * @method
+ * @returns {OO.ui.OutlineControlsWidget|null} The outline controls widget.
+ */
+OO.ui.BookletLayout.prototype.getOutlineControls = function () {
+       return this.outlineControlsWidget;
+};
+
+/**
+ * Get a page by name.
+ *
+ * @method
+ * @param {string} name Symbolic name of page
+ * @returns {OO.ui.PageLayout|undefined} Page, if found
+ */
+OO.ui.BookletLayout.prototype.getPage = function ( name ) {
+       return this.pages[name];
+};
+
+/**
+ * Get the current page name.
+ *
+ * @method
+ * @returns {string|null} Current page name
+ */
+OO.ui.BookletLayout.prototype.getPageName = function () {
+       return this.currentPageName;
+};
+
+/**
+ * Add a page to the layout.
+ *
+ * When pages are added with the same names as existing pages, the existing pages will be
+ * automatically removed before the new pages are added.
+ *
+ * @method
+ * @param {OO.ui.PageLayout[]} pages Pages to add
+ * @param {number} index Index to insert pages after
+ * @fires add
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {
+       var i, len, name, page,
+               items = [],
+               remove = [];
+
+       for ( i = 0, len = pages.length; i < len; i++ ) {
+               page = pages[i];
+               name = page.getName();
+               if ( name in this.pages ) {
+                       // Remove page with same name
+                       remove.push( this.pages[name] );
+               }
+               this.pages[page.getName()] = page;
+               if ( this.outlined ) {
+                       items.push( new OO.ui.BookletOutlineItemWidget( name, page, { '$': this.$ } ) );
+               }
+       }
+       if ( remove.length ) {
+               this.removePages( remove );
+       }
+
+       if ( this.outlined && items.length ) {
+               this.outlineWidget.addItems( items, index );
+               this.updateOutlineWidget();
+       }
+       this.stackLayout.addItems( pages, index );
+       this.emit( 'add', pages, index );
+
+       return this;
+};
+
+/**
+ * Remove a page from the layout.
+ *
+ * @method
+ * @fires remove
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.removePages = function ( pages ) {
+       var i, len, name, page,
+               items = [];
+
+       for ( i = 0, len = pages.length; i < len; i++ ) {
+               page = pages[i];
+               name = page.getName();
+               delete this.pages[name];
+               if ( this.outlined ) {
+                       items.push( this.outlineWidget.getItemFromData( name ) );
+               }
+       }
+       if ( this.outlined && items.length ) {
+               this.outlineWidget.removeItems( items );
+               this.updateOutlineWidget();
+       }
+       this.stackLayout.removeItems( pages );
+       this.emit( 'remove', pages );
+
+       return this;
+};
+
+/**
+ * Clear all pages from the layout.
+ *
+ * @method
+ * @fires remove
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.clearPages = function () {
+       var pages = this.stackLayout.getItems();
+
+       this.pages = {};
+       this.currentPageName = null;
+       if ( this.outlined ) {
+               this.outlineWidget.clearItems();
+       }
+       this.stackLayout.clearItems();
+
+       this.emit( 'remove', pages );
+
+       return this;
+};
+
+/**
+ * Set the current page by name.
+ *
+ * @method
+ * @fires set
+ * @param {string} name Symbolic name of page
+ */
+OO.ui.BookletLayout.prototype.setPage = function ( name ) {
+       var selectedItem,
+               page = this.pages[name];
+
+       if ( this.outlined ) {
+               selectedItem = this.outlineWidget.getSelectedItem();
+               if ( selectedItem && selectedItem.getData() !== name ) {
+                       this.outlineWidget.selectItem( this.outlineWidget.getItemFromData( name ) );
+               }
+       }
+
+       if ( page ) {
+               this.currentPageName = name;
+               this.stackLayout.setItem( page );
+               this.emit( 'set', page );
+       }
+};
+
+/**
+ * Call this after adding or removing items from the OutlineWidget.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.updateOutlineWidget = function () {
+       // Auto-select first item when nothing is selected anymore
+       if ( !this.outlineWidget.getSelectedItem() ) {
+               this.outlineWidget.selectItem( this.outlineWidget.getFirstSelectableItem() );
+       }
+
+       return this;
+};
+/**
+ * Layout that expands to cover the entire area of its parent, with optional scrolling and padding.
+ *
+ * @class
+ * @extends OO.ui.Layout
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [scrollable] Allow vertical scrolling
+ * @cfg {boolean} [padded] Pad the content from the edges
+ */
+OO.ui.PanelLayout = function OoUiPanelLayout( config ) {
+       // Config initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Layout.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-panelLayout' );
+       if ( config.scrollable ) {
+               this.$element.addClass( 'oo-ui-panelLayout-scrollable' );
+       }
+
+       if ( config.padded ) {
+               this.$element.addClass( 'oo-ui-panelLayout-padded' );
+       }
+
+       // Add directionality class:
+       this.$element.addClass( 'oo-ui-' + OO.ui.Element.getDir( this.$.context ) );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.PanelLayout, OO.ui.Layout );
+/**
+ * Page within an OO.ui.BookletLayout.
+ *
+ * @class
+ * @extends OO.ui.PanelLayout
+ *
+ * @constructor
+ * @param {string} name Unique symbolic name of page
+ * @param {Object} [config] Configuration options
+ * @param {string} [icon=''] Symbolic name of icon to display in outline
+ * @param {string} [indicator=''] Symbolic name of indicator to display in outline
+ * @param {string} [indicatorTitle=''] Description of indicator meaning to display in outline
+ * @param {string} [label=''] Label to display in outline
+ * @param {number} [level=0] Indentation level of item in outline
+ * @param {boolean} [movable=false] Page should be movable using outline controls
+ */
+OO.ui.PageLayout = function OoUiPageLayout( name, config ) {
+       // Configuration initialization
+       config = $.extend( { 'scrollable': true }, config );
+
+       // Parent constructor
+       OO.ui.PanelLayout.call( this, config );
+
+       // Properties
+       this.name = name;
+       this.icon = config.icon || '';
+       this.indicator = config.indicator || '';
+       this.indicatorTitle = OO.ui.resolveMsg( config.indicatorTitle ) || '';
+       this.label = OO.ui.resolveMsg( config.label ) || '';
+       this.level = config.level || 0;
+       this.movable = !!config.movable;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-pageLayout' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.PageLayout, OO.ui.PanelLayout );
+
+/* Methods */
+
+/**
+ * Get page name.
+ *
+ * @returns {string} Symbolic name of page
+ */
+OO.ui.PageLayout.prototype.getName = function () {
+       return this.name;
+};
+
+/**
+ * Get page icon.
+ *
+ * @returns {string} Symbolic name of icon
+ */
+OO.ui.PageLayout.prototype.getIcon = function () {
+       return this.icon;
+};
+
+/**
+ * Get page indicator.
+ *
+ * @returns {string} Symbolic name of indicator
+ */
+OO.ui.PageLayout.prototype.getIndicator = function () {
+       return this.indicator;
+};
+
+/**
+ * Get page indicator label.
+ *
+ * @returns {string} Description of indicator meaning
+ */
+OO.ui.PageLayout.prototype.getIndicatorTitle = function () {
+       return this.indicatorTitle;
+};
+
+/**
+ * Get page label.
+ *
+ * @returns {string} Label text
+ */
+OO.ui.PageLayout.prototype.getLabel = function () {
+       return this.label;
+};
+
+/**
+ * Get outline item indentation level.
+ *
+ * @returns {number} Indentation level
+ */
+OO.ui.PageLayout.prototype.getLevel = function () {
+       return this.level;
+};
+
+/**
+ * Check if page is movable using outline controls.
+ *
+ * @returns {boolean} Page is movable
+ */
+OO.ui.PageLayout.prototype.isMovable = function () {
+       return this.movable;
+};
+/**
+ * Layout containing a series of mutually exclusive pages.
+ *
+ * @class
+ * @extends OO.ui.PanelLayout
+ * @mixins OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [continuous=false] Show all pages, one after another
+ * @cfg {string} [icon=''] Symbolic icon name
+ */
+OO.ui.StackLayout = function OoUiStackLayout( config ) {
+       // Config initialization
+       config = $.extend( { 'scrollable': true }, config );
+
+       // Parent constructor
+       OO.ui.PanelLayout.call( this, config );
+
+       // Mixin constructors
+       OO.ui.GroupElement.call( this, this.$element, config );
+
+       // Properties
+       this.currentItem = null;
+       this.continuous = !!config.continuous;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-stackLayout' );
+       if ( this.continuous ) {
+               this.$element.addClass( 'oo-ui-stackLayout-continuous' );
+       }
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.StackLayout, OO.ui.PanelLayout );
+
+OO.mixinClass( OO.ui.StackLayout, OO.ui.GroupElement );
+
+/* Events */
+
+/**
+ * @event set
+ * @param {OO.ui.PanelLayout|null} [item] Current item
+ */
+
+/* Methods */
+
+/**
+ * Add items.
+ *
+ * Adding an existing item (by value) will move it.
+ *
+ * @method
+ * @param {OO.ui.PanelLayout[]} items Items to add
+ * @param {number} [index] Index to insert items after
+ * @chainable
+ */
+OO.ui.StackLayout.prototype.addItems = function ( items, index ) {
+       OO.ui.GroupElement.prototype.addItems.call( this, items, index );
+
+       if ( !this.currentItem && items.length ) {
+               this.setItem( items[0] );
+       }
+
+       return this;
+};
+
+/**
+ * Remove items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @param {OO.ui.PanelLayout[]} items Items to remove
+ * @chainable
+ */
+OO.ui.StackLayout.prototype.removeItems = function ( items ) {
+       OO.ui.GroupElement.prototype.removeItems.call( this, items );
+       if ( items.indexOf( this.currentItem ) !== -1 ) {
+               this.currentItem = null;
+               if ( !this.currentItem && this.items.length ) {
+                       this.setItem( this.items[0] );
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Clear all items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.StackLayout.prototype.clearItems = function () {
+       this.currentItem = null;
+       OO.ui.GroupElement.prototype.clearItems.call( this );
+
+       return this;
+};
+
+/**
+ * Show item.
+ *
+ * Any currently shown item will be hidden.
+ *
+ * @method
+ * @param {OO.ui.PanelLayout} item Item to show
+ * @chainable
+ */
+OO.ui.StackLayout.prototype.setItem = function ( item ) {
+       if ( !this.continuous ) {
+               this.$items.css( 'display', '' );
+       }
+       if ( this.items.indexOf( item ) !== -1 ) {
+               if ( !this.continuous ) {
+                       item.$element.css( 'display', 'block' );
+               }
+       } else {
+               item = null;
+       }
+       this.currentItem = item;
+       this.emit( 'set', item );
+
+       return this;
+};
+/**
+ * Horizontal bar layout of tools as icon buttons.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.ToolGroup
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.BarToolGroup = function OoUiBarToolGroup( toolbar, config ) {
+       // Parent constructor
+       OO.ui.ToolGroup.call( this, toolbar, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-barToolGroup' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.BarToolGroup, OO.ui.ToolGroup );
+
+/* Static Properties */
+
+OO.ui.BarToolGroup.static.titleTooltips = true;
+
+OO.ui.BarToolGroup.static.accelTooltips = true;
+/**
+ * Popup list of tools with an icon and optional label.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.ToolGroup
+ * @mixins OO.ui.IconedElement
+ * @mixins OO.ui.IndicatedElement
+ * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.TitledElement
+ * @mixins OO.ui.ClippableElement
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.ToolGroup.call( this, toolbar, config );
+
+       // Mixin constructors
+       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
+       OO.ui.TitledElement.call( this, this.$element, config );
+       OO.ui.ClippableElement.call( this, this.$group );
+
+       // Properties
+       this.active = false;
+       this.dragging = false;
+       this.onBlurHandler = OO.ui.bind( this.onBlur, this );
+       this.$handle = this.$( '<span>' );
+
+       // Events
+       this.$handle.on( {
+               'mousedown': OO.ui.bind( this.onHandleMouseDown, this ),
+               'mouseup': OO.ui.bind( this.onHandleMouseUp, this )
+       } );
+
+       // Initialization
+       this.$handle
+               .addClass( 'oo-ui-popupToolGroup-handle' )
+               .append( this.$icon, this.$label, this.$indicator );
+       this.$element
+               .addClass( 'oo-ui-popupToolGroup' )
+               .prepend( this.$handle );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.PopupToolGroup, OO.ui.ToolGroup );
+
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IconedElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IndicatedElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.TitledElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.ClippableElement );
+
+/* Static Properties */
+
+/* Methods */
+
+/**
+ * Handle focus being lost.
+ *
+ * The event is actually generated from a mouseup, so it is not a normal blur event object.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse up event
+ */
+OO.ui.PopupToolGroup.prototype.onBlur = function ( e ) {
+       // Only deactivate when clicking outside the dropdown element
+       if ( this.$( e.target ).closest( '.oo-ui-popupToolGroup' )[0] !== this.$element[0] ) {
+               this.setActive( false );
+       }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.PopupToolGroup.prototype.onMouseUp = function ( e ) {
+       this.setActive( false );
+       return OO.ui.ToolGroup.prototype.onMouseUp.call( this, e );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.PopupToolGroup.prototype.onMouseDown = function ( e ) {
+       return OO.ui.ToolGroup.prototype.onMouseDown.call( this, e );
+};
+
+/**
+ * Handle mouse up events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse up event
+ */
+OO.ui.PopupToolGroup.prototype.onHandleMouseUp = function () {
+       return false;
+};
+
+/**
+ * Handle mouse down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.PopupToolGroup.prototype.onHandleMouseDown = function ( e ) {
+       if ( !this.disabled && e.which === 1 ) {
+               this.setActive( !this.active );
+       }
+       return false;
+};
+
+/**
+ * Switch into active mode.
+ *
+ * When active, mouseup events anywhere in the document will trigger deactivation.
+ *
+ * @method
+ */
+OO.ui.PopupToolGroup.prototype.setActive = function ( value ) {
+       value = !!value;
+       if ( this.active !== value ) {
+               this.active = value;
+               if ( value ) {
+                       this.setClipping( true );
+                       this.$element.addClass( 'oo-ui-popupToolGroup-active' );
+                       this.getElementDocument().addEventListener( 'mouseup', this.onBlurHandler, true );
+               } else {
+                       this.setClipping( false );
+                       this.$element.removeClass( 'oo-ui-popupToolGroup-active' );
+                       this.getElementDocument().removeEventListener( 'mouseup', this.onBlurHandler, true );
+               }
+       }
+};
+/**
+ * Drop down list layout of tools as labeled icon buttons.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.PopupToolGroup
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ListToolGroup = function OoUiListToolGroup( toolbar, config ) {
+       // Parent constructor
+       OO.ui.PopupToolGroup.call( this, toolbar, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-listToolGroup' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.ListToolGroup, OO.ui.PopupToolGroup );
+
+/* Static Properties */
+
+OO.ui.ListToolGroup.static.accelTooltips = true;
+/**
+ * Drop down menu layout of tools as selectable menu items.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.PopupToolGroup
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.MenuToolGroup = function OoUiMenuToolGroup( toolbar, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.PopupToolGroup.call( this, toolbar, config );
+
+       // Events
+       this.toolbar.connect( this, { 'updateState': 'onUpdateState' } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-menuToolGroup' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.MenuToolGroup, OO.ui.PopupToolGroup );
+
+/* Static Properties */
+
+OO.ui.MenuToolGroup.static.accelTooltips = true;
+
+/* Methods */
+
+/**
+ * Handle the toolbar state being updated.
+ *
+ * When the state changes, the title of each active item in the menu will be joined together and
+ * used as a label for the group. The label will be empty if none of the items are active.
+ *
+ * @method
+ */
+OO.ui.MenuToolGroup.prototype.onUpdateState = function () {
+       var name,
+               labelTexts = [];
+
+       for ( name in this.tools ) {
+               if ( this.tools[name].isActive() ) {
+                       labelTexts.push( this.tools[name].getTitle() );
+               }
+       }
+
+       this.setLabel( labelTexts.join( ', ' ) );
+};
+/**
+ * UserInterface popup tool.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Tool
+ * @mixins OO.ui.PopuppableElement
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.PopupTool = function OoUiPopupTool( toolbar, config ) {
+       // Parent constructor
+       OO.ui.Tool.call( this, toolbar, config );
+
+       // Mixin constructors
+       OO.ui.PopuppableElement.call( this, config );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-popupTool' )
+               .append( this.popup.$element );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.PopupTool, OO.ui.Tool );
+
+OO.mixinClass( OO.ui.PopupTool, OO.ui.PopuppableElement );
+
+/* Methods */
+
+/**
+ * Handle the tool being selected.
+ *
+ * @inheritdoc
+ */
+OO.ui.PopupTool.prototype.onSelect = function () {
+       if ( !this.disabled ) {
+               if ( this.popup.isVisible() ) {
+                       this.hidePopup();
+               } else {
+                       this.showPopup();
+               }
+       }
+       this.setActive( false );
+       return false;
+};
+
+/**
+ * Handle the toolbar state being updated.
+ *
+ * @inheritdoc
+ */
+OO.ui.PopupTool.prototype.onUpdateState = function () {
+       this.setActive( false );
+};
+/**
+ * Container for multiple related buttons.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixin OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ButtonGroupWidget = function OoUiButtonGroupWidget( config ) {
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.GroupElement.call( this, this.$element, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-buttonGroupWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.ButtonGroupWidget, OO.ui.Widget );
+
+OO.mixinClass( OO.ui.ButtonGroupWidget, OO.ui.GroupElement );
+/**
+ * Creates an OO.ui.ButtonWidget object.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.ButtonedElement
+ * @mixins OO.ui.IconedElement
+ * @mixins OO.ui.IndicatedElement
+ * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.TitledElement
+ * @mixins OO.ui.FlaggableElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [title=''] Title text
+ * @cfg {string} [href] Hyperlink to visit when clicked
+ * @cfg {string} [target] Target to open hyperlink in
+ */
+OO.ui.ButtonWidget = function OoUiButtonWidget( config ) {
+       // Configuration initialization
+       config = $.extend( { 'target': '_blank' }, config );
+
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.ButtonedElement.call( this, this.$( '<a>' ), config );
+       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
+       OO.ui.TitledElement.call( this, this.$button, config );
+       OO.ui.FlaggableElement.call( this, config );
+
+       // Properties
+       this.isHyperlink = typeof config.href === 'string';
+
+       // Events
+       this.$button.on( {
+               'click': OO.ui.bind( this.onClick, this ),
+               'keypress': OO.ui.bind( this.onKeyPress, this )
+       } );
+
+       // Initialization
+       this.$button
+               .append( this.$icon, this.$label, this.$indicator )
+               .attr( { 'href': config.href, 'target': config.target } );
+       this.$element
+               .addClass( 'oo-ui-buttonWidget' )
+               .append( this.$button );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.ButtonWidget, OO.ui.Widget );
+
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.ButtonedElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IconedElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IndicatedElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.TitledElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.FlaggableElement );
+
+/* Events */
+
+/**
+ * @event click
+ */
+
+/* Methods */
+
+/**
+ * Handles mouse click events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse click event
+ * @fires click
+ */
+OO.ui.ButtonWidget.prototype.onClick = function () {
+       if ( !this.disabled ) {
+               this.emit( 'click' );
+               if ( this.isHyperlink ) {
+                       return true;
+               }
+       }
+       return false;
+};
+
+/**
+ * Handles keypress events.
+ *
+ * @method
+ * @param {jQuery.Event} e Keypress event
+ * @fires click
+ */
+OO.ui.ButtonWidget.prototype.onKeyPress = function ( e ) {
+       if ( !this.disabled && e.which === OO.ui.Keys.SPACE ) {
+               if ( this.isHyperlink ) {
+                       this.onClick();
+                       return true;
+               }
+       }
+       return false;
+};
+/**
+ * Creates an OO.ui.InputWidget object.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [name=''] HTML input name
+ * @cfg {string} [value=''] Input value
+ * @cfg {boolean} [readOnly=false] Prevent changes
+ * @cfg {Function} [inputFilter] Filter function to apply to the input. Takes a string argument and returns a string.
+ */
+OO.ui.InputWidget = function OoUiInputWidget( config ) {
+       // Config intialization
+       config = $.extend( { 'readOnly': false }, config );
+
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Properties
+       this.$input = this.getInputElement( config );
+       this.value = '';
+       this.readOnly = false;
+       this.inputFilter = config.inputFilter;
+
+       // Events
+       this.$input.on( 'keydown mouseup cut paste change input select', OO.ui.bind( this.onEdit, this ) );
+
+       // Initialization
+       this.$input
+               .attr( 'name', config.name )
+               .prop( 'disabled', this.disabled );
+       this.setReadOnly( config.readOnly );
+       this.$element.addClass( 'oo-ui-inputWidget' ).append( this.$input );
+       this.setValue( config.value );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.InputWidget, OO.ui.Widget );
+
+/* Events */
+
+/**
+ * @event change
+ * @param value
+ */
+
+/* Methods */
+
+/**
+ * Get input element.
+ *
+ * @method
+ * @param {Object} [config] Configuration options
+ * @returns {jQuery} Input element
+ */
+OO.ui.InputWidget.prototype.getInputElement = function () {
+       return this.$( '<input>' );
+};
+
+/**
+ * Handle potentially value-changing events.
+ *
+ * @method
+ * @param {jQuery.Event} e Key down, mouse up, cut, paste, change, input, or select event
+ */
+OO.ui.InputWidget.prototype.onEdit = function () {
+       if ( !this.disabled ) {
+               // Allow the stack to clear so the value will be updated
+               setTimeout( OO.ui.bind( function () {
+                       this.setValue( this.$input.val() );
+               }, this ) );
+       }
+};
+
+/**
+ * Get the value of the input.
+ *
+ * @method
+ * @returns {string} Input value
+ */
+OO.ui.InputWidget.prototype.getValue = function () {
+       return this.value;
+};
+
+/**
+ * Sets the direction of the current input, either RTL or LTR
+ *
+ * @method
+ * @param {boolean} isRTL
+ */
+OO.ui.InputWidget.prototype.setRTL = function ( isRTL ) {
+       if ( isRTL ) {
+               this.$input.removeClass( 'oo-ui-ltr' );
+               this.$input.addClass( 'oo-ui-rtl' );
+       } else {
+               this.$input.removeClass( 'oo-ui-rtl' );
+               this.$input.addClass( 'oo-ui-ltr' );
+       }
+};
+
+/**
+ * Set the value of the input.
+ *
+ * @method
+ * @param {string} value New value
+ * @fires change
+ * @chainable
+ */
+OO.ui.InputWidget.prototype.setValue = function ( value ) {
+       value = this.sanitizeValue( value );
+       if ( this.value !== value ) {
+               this.value = value;
+               this.emit( 'change', this.value );
+       }
+       // Update the DOM if it has changed. Note that with sanitizeValue, it
+       // is possible for the DOM value to change without this.value changing.
+       if ( this.$input.val() !== this.value ) {
+               this.$input.val( this.value );
+       }
+       return this;
+};
+
+/**
+ * Sanitize incoming value.
+ *
+ * Ensures value is a string, and converts undefined and null to empty strings.
+ *
+ * @method
+ * @param {string} value Original value
+ * @returns {string} Sanitized value
+ */
+OO.ui.InputWidget.prototype.sanitizeValue = function ( value ) {
+       if ( value === undefined || value === null ) {
+               return '';
+       } else if ( this.inputFilter ) {
+               return this.inputFilter( String( value ) );
+       } else {
+               return String( value );
+       }
+};
+
+/**
+ * Check if the widget is read-only.
+ *
+ * @method
+ * @param {boolean} Input is read-only
+ */
+OO.ui.InputWidget.prototype.isReadOnly = function () {
+       return this.readOnly;
+};
+
+/**
+ * Set the read-only state of the widget.
+ *
+ * This should probably change the widgets's appearance and prevent it from being used.
+ *
+ * @method
+ * @param {boolean} state Make input read-only
+ * @chainable
+ */
+OO.ui.InputWidget.prototype.setReadOnly = function ( state ) {
+       this.readOnly = !!state;
+       this.$input.prop( 'readonly', this.readOnly );
+       return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.InputWidget.prototype.setDisabled = function ( state ) {
+       OO.ui.Widget.prototype.setDisabled.call( this, state );
+       if ( this.$input ) {
+               this.$input.prop( 'disabled', this.disabled );
+       }
+       return this;
+};/**
+ * Creates an OO.ui.CheckboxInputWidget object.
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.CheckboxInputWidget = function OoUiCheckboxInputWidget( config ) {
+       // Parent constructor
+       OO.ui.InputWidget.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-checkboxInputWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.CheckboxInputWidget, OO.ui.InputWidget );
+
+/* Events */
+
+/* Methods */
+
+/**
+ * Get input element.
+ *
+ * @returns {jQuery} Input element
+ */
+OO.ui.CheckboxInputWidget.prototype.getInputElement = function () {
+       return this.$( '<input type="checkbox" />' );
+};
+
+/**
+ * Get checked state of the checkbox
+ *
+ * @returns {boolean} If the checkbox is checked
+ */
+OO.ui.CheckboxInputWidget.prototype.getValue = function () {
+       return this.value;
+};
+
+/**
+ * Set value
+ */
+OO.ui.CheckboxInputWidget.prototype.setValue = function ( value ) {
+       value = !!value;
+       if ( this.value !== value ) {
+               this.value = value;
+               this.$input.prop( 'checked', this.value );
+               this.emit( 'change', this.value );
+       }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxInputWidget.prototype.onEdit = function () {
+       if ( !this.disabled ) {
+               // Allow the stack to clear so the value will be updated
+               setTimeout( OO.ui.bind( function () {
+                       this.setValue( this.$input.prop( 'checked' ) );
+               }, this ) );
+       }
+};
+/**
+ * Creates an OO.ui.CheckboxWidget object.
+ *
+ * @class
+ * @extends OO.ui.CheckboxInputWidget
+ * @mixins OO.ui.LabeledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [label=''] Label
+ */
+OO.ui.CheckboxWidget = function OoUiCheckboxWidget( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.CheckboxInputWidget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.LabeledElement.call( this, this.$( '<span>' ) , config );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-checkboxWidget' )
+               .append( this.$( '<label>' ).append( this.$input, this.$label ) );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.CheckboxWidget, OO.ui.CheckboxInputWidget );
+
+OO.mixinClass( OO.ui.CheckboxWidget, OO.ui.LabeledElement );
+/**
+ * Creates an OO.ui.InputLabelWidget object.
+ *
+ * CSS classes will be added to the button for each flag, each prefixed with 'oo-ui-InputLabelWidget-'
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.LabeledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.InputWidget|null} [input] Related input widget
+ */
+OO.ui.InputLabelWidget = function OoUiInputLabelWidget( config ) {
+       // Config intialization
+       config = $.extend( { 'input': null }, config );
+
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.LabeledElement.call( this, this.$element, config );
+
+       // Properties
+       this.input = config.input;
+
+       // Events
+       this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-inputLabelWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.InputLabelWidget, OO.ui.Widget );
+
+OO.mixinClass( OO.ui.InputLabelWidget, OO.ui.LabeledElement );
+
+/* Static Properties */
+
+OO.ui.InputLabelWidget.static.tagName = 'label';
+
+/* Methods */
+
+/**
+ * Handles mouse click events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse click event
+ */
+OO.ui.InputLabelWidget.prototype.onClick = function () {
+       if ( !this.disabled && this.input ) {
+               this.input.$input.focus();
+       }
+       return false;
+};
+/**
+ * Lookup input widget.
+ *
+ * Mixin that adds a menu showing suggested values to a text input. Subclasses must handle `select`
+ * events on #lookupMenu to make use of selections.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {OO.ui.TextInputWidget} input Input widget
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$overlay=this.$( 'body' )] Overlay layer
+ */
+OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Properties
+       this.lookupInput = input;
+       this.$overlay = config.$overlay || this.$( 'body,.oo-ui-window-overlay' ).last();
+       this.lookupMenu = new OO.ui.TextInputMenuWidget( this, {
+               '$': OO.ui.Element.getJQuery( this.$overlay ),
+               'input': this.lookupInput,
+               '$container': config.$container
+       } );
+       this.lookupCache = {};
+       this.lookupQuery = null;
+       this.lookupRequest = null;
+       this.populating = false;
+
+       // Events
+       this.$overlay.append( this.lookupMenu.$element );
+
+       this.lookupInput.$input.on( {
+               'focus': OO.ui.bind( this.onLookupInputFocus, this ),
+               'blur': OO.ui.bind( this.onLookupInputBlur, this ),
+               'mousedown': OO.ui.bind( this.onLookupInputMouseDown, this )
+       } );
+       this.lookupInput.connect( this, { 'change': 'onLookupInputChange' } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-lookupWidget' );
+       this.lookupMenu.$element.addClass( 'oo-ui-lookupWidget-menu' );
+};
+
+/* Methods */
+
+/**
+ * Handle input focus event.
+ *
+ * @method
+ * @param {jQuery.Event} e Input focus event
+ */
+OO.ui.LookupInputWidget.prototype.onLookupInputFocus = function () {
+       this.openLookupMenu();
+};
+
+/**
+ * Handle input blur event.
+ *
+ * @method
+ * @param {jQuery.Event} e Input blur event
+ */
+OO.ui.LookupInputWidget.prototype.onLookupInputBlur = function () {
+       this.lookupMenu.hide();
+};
+
+/**
+ * Handle input mouse down event.
+ *
+ * @method
+ * @param {jQuery.Event} e Input mouse down event
+ */
+OO.ui.LookupInputWidget.prototype.onLookupInputMouseDown = function () {
+       this.openLookupMenu();
+};
+
+/**
+ * Handle input change event.
+ *
+ * @method
+ * @param {string} value New input value
+ */
+OO.ui.LookupInputWidget.prototype.onLookupInputChange = function () {
+       this.openLookupMenu();
+};
+
+/**
+ * Open the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.LookupInputWidget.prototype.openLookupMenu = function () {
+       var value = this.lookupInput.getValue();
+
+       if ( this.lookupMenu.$input.is( ':focus' ) && $.trim( value ) !== '' ) {
+               this.populateLookupMenu();
+               if ( !this.lookupMenu.isVisible() ) {
+                       this.lookupMenu.show();
+               }
+       } else {
+               this.lookupMenu.clearItems();
+               this.lookupMenu.hide();
+       }
+
+       return this;
+};
+
+/**
+ * Populate lookup menu with current information.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.LookupInputWidget.prototype.populateLookupMenu = function () {
+       if ( !this.populating ) {
+               this.populating = true;
+               this.getLookupMenuItems()
+                       .done( OO.ui.bind( function ( items ) {
+                               this.lookupMenu.clearItems();
+                               if ( items.length ) {
+                                       this.lookupMenu.show();
+                                       this.lookupMenu.addItems( items );
+                                       this.initializeLookupMenuSelection();
+                                       this.openLookupMenu();
+                               } else {
+                                       this.lookupMenu.hide();
+                               }
+                               this.populating = false;
+                       }, this ) )
+                       .fail( OO.ui.bind( function () {
+                               this.lookupMenu.clearItems();
+                               this.populating = false;
+                       }, this ) );
+       }
+
+       return this;
+};
+
+/**
+ * Set selection in the lookup menu with current information.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.LookupInputWidget.prototype.initializeLookupMenuSelection = function () {
+       if ( !this.lookupMenu.getSelectedItem() ) {
+               this.lookupMenu.intializeSelection( this.lookupMenu.getFirstSelectableItem() );
+       }
+       this.lookupMenu.highlightItem( this.lookupMenu.getSelectedItem() );
+};
+
+/**
+ * Get lookup menu items for the current query.
+ *
+ * @method
+ * @returns {jQuery.Promise} Promise object which will be passed menu items as the first argument
+ * of the done event
+ */
+OO.ui.LookupInputWidget.prototype.getLookupMenuItems = function () {
+       var value = this.lookupInput.getValue(),
+               deferred = $.Deferred();
+
+       if ( value && value !== this.lookupQuery ) {
+               // Abort current request if query has changed
+               if ( this.lookupRequest ) {
+                       this.lookupRequest.abort();
+                       this.lookupQuery = null;
+                       this.lookupRequest = null;
+               }
+               if ( value in this.lookupCache ) {
+                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
+               } else {
+                       this.lookupQuery = value;
+                       this.lookupRequest = this.getLookupRequest()
+                               .always( OO.ui.bind( function () {
+                                       this.lookupQuery = null;
+                                       this.lookupRequest = null;
+                               }, this ) )
+                               .done( OO.ui.bind( function ( data ) {
+                                       this.lookupCache[value] = this.getLookupCacheItemFromData( data );
+                                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
+                               }, this ) )
+                               .fail( function () {
+                                       deferred.reject();
+                               } );
+                       this.pushPending();
+                       this.lookupRequest.always( OO.ui.bind( function () {
+                               this.popPending();
+                       }, this ) );
+               }
+       }
+       return deferred.promise();
+};
+
+/**
+ * Get a new request object of the current lookup query value.
+ *
+ * @method
+ * @abstract
+ * @returns {jqXHR} jQuery AJAX object, or promise object with an .abort() method
+ */
+OO.ui.LookupInputWidget.prototype.getLookupRequest = function () {
+       // Stub, implemented in subclass
+       return null;
+};
+
+/**
+ * Handle successful lookup request.
+ *
+ * Overriding methods should call #populateLookupMenu when results are available and cache results
+ * for future lookups in #lookupCache as an array of #OO.ui.MenuItemWidget objects.
+ *
+ * @method
+ * @abstract
+ * @param {Mixed} data Response from server
+ */
+OO.ui.LookupInputWidget.prototype.onLookupRequestDone = function () {
+       // Stub, implemented in subclass
+};
+
+/**
+ * Get a list of menu item widgets from the data stored by the lookup request's done handler.
+ *
+ * @method
+ * @abstract
+ * @param {Mixed} data Cached result data, usually an array
+ * @returns {OO.ui.MenuItemWidget[]} Menu items
+ */
+OO.ui.LookupInputWidget.prototype.getLookupMenuItemsFromData = function () {
+       // Stub, implemented in subclass
+       return [];
+};
+/**
+ * Creates an OO.ui.OptionWidget object.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.IconedElement
+ * @mixins OO.ui.LabeledElement
+ * @mixins OO.ui.IndicatedElement
+ *
+ * @constructor
+ * @param {Mixed} data Option data
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [selected=false] Select option
+ * @cfg {boolean} [highlighted=false] Highlight option
+ * @cfg {string} [rel] Value for `rel` attribute in DOM, allowing per-option styling
+ */
+OO.ui.OptionWidget = function OoUiOptionWidget( data, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
+       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
+       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
+
+       // Properties
+       this.data = data;
+       this.selected = false;
+       this.highlighted = false;
+
+       // Initialization
+       this.$element
+               .data( 'oo-ui-optionWidget', this )
+               .attr( 'rel', config.rel )
+               .addClass( 'oo-ui-optionWidget' )
+               .append( this.$label );
+       this.setSelected( config.selected );
+       this.setHighlighted( config.highlighted );
+
+       // Options
+       this.$element
+               .prepend( this.$icon )
+               .append( this.$indicator );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.OptionWidget, OO.ui.Widget );
+
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.IconedElement );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.LabeledElement );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.IndicatedElement );
+
+/* Static Properties */
+
+OO.ui.OptionWidget.static.tagName = 'li';
+
+OO.ui.OptionWidget.static.selectable = true;
+
+OO.ui.OptionWidget.static.highlightable = true;
+
+OO.ui.OptionWidget.static.scrollIntoViewOnSelect = false;
+
+/* Methods */
+
+/**
+ * Check if option can be selected.
+ *
+ * @method
+ * @returns {boolean} Item is selectable
+ */
+OO.ui.OptionWidget.prototype.isSelectable = function () {
+       return this.constructor.static.selectable && !this.disabled;
+};
+
+/**
+ * Check if option can be highlighted.
+ *
+ * @method
+ * @returns {boolean} Item is highlightable
+ */
+OO.ui.OptionWidget.prototype.isHighlightable = function () {
+       return this.constructor.static.highlightable && !this.disabled;
+};
+
+/**
+ * Check if option is selected.
+ *
+ * @method
+ * @returns {boolean} Item is selected
+ */
+OO.ui.OptionWidget.prototype.isSelected = function () {
+       return this.selected;
+};
+
+/**
+ * Check if option is highlighted.
+ *
+ * @method
+ * @returns {boolean} Item is highlighted
+ */
+OO.ui.OptionWidget.prototype.isHighlighted = function () {
+       return this.highlighted;
+};
+
+/**
+ * Set selected state.
+ *
+ * @method
+ * @param {boolean} [state=false] Select option
+ * @chainable
+ */
+OO.ui.OptionWidget.prototype.setSelected = function ( state ) {
+       if ( !this.disabled && this.constructor.static.selectable ) {
+               this.selected = !!state;
+               if ( this.selected ) {
+                       this.$element.addClass( 'oo-ui-optionWidget-selected' );
+                       if ( this.constructor.static.scrollIntoViewOnSelect ) {
+                               this.scrollElementIntoView();
+                       }
+               } else {
+                       this.$element.removeClass( 'oo-ui-optionWidget-selected' );
+               }
+       }
+       return this;
+};
+
+/**
+ * Set highlighted state.
+ *
+ * @method
+ * @param {boolean} [state=false] Highlight option
+ * @chainable
+ */
+OO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {
+       if ( !this.disabled && this.constructor.static.highlightable ) {
+               this.highlighted = !!state;
+               if ( this.highlighted ) {
+                       this.$element.addClass( 'oo-ui-optionWidget-highlighted' );
+               } else {
+                       this.$element.removeClass( 'oo-ui-optionWidget-highlighted' );
+               }
+       }
+       return this;
+};
+
+/**
+ * Make the option's highlight flash.
+ *
+ * @method
+ * @param {Function} [done] Callback to execute when flash effect is complete.
+ */
+OO.ui.OptionWidget.prototype.flash = function ( done ) {
+       var $this = this.$element;
+
+       if ( !this.disabled && this.constructor.static.highlightable ) {
+               $this.removeClass( 'oo-ui-optionWidget-highlighted' );
+               setTimeout( OO.ui.bind( function () {
+                       $this.addClass( 'oo-ui-optionWidget-highlighted' );
+                       if ( done ) {
+                               setTimeout( done, 100 );
+                       }
+               }, this ), 100 );
+       }
+};
+
+/**
+ * Get option data.
+ *
+ * @method
+ * @returns {Mixed} Option data
+ */
+OO.ui.OptionWidget.prototype.getData = function () {
+       return this.data;
+};
+/**
+ * Create an OO.ui.SelectWidget object.
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixin OO.ui.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.SelectWidget = function OoUiSelectWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.GroupElement.call( this, this.$element, config );
+
+       // Properties
+       this.pressed = false;
+       this.selecting = null;
+       this.hashes = {};
+
+       // Events
+       this.$element.on( {
+               'mousedown': OO.ui.bind( this.onMouseDown, this ),
+               'mouseup': OO.ui.bind( this.onMouseUp, this ),
+               'mousemove': OO.ui.bind( this.onMouseMove, this ),
+               'mouseover': OO.ui.bind( this.onMouseOver, this ),
+               'mouseleave': OO.ui.bind( this.onMouseLeave, this )
+       } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-selectWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.SelectWidget, OO.ui.Widget );
+
+OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupElement );
+
+/* Events */
+
+/**
+ * @event highlight
+ * @param {OO.ui.OptionWidget|null} item Highlighted item
+ */
+
+/**
+ * @event select
+ * @param {OO.ui.OptionWidget|null} item Selected item
+ */
+
+/**
+ * @event add
+ * @param {OO.ui.OptionWidget[]} items Added items
+ * @param {number} index Index items were added at
+ */
+
+/**
+ * @event remove
+ * @param {OO.ui.OptionWidget[]} items Removed items
+ */
+
+/* Static Properties */
+
+OO.ui.SelectWidget.static.tagName = 'ul';
+
+/* Methods */
+
+/**
+ * Handle mouse down events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.SelectWidget.prototype.onMouseDown = function ( e ) {
+       var item;
+
+       if ( !this.disabled && e.which === 1 ) {
+               this.pressed = true;
+               item = this.getTargetItem( e );
+               if ( item && item.isSelectable() ) {
+                       this.intializeSelection( item );
+                       this.selecting = item;
+                       this.$( this.$.context ).one( 'mouseup', OO.ui.bind( this.onMouseUp, this ) );
+               }
+       }
+       return false;
+};
+
+/**
+ * Handle mouse up events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse up event
+ */
+OO.ui.SelectWidget.prototype.onMouseUp = function ( e ) {
+       var item;
+       this.pressed = false;
+       if ( !this.selecting ) {
+               item = this.getTargetItem( e );
+               if ( item && item.isSelectable() ) {
+                       this.selecting = item;
+               }
+       }
+       if ( !this.disabled && e.which === 1 && this.selecting ) {
+               this.selectItem( this.selecting );
+               this.selecting = null;
+       }
+       return false;
+};
+
+/**
+ * Handle mouse move events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse move event
+ */
+OO.ui.SelectWidget.prototype.onMouseMove = function ( e ) {
+       var item;
+
+       if ( !this.disabled && this.pressed ) {
+               item = this.getTargetItem( e );
+               if ( item && item !== this.selecting && item.isSelectable() ) {
+                       this.intializeSelection( item );
+                       this.selecting = item;
+               }
+       }
+       return false;
+};
+
+/**
+ * Handle mouse over events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse over event
+ */
+OO.ui.SelectWidget.prototype.onMouseOver = function ( e ) {
+       var item;
+
+       if ( !this.disabled ) {
+               item = this.getTargetItem( e );
+               if ( item && item.isHighlightable() ) {
+                       this.highlightItem( item );
+               }
+       }
+       return false;
+};
+
+/**
+ * Handle mouse leave events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse over event
+ */
+OO.ui.SelectWidget.prototype.onMouseLeave = function () {
+       if ( !this.disabled ) {
+               this.highlightItem();
+       }
+       return false;
+};
+
+/**
+ * Get the closest item to a jQuery.Event.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e
+ * @returns {OO.ui.OptionWidget|null} Outline item widget, `null` if none was found
+ */
+OO.ui.SelectWidget.prototype.getTargetItem = function ( e ) {
+       var $item = this.$( e.target ).closest( '.oo-ui-optionWidget' );
+       if ( $item.length ) {
+               return $item.data( 'oo-ui-optionWidget' );
+       }
+       return null;
+};
+
+/**
+ * Get selected item.
+ *
+ * @method
+ * @returns {OO.ui.OptionWidget|null} Selected item, `null` if no item is selected
+ */
+OO.ui.SelectWidget.prototype.getSelectedItem = function () {
+       var i, len;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               if ( this.items[i].isSelected() ) {
+                       return this.items[i];
+               }
+       }
+       return null;
+};
+
+/**
+ * Get highlighted item.
+ *
+ * @method
+ * @returns {OO.ui.OptionWidget|null} Highlighted item, `null` if no item is highlighted
+ */
+OO.ui.SelectWidget.prototype.getHighlightedItem = function () {
+       var i, len;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               if ( this.items[i].isHighlighted() ) {
+                       return this.items[i];
+               }
+       }
+       return null;
+};
+
+/**
+ * Get an existing item with equivilant data.
+ *
+ * @method
+ * @param {Object} data Item data to search for
+ * @returns {OO.ui.OptionWidget|null} Item with equivilent value, `null` if none exists
+ */
+OO.ui.SelectWidget.prototype.getItemFromData = function ( data ) {
+       var hash = OO.getHash( data );
+
+       if ( hash in this.hashes ) {
+               return this.hashes[hash];
+       }
+
+       return null;
+};
+
+/**
+ * Highlight an item.
+ *
+ * Highlighting is mutually exclusive.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} [item] Item to highlight, omit to deselect all
+ * @fires highlight
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.highlightItem = function ( item ) {
+       var i, len;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               this.items[i].setHighlighted( this.items[i] === item );
+       }
+       this.emit( 'highlight', item );
+
+       return this;
+};
+
+/**
+ * Select an item.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
+ * @fires select
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.selectItem = function ( item ) {
+       var i, len;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               this.items[i].setSelected( this.items[i] === item );
+       }
+       this.emit( 'select', item );
+
+       return this;
+};
+
+/**
+ * Setup selection and highlighting.
+ *
+ * This should be used to synchronize the UI with the model without emitting events that would in
+ * turn update the model.
+ *
+ * @param {OO.ui.OptionWidget} [item] Item to select
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.intializeSelection = function( item ) {
+       var i, len, selected;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               selected = this.items[i] === item;
+               this.items[i].setSelected( selected );
+               this.items[i].setHighlighted( selected );
+       }
+
+       return this;
+};
+
+/**
+ * Get an item relative to another one.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} item Item to start at
+ * @param {number} direction Direction to move in
+ * @returns {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the menu
+ */
+OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direction ) {
+       var inc = direction > 0 ? 1 : -1,
+               len = this.items.length,
+               index = item instanceof OO.ui.OptionWidget ?
+                       this.items.indexOf( item ) : ( inc > 0 ? -1 : 0 ),
+               stopAt = Math.max( Math.min( index, len - 1 ), 0 ),
+               i = inc > 0 ?
+                       // Default to 0 instead of -1, if nothing is selected let's start at the beginning
+                       Math.max( index, -1 ) :
+                       // Default to n-1 instead of -1, if nothing is selected let's start at the end
+                       Math.min( index, len );
+
+       while ( true ) {
+               i = ( i + inc + len ) % len;
+               item = this.items[i];
+               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
+                       return item;
+               }
+               // Stop iterating when we've looped all the way around
+               if ( i === stopAt ) {
+                       break;
+               }
+       }
+       return null;
+};
+
+/**
+ * Get the next selectable item.
+ *
+ * @method
+ * @returns {OO.ui.OptionWidget|null} Item, `null` if ther aren't any selectable items
+ */
+OO.ui.SelectWidget.prototype.getFirstSelectableItem = function () {
+       var i, len, item;
+
+       for ( i = 0, len = this.items.length; i < len; i++ ) {
+               item = this.items[i];
+               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
+                       return item;
+               }
+       }
+
+       return null;
+};
+
+/**
+ * Add items.
+ *
+ * When items are added with the same values as existing items, the existing items will be
+ * automatically removed before the new items are added.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget[]} items Items to add
+ * @param {number} [index] Index to insert items after
+ * @fires add
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.addItems = function ( items, index ) {
+       var i, len, item, hash,
+               remove = [];
+
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               hash = OO.getHash( item.getData() );
+               if ( hash in this.hashes ) {
+                       // Remove item with same value
+                       remove.push( this.hashes[hash] );
+               }
+               this.hashes[hash] = item;
+       }
+       if ( remove.length ) {
+               this.removeItems( remove );
+       }
+
+       OO.ui.GroupElement.prototype.addItems.call( this, items, index );
+
+       // Always provide an index, even if it was omitted
+       this.emit( 'add', items, index === undefined ? this.items.length - items.length - 1 : index );
+
+       return this;
+};
+
+/**
+ * Remove items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget[]} items Items to remove
+ * @fires remove
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.removeItems = function ( items ) {
+       var i, len, item, hash;
+
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               hash = OO.getHash( item.getData() );
+               if ( hash in this.hashes ) {
+                       // Remove existing item
+                       delete this.hashes[hash];
+               }
+               if ( item.isSelected() ) {
+                       this.selectItem( null );
+               }
+       }
+       OO.ui.GroupElement.prototype.removeItems.call( this, items );
+
+       this.emit( 'remove', items );
+
+       return this;
+};
+
+/**
+ * Clear all items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @fires remove
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.clearItems = function () {
+       var items = this.items.slice();
+
+       // Clear all items
+       this.hashes = {};
+       OO.ui.GroupElement.prototype.clearItems.call( this );
+       this.selectItem( null );
+
+       this.emit( 'remove', items );
+
+       return this;
+};
+/**
+ * Creates an OO.ui.MenuItemWidget object.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ *
+ * @constructor
+ * @param {Mixed} data Item data
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.MenuItemWidget = function OoUiMenuItemWidget( data, config ) {
+       // Configuration initialization
+       config = $.extend( { 'icon': 'check' }, config );
+
+       // Parent constructor
+       OO.ui.OptionWidget.call( this, data, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-menuItemWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.MenuItemWidget, OO.ui.OptionWidget );
+/**
+ * Create an OO.ui.MenuWidget object.
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ * @mixins OO.ui.ClippableElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.InputWidget} [input] Input to bind keyboard handlers to
+ */
+OO.ui.MenuWidget = function OoUiMenuWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.SelectWidget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.ClippableElement.call( this, this.$group );
+
+       // Properties
+       this.newItems = [];
+       this.$input = config.input ? config.input.$input : null;
+       this.$previousFocus = null;
+       this.isolated = !config.input;
+       this.visible = false;
+       this.onKeyDownHandler = OO.ui.bind( this.onKeyDown, this );
+
+       // Initialization
+       this.$element.hide().addClass( 'oo-ui-menuWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.MenuWidget, OO.ui.SelectWidget );
+
+OO.mixinClass( OO.ui.MenuWidget, OO.ui.ClippableElement );
+
+/* Methods */
+
+/**
+ * Handles key down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.MenuWidget.prototype.onKeyDown = function ( e ) {
+       var nextItem,
+               handled = false,
+               highlightItem = this.getHighlightedItem();
+
+       if ( !this.disabled && this.visible ) {
+               if ( !highlightItem ) {
+                       highlightItem = this.getSelectedItem();
+               }
+               switch ( e.keyCode ) {
+                       case OO.ui.Keys.ENTER:
+                               this.selectItem( highlightItem );
+                               handled = true;
+                               break;
+                       case OO.ui.Keys.UP:
+                               nextItem = this.getRelativeSelectableItem( highlightItem, -1 );
+                               handled = true;
+                               break;
+                       case OO.ui.Keys.DOWN:
+                               nextItem = this.getRelativeSelectableItem( highlightItem, 1 );
+                               handled = true;
+                               break;
+                       case OO.ui.Keys.ESCAPE:
+                               if ( highlightItem ) {
+                                       highlightItem.setHighlighted( false );
+                               }
+                               this.hide();
+                               handled = true;
+                               break;
+               }
+
+               if ( nextItem ) {
+                       this.highlightItem( nextItem );
+                       nextItem.scrollElementIntoView();
+               }
+
+               if ( handled ) {
+                       e.preventDefault();
+                       e.stopPropagation();
+                       return false;
+               }
+       }
+};
+
+/**
+ * Check if the menu is visible.
+ *
+ * @method
+ * @returns {boolean} Menu is visible
+ */
+OO.ui.MenuWidget.prototype.isVisible = function () {
+       return this.visible;
+};
+
+/**
+ * Bind key down listener
+ *
+ * @method
+ */
+OO.ui.MenuWidget.prototype.bindKeyDownListener = function () {
+       if ( this.$input ) {
+               this.$input.on( 'keydown', this.onKeyDownHandler );
+       } else {
+               // Capture menu navigation keys
+               this.getElementWindow().addEventListener( 'keydown', this.onKeyDownHandler, true );
+       }
+};
+
+/**
+ * Unbind key down listener
+ *
+ * @method
+ */
+OO.ui.MenuWidget.prototype.unbindKeyDownListener = function () {
+       if ( this.$input ) {
+               this.$input.off( 'keydown' );
+       } else {
+               this.getElementWindow().removeEventListener( 'keydown', this.onKeyDownHandler, true );
+       }
+};
+
+/**
+ * Select an item.
+ *
+ * The menu will stay open if an item is silently selected.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
+ * @chainable
+ */
+OO.ui.MenuWidget.prototype.selectItem = function ( item ) {
+       // Parent method
+       OO.ui.SelectWidget.prototype.selectItem.call( this, item );
+
+       if ( !this.disabled ) {
+               if ( item ) {
+                       this.disabled = true;
+                       item.flash( OO.ui.bind( function () {
+                               this.hide();
+                               this.disabled = false;
+                       }, this ) );
+               } else {
+                       this.hide();
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Add items.
+ *
+ * Adding an existing item (by value) will move it.
+ *
+ * @method
+ * @param {OO.ui.MenuItemWidget[]} items Items to add
+ * @param {number} [index] Index to insert items after
+ * @chainable
+ */
+OO.ui.MenuWidget.prototype.addItems = function ( items, index ) {
+       var i, len, item;
+
+       // Parent method
+       OO.ui.SelectWidget.prototype.addItems.call( this, items, index );
+
+       for ( i = 0, len = items.length; i < len; i++ ) {
+               item = items[i];
+               if ( this.visible ) {
+                       // Defer fitting label until
+                       item.fitLabel();
+               } else {
+                       this.newItems.push( item );
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Show the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.MenuWidget.prototype.show = function () {
+       var i, len;
+
+       if ( this.items.length ) {
+               this.$element.show();
+               this.visible = true;
+               this.bindKeyDownListener();
+
+               // Change focus to enable keyboard navigation
+               if ( this.isolated && this.$input && !this.$input.is( ':focus' ) ) {
+                       this.$previousFocus = this.$( ':focus' );
+                       this.$input.focus();
+               }
+               if ( this.newItems.length ) {
+                       for ( i = 0, len = this.newItems.length; i < len; i++ ) {
+                               this.newItems[i].fitLabel();
+                       }
+                       this.newItems = [];
+               }
+
+               this.setClipping( true );
+       }
+
+       return this;
+};
+
+/**
+ * Hide the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.MenuWidget.prototype.hide = function () {
+       this.$element.hide();
+       this.visible = false;
+       this.unbindKeyDownListener();
+
+       if ( this.isolated && this.$previousFocus ) {
+               this.$previousFocus.focus();
+               this.$previousFocus = null;
+       }
+
+       this.setClipping( false );
+
+       return this;
+};
+/**
+ * Creates an OO.ui.MenuSectionItemWidget object.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ *
+ * @constructor
+ * @param {Mixed} data Item data
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.MenuSectionItemWidget = function OoUiMenuSectionItemWidget( data, config ) {
+       // Parent constructor
+       OO.ui.OptionWidget.call( this, data, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-menuSectionItemWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.MenuSectionItemWidget, OO.ui.OptionWidget );
+
+OO.ui.MenuSectionItemWidget.static.selectable = false;
+
+OO.ui.MenuSectionItemWidget.static.highlightable = false;
+/**
+ * Create an OO.ui.OutlineWidget object.
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.OutlineWidget = function OoUiOutlineWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.SelectWidget.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-outlineWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.OutlineWidget, OO.ui.SelectWidget );
+/**
+ * Creates an OO.ui.OutlineControlsWidget object.
+ *
+ * @class
+ *
+ * @constructor
+ * @param {OO.ui.OutlineWidget} outline Outline to control
+ * @param {Object} [config] Configuration options
+ * @cfg {Object[]} [adders] List of icons to show as addable item types, each an object with
+ *  name, title and icon properties
+ */
+OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Properties
+       this.outline = outline;
+       this.adders = {};
+       this.$adders = this.$( '<div>' );
+       this.$movers = this.$( '<div>' );
+       this.addButton = new OO.ui.ButtonWidget( {
+               '$': this.$,
+               'frameless': true,
+               'icon': 'add-item'
+       } );
+       this.upButton = new OO.ui.ButtonWidget( {
+               '$': this.$,
+               'frameless': true,
+               'icon': 'collapse',
+               'title': OO.ui.msg( 'ooui-outline-control-move-up' )
+       } );
+       this.downButton = new OO.ui.ButtonWidget( {
+               '$': this.$,
+               'frameless': true,
+               'icon': 'expand',
+               'title': OO.ui.msg( 'ooui-outline-control-move-down' )
+       } );
+
+       // Events
+       outline.connect( this, {
+               'select': 'onOutlineChange',
+               'add': 'onOutlineChange',
+               'remove': 'onOutlineChange'
+       } );
+       this.upButton.connect( this, { 'click': ['emit', 'move', -1] } );
+       this.downButton.connect( this, { 'click': ['emit', 'move', 1] } );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-outlineControlsWidget' );
+       this.$adders.addClass( 'oo-ui-outlineControlsWidget-adders' );
+       this.$movers
+               .addClass( 'oo-ui-outlineControlsWidget-movers' )
+               .append( this.upButton.$element, this.downButton.$element );
+       this.$element.append( this.$adders, this.$movers );
+       if ( config.adders && config.adders.length ) {
+               this.setupAdders( config.adders );
+       }
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );
+
+/* Events */
+
+/**
+ * @event move
+ * @param {number} places Number of places to move
+ */
+
+/* Methods */
+
+/**
+ * Handle outline change events.
+ *
+ * @method
+ */
+OO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {
+       var i, len, firstMovable, lastMovable,
+               movable = false,
+               items = this.outline.getItems(),
+               selectedItem = this.outline.getSelectedItem();
+
+       if ( selectedItem && selectedItem.isMovable() ) {
+               movable = true;
+               i = -1;
+               len = items.length;
+               while ( ++i < len ) {
+                       if ( items[i].isMovable() ) {
+                               firstMovable = items[i];
+                               break;
+                       }
+               }
+               i = len;
+               while ( i-- ) {
+                       if ( items[i].isMovable() ) {
+                               lastMovable = items[i];
+                               break;
+                       }
+               }
+       }
+       this.upButton.setDisabled( !movable || selectedItem === firstMovable );
+       this.downButton.setDisabled( !movable || selectedItem === lastMovable );
+};
+
+/**
+ * Setup adders icons.
+ *
+ * @method
+ * @param {Object[]} adders List of configuations for adder buttons, each containing a name, title
+ *  and icon property
+ */
+OO.ui.OutlineControlsWidget.prototype.setupAdders = function ( adders ) {
+       var i, len, addition, button,
+               $buttons = this.$( [] );
+
+       this.$adders.append( this.addButton.$element );
+       for ( i = 0, len = adders.length; i < len; i++ ) {
+               addition = adders[i];
+               button = new OO.ui.ButtonWidget( {
+                       '$': this.$, 'frameless': true, 'icon': addition.icon, 'title': addition.title
+               } );
+               button.connect( this, { 'click': ['emit', 'add', addition.name] } );
+               this.adders[addition.name] = button;
+               this.$adders.append( button.$element );
+               $buttons = $buttons.add( button.$element );
+       }
+};
+/**
+ * Creates an OO.ui.OutlineItemWidget object.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ *
+ * @constructor
+ * @param {Mixed} data Item data
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [level] Indentation level
+ * @cfg {boolean} [movable] Allow modification from outline controls
+ */
+OO.ui.OutlineItemWidget = function OoUiOutlineItemWidget( data, config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.OptionWidget.call( this, data, config );
+
+       // Properties
+       this.level = 0;
+       this.movable = !!config.movable;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-outlineItemWidget' );
+       this.setLevel( config.level );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.OutlineItemWidget, OO.ui.OptionWidget );
+
+/* Static Properties */
+
+OO.ui.OutlineItemWidget.static.highlightable = false;
+
+OO.ui.OutlineItemWidget.static.scrollIntoViewOnSelect = true;
+
+OO.ui.OutlineItemWidget.static.levelClass = 'oo-ui-outlineItemWidget-level-';
+
+OO.ui.OutlineItemWidget.static.levels = 3;
+
+/* Methods */
+
+/**
+ * Check if item is movable.
+ *
+ * Moveablilty is used by outline controls.
+ *
+ * @returns {boolean} Item is movable
+ */
+OO.ui.OutlineItemWidget.prototype.isMovable = function () {
+       return this.movable;
+};
+
+/**
+ * Get indentation level.
+ *
+ * @returns {number} Indentation level
+ */
+OO.ui.OutlineItemWidget.prototype.getLevel = function () {
+       return this.level;
+};
+
+/**
+ * Set indentation level.
+ *
+ * @method
+ * @param {number} [level=0] Indentation level, in the range of [0,#maxLevel]
+ * @chainable
+ */
+OO.ui.OutlineItemWidget.prototype.setLevel = function ( level ) {
+       var levels = this.constructor.static.levels,
+               levelClass = this.constructor.static.levelClass,
+               i = levels;
+
+       this.level = level ? Math.max( 0, Math.min( levels - 1, level ) ) : 0;
+       while ( i-- ) {
+               if ( this.level === i ) {
+                       this.$element.addClass( levelClass + i );
+               } else {
+                       this.$element.removeClass( levelClass + i );
+               }
+       }
+
+       return this;
+};
+/**
+ * Creates an OO.ui.BookletOutlineItemWidget object.
+ *
+ * @class
+ * @extends OO.ui.OutlineItemWidget
+ *
+ * @constructor
+ * @param {Mixed} data Item data
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.BookletOutlineItemWidget = function OoUiBookletOutlineItemWidget( data, page, config ) {
+       // Configuration intialization
+       config = $.extend( {
+               'label': page.getLabel() || data,
+               'level': page.getLevel(),
+               'icon': page.getIcon(),
+               'indicator': page.getIndicator(),
+               'indicatorTitle': page.getIndicatorTitle(),
+               'movable': page.isMovable()
+       }, config );
+
+       // Parent constructor
+       OO.ui.OutlineItemWidget.call( this, data, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-bookletOutlineItemWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.BookletOutlineItemWidget, OO.ui.OutlineItemWidget );
+/**
+ * Create an OO.ui.ButtonSelect object.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ * @mixins OO.ui.ButtonedElement
+ * @mixins OO.ui.FlaggableElement
+ *
+ * @constructor
+ * @param {Mixed} data Option data
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( data, config ) {
+       // Parent constructor
+       OO.ui.OptionWidget.call( this, data, config );
+
+       // Mixin constructors
+       OO.ui.ButtonedElement.call( this, this.$( '<a>' ), config );
+       OO.ui.FlaggableElement.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-buttonOptionWidget' );
+       this.$button.append( this.$element.contents() );
+       this.$element.append( this.$button );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.ButtonOptionWidget, OO.ui.OptionWidget );
+
+OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.ButtonedElement );
+OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.FlaggableElement );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
+       OO.ui.OptionWidget.prototype.setSelected.call( this, state );
+
+       this.setActive( state );
+
+       return this;
+};
+/**
+ * Create an OO.ui.ButtonSelect object.
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ButtonSelectWidget = function OoUiButtonSelectWidget( config ) {
+       // Parent constructor
+       OO.ui.SelectWidget.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-buttonSelectWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.ButtonSelectWidget, OO.ui.SelectWidget );
+/**
+ * Creates an OO.ui.PopupWidget object.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.LabeledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [tail=true] Show tail pointing to origin of popup
+ * @cfg {string} [align='center'] Alignment of popup to origin
+ * @cfg {jQuery} [$container] Container to prevent popup from rendering outside of
+ * @cfg {boolean} [autoClose=false] Popup auto-closes when it loses focus
+ * @cfg {jQuery} [$autoCloseIgnore] Elements to not auto close when clicked
+ * @cfg {boolean} [head] Show label and close button at the top
+ */
+OO.ui.PopupWidget = function OoUiPopupWidget( config ) {
+       // Config intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.LabeledElement.call( this, this.$( '<div>' ), config );
+
+       // Properties
+       this.visible = false;
+       this.$popup = this.$( '<div>' );
+       this.$head = this.$( '<div>' );
+       this.$body = this.$( '<div>' );
+       this.$tail = this.$( '<div>' );
+       this.$container = config.$container || this.$( 'body' );
+       this.autoClose = !!config.autoClose;
+       this.$autoCloseIgnore = config.$autoCloseIgnore;
+       this.transitionTimeout = null;
+       this.tail = false;
+       this.align = config.align || 'center';
+       this.closeButton = new OO.ui.ButtonWidget( { '$': this.$, 'frameless': true, 'icon': 'close' } );
+       this.onMouseDownHandler = OO.ui.bind( this.onMouseDown, this );
+
+       // Events
+       this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
+
+       // Initialization
+       this.useTail( config.tail !== undefined ? !!config.tail : true );
+       this.$body.addClass( 'oo-ui-popupWidget-body' );
+       this.$tail.addClass( 'oo-ui-popupWidget-tail' );
+       this.$head
+               .addClass( 'oo-ui-popupWidget-head' )
+               .append( this.$label, this.closeButton.$element );
+       if ( !config.head ) {
+               this.$head.hide();
+       }
+       this.$popup
+               .addClass( 'oo-ui-popupWidget-popup' )
+               .append( this.$head, this.$body );
+       this.$element.hide()
+               .addClass( 'oo-ui-popupWidget' )
+               .append( this.$popup, this.$tail );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.PopupWidget, OO.ui.Widget );
+
+OO.mixinClass( OO.ui.PopupWidget, OO.ui.LabeledElement );
+
+/* Events */
+
+/**
+ * @event hide
+ */
+
+/**
+ * @event show
+ */
+
+/* Methods */
+
+/**
+ * Handles mouse down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.PopupWidget.prototype.onMouseDown = function ( e ) {
+       if (
+               this.visible &&
+               !$.contains( this.$element[0], e.target ) &&
+               ( !this.$autoCloseIgnore || !this.$autoCloseIgnore.has( e.target ).length )
+       ) {
+               this.hide();
+       }
+};
+
+/**
+ * Bind mouse down listener
+ *
+ * @method
+ */
+OO.ui.PopupWidget.prototype.bindMouseDownListener = function () {
+       // Capture clicks outside popup
+       this.getElementWindow().addEventListener( 'mousedown', this.onMouseDownHandler, true );
+};
+
+/**
+ * Handles close button click events.
+ *
+ * @method
+ */
+OO.ui.PopupWidget.prototype.onCloseButtonClick = function () {
+       if ( this.visible ) {
+               this.hide();
+       }
+};
+
+/**
+ * Unbind mouse down listener
+ *
+ * @method
+ */
+OO.ui.PopupWidget.prototype.unbindMouseDownListener = function () {
+       this.getElementWindow().removeEventListener( 'mousedown', this.onMouseDownHandler, true );
+};
+
+/**
+ * Check if the popup is visible.
+ *
+ * @method
+ * @returns {boolean} Popup is visible
+ */
+OO.ui.PopupWidget.prototype.isVisible = function () {
+       return this.visible;
+};
+
+/**
+ * Set whether to show a tail.
+ *
+ * @method
+ * @returns {boolean} Make tail visible
+ */
+OO.ui.PopupWidget.prototype.useTail = function ( value ) {
+       value = !!value;
+       if ( this.tail !== value ) {
+               this.tail = value;
+               if ( value ) {
+                       this.$element.addClass( 'oo-ui-popupWidget-tailed' );
+               } else {
+                       this.$element.removeClass( 'oo-ui-popupWidget-tailed' );
+               }
+       }
+};
+
+/**
+ * Check if showing a tail.
+ *
+ * @method
+ * @returns {boolean} tail is visible
+ */
+OO.ui.PopupWidget.prototype.hasTail = function () {
+       return this.tail;
+};
+
+/**
+ * Show the context.
+ *
+ * @method
+ * @fires show
+ * @chainable
+ */
+OO.ui.PopupWidget.prototype.show = function () {
+       if ( !this.visible ) {
+               this.$element.show();
+               this.visible = true;
+               this.emit( 'show' );
+               if ( this.autoClose ) {
+                       this.bindMouseDownListener();
+               }
+       }
+       return this;
+};
+
+/**
+ * Hide the context.
+ *
+ * @method
+ * @fires hide
+ * @chainable
+ */
+OO.ui.PopupWidget.prototype.hide = function () {
+       if ( this.visible ) {
+               this.$element.hide();
+               this.visible = false;
+               this.emit( 'hide' );
+               if ( this.autoClose ) {
+                       this.unbindMouseDownListener();
+               }
+       }
+       return this;
+};
+
+/**
+ * Updates the position and size.
+ *
+ * @method
+ * @param {number} width Width
+ * @param {number} height Height
+ * @param {boolean} [transition=false] Use a smooth transition
+ * @chainable
+ */
+OO.ui.PopupWidget.prototype.display = function ( width, height, transition ) {
+       var padding = 10,
+               originOffset = Math.round( this.$element.offset().left ),
+               containerLeft = Math.round( this.$container.offset().left ),
+               containerWidth = this.$container.innerWidth(),
+               containerRight = containerLeft + containerWidth,
+               popupOffset = width * ( { 'left': 0, 'center': -0.5, 'right': -1 } )[this.align],
+               popupLeft = popupOffset - padding,
+               popupRight = popupOffset + padding + width + padding,
+               overlapLeft = ( originOffset + popupLeft ) - containerLeft,
+               overlapRight = containerRight - ( originOffset + popupRight );
+
+       // Prevent transition from being interrupted
+       clearTimeout( this.transitionTimeout );
+       if ( transition ) {
+               // Enable transition
+               this.$element.addClass( 'oo-ui-popupWidget-transitioning' );
+       }
+
+       if ( overlapRight < 0 ) {
+               popupOffset += overlapRight;
+       } else if ( overlapLeft < 0 ) {
+               popupOffset -= overlapLeft;
+       }
+
+       // Position body relative to anchor and resize
+       this.$popup.css( {
+               'left': popupOffset,
+               'width': width,
+               'height': height === undefined ? 'auto' : height
+       } );
+
+       if ( transition ) {
+               // Prevent transitioning after transition is complete
+               this.transitionTimeout = setTimeout( OO.ui.bind( function () {
+                       this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
+               }, this ), 200 );
+       } else {
+               // Prevent transitioning immediately
+               this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
+       }
+
+       return this;
+};
+/**
+ * Button that shows and hides a popup.
+ *
+ * @class
+ * @extends OO.ui.ButtonWidget
+ * @mixins OO.ui.PopuppableElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.PopupButtonWidget = function OoUiPopupButtonWidget( config ) {
+       // Parent constructor
+       OO.ui.ButtonWidget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.PopuppableElement.call( this, config );
+
+       // Initialization
+       this.$element
+               .addClass( 'oo-ui-popupButtonWidget' )
+               .append( this.popup.$element );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.PopupButtonWidget, OO.ui.ButtonWidget );
+
+OO.mixinClass( OO.ui.PopupButtonWidget, OO.ui.PopuppableElement );
+
+/* Methods */
+
+/**
+ * Handles mouse click events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse click event
+ */
+OO.ui.PopupButtonWidget.prototype.onClick = function ( e ) {
+       // Skip clicks within the popup
+       if ( $.contains( this.popup.$element[0], e.target ) ) {
+               return;
+       }
+
+       if ( !this.disabled ) {
+               if ( this.popup.isVisible() ) {
+                       this.hidePopup();
+               } else {
+                       this.showPopup();
+               }
+               OO.ui.ButtonWidget.prototype.onClick.call( this );
+       }
+       return false;
+};
+/**
+ * Creates an OO.ui.SearchWidget object.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string|jQuery} [placeholder] Placeholder text for query input
+ * @cfg {string} [value] Initial query value
+ */
+OO.ui.SearchWidget = function OoUiSearchWidget( config ) {
+       // Configuration intialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Properties
+       this.query = new OO.ui.TextInputWidget( {
+               '$': this.$,
+               'icon': 'search',
+               'placeholder': config.placeholder,
+               'value': config.value
+       } );
+       this.results = new OO.ui.SelectWidget( { '$': this.$ } );
+       this.$query = this.$( '<div>' );
+       this.$results = this.$( '<div>' );
+
+       // Events
+       this.query.connect( this, {
+               'change': 'onQueryChange',
+               'enter': 'onQueryEnter'
+       } );
+       this.results.connect( this, {
+               'highlight': 'onResultsHighlight',
+               'select': 'onResultsSelect'
+       } );
+       this.query.$input.on( 'keydown', OO.ui.bind( this.onQueryKeydown, this ) );
+
+       // Initialization
+       this.$query
+               .addClass( 'oo-ui-searchWidget-query' )
+               .append( this.query.$element );
+       this.$results
+               .addClass( 'oo-ui-searchWidget-results' )
+               .append( this.results.$element );
+       this.$element
+               .addClass( 'oo-ui-searchWidget' )
+               .append( this.$results, this.$query );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.SearchWidget, OO.ui.Widget );
+
+/* Events */
+
+/**
+ * @event highlight
+ * @param {Object|null} item Item data or null if no item is highlighted
+ */
+
+/**
+ * @event select
+ * @param {Object|null} item Item data or null if no item is selected
+ */
+
+/* Methods */
+
+/**
+ * Handle query key down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.SearchWidget.prototype.onQueryKeydown = function ( e ) {
+       var highlightedItem, nextItem,
+               dir = e.which === OO.ui.Keys.DOWN ? 1 : ( e.which === OO.ui.Keys.UP ? -1 : 0 );
+
+       if ( dir ) {
+               highlightedItem = this.results.getHighlightedItem();
+               if ( !highlightedItem ) {
+                       highlightedItem = this.results.getSelectedItem();
+               }
+               nextItem = this.results.getRelativeSelectableItem( highlightedItem, dir );
+               this.results.highlightItem( nextItem );
+               nextItem.scrollElementIntoView();
+       }
+};
+
+/**
+ * Handle select widget select events.
+ *
+ * Clears existing results. Subclasses should repopulate items according to new query.
+ *
+ * @method
+ * @param {string} value New value
+ */
+OO.ui.SearchWidget.prototype.onQueryChange = function () {
+       // Reset
+       this.results.clearItems();
+};
+
+/**
+ * Handle select widget enter key events.
+ *
+ * Selects highlighted item.
+ *
+ * @method
+ * @param {string} value New value
+ */
+OO.ui.SearchWidget.prototype.onQueryEnter = function () {
+       // Reset
+       this.results.selectItem( this.results.getHighlightedItem() );
+};
+
+/**
+ * Handle select widget highlight events.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} item Highlighted item
+ * @fires highlight
+ */
+OO.ui.SearchWidget.prototype.onResultsHighlight = function ( item ) {
+       this.emit( 'highlight', item ? item.getData() : null );
+};
+
+/**
+ * Handle select widget select events.
+ *
+ * @method
+ * @param {OO.ui.OptionWidget} item Selected item
+ * @fires select
+ */
+OO.ui.SearchWidget.prototype.onResultsSelect = function ( item ) {
+       this.emit( 'select', item ? item.getData() : null );
+};
+
+/**
+ * Get the query input.
+ *
+ * @method
+ * @returns {OO.ui.TextInputWidget} Query input
+ */
+OO.ui.SearchWidget.prototype.getQuery = function () {
+       return this.query;
+};
+
+/**
+ * Get the results list.
+ *
+ * @method
+ * @returns {OO.ui.SelectWidget} Select list
+ */
+OO.ui.SearchWidget.prototype.getResults = function () {
+       return this.results;
+};
+/**
+ * Creates an OO.ui.TextInputWidget object.
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [placeholder] Placeholder text
+ * @cfg {string} [icon] Symbolic name of icon
+ * @cfg {boolean} [multiline=false] Allow multiple lines of text
+ */
+OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.InputWidget.call( this, config );
+
+       // Properties
+       this.pending = 0;
+       this.multiline = !!config.multiline;
+
+       // Events
+       this.$input.on( 'keypress', OO.ui.bind( this.onKeyPress, this ) );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-textInputWidget' );
+       if ( config.icon ) {
+               this.$element.addClass( 'oo-ui-textInputWidget-decorated' );
+               this.$element.append(
+                       this.$( '<span>' )
+                               .addClass( 'oo-ui-textInputWidget-icon oo-ui-icon-' + config.icon )
+                               .mousedown( OO.ui.bind( function () {
+                                       this.$input.focus();
+                                       return false;
+                               }, this ) )
+               );
+       }
+       if ( config.placeholder ) {
+               this.$input.attr( 'placeholder', config.placeholder );
+       }
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.TextInputWidget, OO.ui.InputWidget );
+
+/* Events */
+
+/**
+ * User presses enter inside the text box.
+ *
+ * Not called if input is multiline.
+ *
+ * @event enter
+ */
+
+/* Methods */
+
+/**
+ * Handles key press events.
+ *
+ * @param {jQuery.Event} e Key press event
+ * @fires enter If enter key is pressed and input is not multiline
+ */
+OO.ui.TextInputWidget.prototype.onKeyPress = function ( e ) {
+       if ( e.which === OO.ui.Keys.ENTER && !this.multiline ) {
+               this.emit( 'enter' );
+       }
+};
+
+/**
+ * Get input element.
+ *
+ * @method
+ * @param {Object} [config] Configuration options
+ * @returns {jQuery} Input element
+ */
+OO.ui.TextInputWidget.prototype.getInputElement = function ( config ) {
+       return config.multiline ? this.$( '<textarea>' ) : this.$( '<input type="text" />' );
+};
+
+/* Methods */
+
+/**
+ * Checks if input is pending.
+ *
+ * @method
+ * @returns {boolean} Input is pending
+ */
+OO.ui.TextInputWidget.prototype.isPending = function () {
+       return !!this.pending;
+};
+
+/**
+ * Increases the pending stack.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.pushPending = function () {
+       this.pending++;
+       this.$element.addClass( 'oo-ui-textInputWidget-pending' );
+       this.$input.addClass( 'oo-ui-texture-pending' );
+       return this;
+};
+
+/**
+ * Reduces the pending stack.
+ *
+ * Clamped at zero.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.popPending = function () {
+       this.pending = Math.max( 0, this.pending - 1 );
+       if ( !this.pending ) {
+               this.$element.removeClass( 'oo-ui-textInputWidget-pending' );
+               this.$input.removeClass( 'oo-ui-texture-pending' );
+       }
+       return this;
+};
+/**
+ * Creates an OO.ui.TextInputMenuWidget object.
+ *
+ * @class
+ * @extends OO.ui.MenuWidget
+ *
+ * @constructor
+ * @param {OO.ui.TextInputWidget} input Text input widget to provide menu for
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$container=input.$element] Element to render menu under
+ */
+OO.ui.TextInputMenuWidget = function OoUiTextInputMenuWidget( input, config ) {
+       // Parent constructor
+       OO.ui.MenuWidget.call( this, config );
+
+       // Properties
+       this.input = input;
+       this.$container = config.$container || this.input.$element;
+       this.onWindowResizeHandler = OO.ui.bind( this.onWindowResize, this );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-textInputMenuWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.TextInputMenuWidget, OO.ui.MenuWidget );
+
+/* Methods */
+
+/**
+ * Handle window resize event.
+ *
+ * @method
+ * @param {jQuery.Event} e Window resize event
+ */
+OO.ui.TextInputMenuWidget.prototype.onWindowResize = function () {
+       this.position();
+};
+
+/**
+ * Shows the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.TextInputMenuWidget.prototype.show = function () {
+       // Parent method
+       OO.ui.MenuWidget.prototype.show.call( this );
+
+       this.position();
+       this.$( this.getElementWindow() ).on( 'resize', this.onWindowResizeHandler );
+       return this;
+};
+
+/**
+ * Hides the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.TextInputMenuWidget.prototype.hide = function () {
+       // Parent method
+       OO.ui.MenuWidget.prototype.hide.call( this );
+
+       this.$( this.getElementWindow() ).off( 'resize', this.onWindowResizeHandler );
+       return this;
+};
+
+/**
+ * Positions the menu.
+ *
+ * @method
+ * @chainable
+ */
+OO.ui.TextInputMenuWidget.prototype.position = function () {
+       var frameOffset,
+               $container = this.$container,
+               dimensions = $container.offset();
+
+       // Position under input
+       dimensions.top += $container.height();
+
+       // Compensate for frame position if in a differnt frame
+       if ( this.input.$.frame && this.input.$.context !== this.$element[0].ownerDocument ) {
+               frameOffset = OO.ui.Element.getRelativePosition(
+                       this.input.$.frame.$element, this.$element.offsetParent()
+               );
+               dimensions.left += frameOffset.left;
+               dimensions.top += frameOffset.top;
+       } else {
+               // Fix for RTL (for some reason, no need to fix if the frameoffset is set)
+               if ( this.$element.css( 'direction' ) === 'rtl' ) {
+                       dimensions.right = this.$element.parent().position().left -
+                               dimensions.width - dimensions.left;
+                       // Erase the value for 'left':
+                       delete dimensions.left;
+               }
+       }
+
+       this.$element.css( dimensions );
+       this.setIdealSize( $container.width() );
+       return this;
+};
+/**
+ * Mixin for widgets with a boolean state.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [value=false] Initial value
+ */
+OO.ui.ToggleWidget = function OoUiToggleWidget( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Properties
+       this.value = null;
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-toggleWidget' );
+       this.setValue( !!config.value );
+};
+
+/* Events */
+
+/**
+ * @event change
+ * @param {boolean} value Changed value
+ */
+
+/* Methods */
+
+/**
+ * Get the value of the toggle.
+ *
+ * @method
+ * @returns {boolean} Toggle value
+ */
+OO.ui.ToggleWidget.prototype.getValue = function () {
+       return this.value;
+};
+
+/**
+ * Set the value of the toggle.
+ *
+ * @method
+ * @param {boolean} value New value
+ * @fires change
+ * @chainable
+ */
+OO.ui.ToggleWidget.prototype.setValue = function ( value ) {
+       value = !!value;
+       if ( this.value !== value ) {
+               this.value = value;
+               this.emit( 'change', value );
+               this.$element.toggleClass( 'oo-ui-toggleWidget-on', value );
+               this.$element.toggleClass( 'oo-ui-toggleWidget-off', !value );
+       }
+       return this;
+};
+/**
+ * @class
+ * @extends OO.ui.ButtonWidget
+ * @mixins OO.ui.ToggleWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [value=false] Initial value
+ */
+OO.ui.ToggleButtonWidget = function OoUiToggleButtonWidget( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Parent constructor
+       OO.ui.ButtonWidget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.ToggleWidget.call( this, config );
+
+       // Initialization
+       this.$element.addClass( 'oo-ui-toggleButtonWidget' );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.ToggleButtonWidget, OO.ui.ButtonWidget );
+
+OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.ToggleWidget );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToggleButtonWidget.prototype.onClick = function () {
+       if ( !this.disabled ) {
+               this.setValue( !this.value );
+       }
+
+       // Parent method
+       return OO.ui.ButtonWidget.prototype.onClick.call( this );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToggleButtonWidget.prototype.setValue = function ( value ) {
+       value = !!value;
+       if ( value !== this.value ) {
+               this.setActive( value );
+       }
+
+       // Parent method
+       OO.ui.ToggleWidget.prototype.setValue.call( this, value );
+
+       return this;
+};
+/**
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.ToggleWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [value=false] Initial value
+ */
+OO.ui.ToggleSwitchWidget = function OoUiToggleSwitchWidget( config ) {
+       // Parent constructor
+       OO.ui.Widget.call( this, config );
+
+       // Mixin constructors
+       OO.ui.ToggleWidget.call( this, config );
+
+       // Properties
+       this.dragging = false;
+       this.dragStart = null;
+       this.sliding = false;
+       this.$on = this.$( '<span>' );
+       this.$grip = this.$( '<span>' );
+
+       // Events
+       this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
+
+       // Initialization
+       this.$on.addClass( 'oo-ui-toggleSwitchWidget-on' );
+       this.$grip.addClass( 'oo-ui-toggleSwitchWidget-grip' );
+       this.$element
+               .addClass( 'oo-ui-toggleSwitchWidget' )
+               .append( this.$on, this.$grip );
+};
+
+/* Inheritance */
+
+OO.inheritClass( OO.ui.ToggleSwitchWidget, OO.ui.Widget );
+
+OO.mixinClass( OO.ui.ToggleSwitchWidget, OO.ui.ToggleWidget );
+
+/* Methods */
+
+/**
+ * Handles mouse down events.
+ *
+ * @method
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.ToggleSwitchWidget.prototype.onClick = function ( e ) {
+       if ( !this.disabled && e.which === 1 ) {
+               this.setValue( !this.value );
+       }
+};
+}() );
diff --git a/resources/oojs-ui/oojs-ui.svg.css b/resources/oojs-ui/oojs-ui.svg.css
new file mode 100644 (file)
index 0000000..185bcf0
--- /dev/null
@@ -0,0 +1,1880 @@
+/*!
+ * OOjs UI v0.1.0-pre-svg (a290673bbd)
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2014 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: Wed Feb 12 2014 13:52:08 GMT-0800 (PST)
+ */
+/*csslint vendor-prefix:false */
+
+/* Textures */
+
+.oo-ui-texture-pending {
+       /* @embed */
+       background-image: url(images/textures/pending.gif);
+}
+
+.oo-ui-texture-transparency {
+       /* @embed */
+       background-image: url(images/textures/transparency.png);
+}
+
+/* Animation */
+
+@-webkit-keyframes oo-ui-zoom-in {
+       from { -webkit-transform: scale(0.5); }
+       to { -webkit-transform: scale(1); }
+}
+
+@-moz-keyframes oo-ui-zoom-in {
+       from { -moz-transform: scale(0.5); }
+       to { -moz-transform: scale(1); }
+}
+
+@-o-keyframes oo-ui-zoom-in {
+       from { -o-transform: scale(0.5); }
+       to { -o-transform: scale(1); }
+}
+
+@keyframes oo-ui-zoom-in {
+       from { transform: scale(0.5); }
+       to { transform: scale(1); }
+}
+
+@-webkit-keyframes oo-ui-fade-in {
+       from { opacity: 0; }
+       to { opacity: 1; }
+}
+
+@-moz-keyframes oo-ui-fade-in {
+       from { opacity: 0; }
+       to { opacity: 1; }
+}
+
+@-o-keyframes oo-ui-fade-in {
+       from { opacity: 0; }
+       to { opacity: 1; }
+}
+
+@keyframes oo-ui-fade-in {
+       from { opacity: 0; }
+       to { opacity: 1; }
+}
+
+/* RTL Definitions */
+
+/* @noflip */
+.oo-ui-rtl {
+       direction: rtl;
+}
+/* @noflip */
+.oo-ui-ltr {
+       direction: ltr;
+}
+.oo-ui-dialog {
+       position: fixed;
+       top: 0;
+       right: 0;
+       bottom: 0;
+       left: 0;
+       padding: 1em;
+       line-height: 1em;
+       background-color: #fff;
+       background-color: rgba(255,255,255,0.5);
+       -webkit-animation: oo-ui-fade-in 250ms ease-in-out 0 1 normal;
+       -moz-animation: oo-ui-fade-in 250ms ease-in-out 0 1 normal;
+       -o-animation: oo-ui-fade-in 250ms ease-in-out 0 1 normal;
+       animation: oo-ui-fade-in 250ms ease-in-out 0 1 normal;
+}
+
+.oo-ui-dialog-closing {
+       -webkit-animation: oo-ui-fade-in 250ms ease-in-out 0 1 reverse;
+       -moz-animation: oo-ui-fade-in 250ms ease-in-out 0 1 reverse;
+       -o-animation: oo-ui-fade-in 250ms ease-in-out 0 1 reverse;
+       animation: oo-ui-fade-in 250ms ease-in-out 0 1 reverse;
+}
+
+.oo-ui-dialog .oo-ui-window-frame {
+       position: fixed;
+       top: 1em;
+       right: 0;
+       bottom: 1em;
+       left: 0;
+       margin: auto;
+       width: 800px;
+       min-height: 12em;
+       max-height: 600px;
+       background-color: #fff;
+       border: solid 1px #ccc;
+       border-radius: 0.5em;
+       box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
+       overflow: hidden;
+       -webkit-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 normal;
+       -moz-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 normal;
+       -o-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 normal;
+       animation: oo-ui-zoom-in 250ms ease-in-out 0 1 normal;
+}
+
+.oo-ui-dialog .oo-ui-window-frame.oo-ui-window-frame-small {
+       max-width: 600px;
+       max-height: 400px;
+}
+
+.oo-ui-dialog-closing .oo-ui-window-frame {
+       -webkit-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 reverse;
+       -moz-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 reverse;
+       -o-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 reverse;
+       animation: oo-ui-zoom-in 250ms ease-in-out 0 1 reverse;
+}
+
+.oo-ui-dialog .oo-ui-frame {
+       width: 100%;
+       height: 100%;
+}
+
+.oo-ui-dialog-content .oo-ui-window-head,
+.oo-ui-dialog-content .oo-ui-window-body,
+.oo-ui-dialog-content .oo-ui-window-foot {
+       position: absolute;
+       left: 0;
+       right: 0;
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+       overflow: hidden;
+}
+
+.oo-ui-dialog-content .oo-ui-window-head {
+       top: 0;
+       height: 3.8em;
+       padding: 0.5em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-foot {
+       bottom: 0;
+       height: 4.8em;
+       padding: 1em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-body {
+       box-shadow: 0 0 0.66em rgba(0,0,0,0.25);
+       top: 3.8em;
+       bottom: 4.8em;
+}
+
+.oo-ui-dialog-content-footless .oo-ui-window-body {
+       bottom: 0;
+}
+
+.oo-ui-dialog-content-footless .oo-ui-window-foot {
+       display: none;
+}
+
+.oo-ui-dialog-content .oo-ui-window-icon {
+       width: 2.4em;
+       height: 2.8em;
+       line-height: 2.8em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-title {
+       line-height: 2.8em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed {
+       float: left;
+       margin: 0.125em 0.25em;
+}
+
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary,
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive,
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed.oo-ui-flaggableElement-destructive {
+       float: right;
+}
+
+.oo-ui-dialog-content .oo-ui-window-closeButton {
+       float: right;
+       margin: 0.25em 0.25em;
+}
+
+/* OO.ui.ButtonedElement */
+
+a.oo-ui-buttonedElement-button {
+       color: #333;
+       cursor: pointer;
+       display: inline-block;
+       vertical-align: middle;
+       -webkit-touch-callout: none;
+       -webkit-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+       display: none;
+}
+
+.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
+.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+       opacity: 0.8;
+       display: inline-block;
+       vertical-align: middle;
+       background-position: center center;
+       background-repeat: no-repeat;
+       width: 1.9em;
+       height: 1.9em;
+}
+
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+       margin-left: 0;
+}
+
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator {
+       margin-right: -0.75em;
+}
+
+.oo-ui-buttonedElement-frameless {
+       display: inline-block;
+       position: relative;
+       -webkit-transition: opacity 200ms;
+       -moz-transition: opacity 200ms;
+       -o-transition: opacity 200ms;
+       transition: opacity 200ms;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-iconedElement-icon,
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-iconedElement-icon {
+       opacity: 1;
+}
+
+.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+       opacity: 0.2;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+       display: inline-block;
+       vertical-align: middle;
+       margin-left: 0.25em;
+       color: #333;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-labeledElement-label,
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-labeledElement-label {
+       color: #000;
+}
+
+.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+       color: #ccc;
+}
+
+/* OO.ui.ButtonWidget */
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
+       display: inline-block;
+       font-size: 1em;
+       margin: 0.1em 0;
+       padding: 0.2em 0.8em;
+       border-radius: 0.3em;
+       vertical-align: top;
+       text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+       box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
+       text-align: center;
+
+       /* Animation */
+       -webkit-transition: border-color 100ms;
+       -moz-transition: border-color 100ms;
+       -o-transition: border-color 100ms;
+       transition: border-color 100ms;
+
+       /* Gray */
+       border: 1px #c9c9c9 solid;
+       background-color: #dddddd;
+       filter: progid:DXImageTransform.Microsoft.gradient(
+               GradientType=0,startColorstr=#ffffff, endColorstr=#dddddd
+       );
+       background-image: -webkit-gradient(
+               linear, right top, right bottom, color-stop(0%,#ffffff), color-stop(100%,#dddddd)
+       );
+       background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+       background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+       background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+       background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+       background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:focus {
+       border-color: #aaa;
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:active,
+.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active .oo-ui-buttonedElement-button {
+       box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+       color: black;
+
+       /* Gray */
+       border-color: #c9c9c9;
+       background-color: #dddddd;
+       filter: progid:DXImageTransform.Microsoft.gradient(
+               GradientType=0,startColorstr=#dddddd, endColorstr=#ffffff
+       );
+       background-image: -webkit-gradient(
+               linear, right top, right bottom, color-stop(0%,#dddddd), color-stop(100%,#ffffff)
+       );
+       background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+       background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+       background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+       background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+       background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+       margin-left: -0.5em;
+       margin-right: -0.5em;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-iconedElement.oo-ui-labeledElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+       margin-left: -0.5em;
+       margin-right: 0;
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+       display: inline-block;
+       vertical-align: middle;
+       line-height: 1.9em;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-destructive .oo-ui-buttonedElement-button {
+       /* Red text */
+       color: #d45353;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button {
+       /* Green */
+       border: solid 1px #b8d892;
+       background-color: #f0fbe1;
+       filter: progid:DXImageTransform.Microsoft.gradient(
+               GradientType=0,startColorstr=#f0fbe1, endColorstr=#c3e59a
+       );
+       background-image: -webkit-gradient(
+               linear, right top, right bottom, color-stop(0%,#f0fbe1), color-stop(100%,#c3e59a)
+       );
+       background-image: -webkit-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+       background-image: -moz-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+       background-image: -ms-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+       background-image: -o-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+       background-image: linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:focus {
+       border-color: #adcb89;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:active,
+.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button {
+       /* Green */
+       border: solid 1px #b8d892;
+       background-color: #c3e59a;
+       filter: progid:DXImageTransform.Microsoft.gradient(
+               GradientType=0,startColorstr=#c3e59a, endColorstr=#f0fbe1
+       );
+       background-image: -webkit-gradient(
+               linear, right top, right bottom, color-stop(0%,#c3e59a), color-stop(100%,#f0fbe1)
+       );
+       background-image: -webkit-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+       background-image: -moz-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+       background-image: -ms-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+       background-image: -o-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+       background-image: linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
+       /* Blue */
+       border: solid 1px #a6cee1;
+       background-color: #eaf4fa;
+       filter: progid:DXImageTransform.Microsoft.gradient(
+               GradientType=0,startColorstr=#eaf4fa, endColorstr=#b0d9ee
+       );
+       background-image: -webkit-gradient(
+               linear, right top, right bottom, color-stop(0%,#eaf4fa), color-stop(100%,#b0d9ee)
+       );
+       background-image: -webkit-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+       background-image: -moz-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+       background-image: -ms-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+       background-image: -o-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+       background-image: linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:focus {
+       border-color: #9dc2d4;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:active,
+.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
+       /* Blue */
+       border: solid 1px #a6cee1;
+       background-color: #b0d9ee;
+       filter: progid:DXImageTransform.Microsoft.gradient(
+               GradientType=0,startColorstr=#b0d9ee, endColorstr=#eaf4fa
+       );
+       background-image: -webkit-gradient(
+               linear, right top, right bottom, color-stop(0%,#b0d9ee), color-stop(100%,#eaf4fa)
+       );
+       background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+       background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+       background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+       background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+       background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:active,
+.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active.oo-ui-widget-disabled .oo-ui-buttonedElement-button:active {
+       opacity: 0.5;
+       cursor: default;
+       box-shadow: none;
+       color: #333;
+       background: #eee;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:focus {
+       border-color: #ccc;
+       box-shadow: none;
+}
+
+/* OO.ui.LabeledElement */
+
+.oo-ui-labeledElement-label {
+       display: block;
+}
+
+.oo-ui-clippableElement-clippable {
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+}
+.oo-ui-frame {
+       margin: 0;
+       padding: 0;
+}
+
+.oo-ui-frame-body {
+       margin: 0;
+       padding: 0;
+       background: none;
+}
+
+.oo-ui-frame-content {
+       font-family: sans-serif;
+       font-size: 0.8em;
+}
+/* OO.ui.GridLayout */
+/* OO.ui.PanelLayout */
+
+.oo-ui-gridLayout,
+.oo-ui-panelLayout {
+       position: absolute;
+       top: 0;
+       left: 0;
+       right: 0;
+       bottom: 0;
+}
+
+.oo-ui-panelLayout-scrollable {
+       overflow-y: auto;
+}
+
+.oo-ui-panelLayout-padded {
+       padding: 2em;
+}
+
+/* OO.ui.FieldsetLayout */
+
+.oo-ui-fieldsetLayout {
+       border: none;
+       margin: 0;
+       padding: 0;
+}
+
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
+       margin-top: 2em;
+}
+
+.oo-ui-fieldsetLayout-labeled {
+       margin-top: -0.75em;
+}
+
+.oo-ui-fieldsetLayout > legend.oo-ui-labeledElement-label {
+       font-size: 1.5em;
+       margin-bottom: 0.5em;
+}
+
+.oo-ui-fieldsetLayout-decorated > legend.oo-ui-labeledElement-label {
+       padding-left: 1.75em;
+       background-position: left center;
+       background-repeat: no-repeat;
+}
+
+/* OO.ui.BookletLayout */
+
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
+       padding: 1.5em;
+       width: 100%;
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+}
+
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
+       overflow-y: auto;
+}
+
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
+       padding: 2em;
+}
+
+.oo-ui-bookletLayout-outlinePanel {
+       border-right: solid 1px #ddd;
+}
+
+.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
+       position: absolute;
+       top: 0;
+       left: 0;
+       right: 0;
+       bottom: 3em;
+       overflow-y: auto;
+}
+
+.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
+       position: absolute;
+       bottom: 0;
+       left: 0;
+       right: 0;
+       box-shadow: 0 0 0.25em rgba(0,0,0,0.25);
+}
+
+.oo-ui-stackLayout > .oo-ui-panelLayout {
+       display: none;
+}
+
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
+       display: block;
+       position: relative;
+       margin-bottom: 1em;
+       box-shadow: 0 0 0.5em rgba(0,0,0,0.25);
+}
+
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout:last-child {
+       margin-bottom: 0;
+}
+/* OO.ui.PopupTool */
+
+.oo-ui-popupTool .oo-ui-popupWidget {
+       margin-left: 1.25em;
+       font-size: 0.8em;
+}
+
+.oo-ui-popupTool .oo-ui-popupWidget-popup,
+.oo-ui-popupTool .oo-ui-popupWidget-tail {
+       z-index: 4;
+}
+.oo-ui-toolbar {
+       clear: both;
+}
+
+.oo-ui-toolbar-bar {
+       border-bottom: solid 1px #ccc;
+       background-color: white;
+       /* @embed */
+       background-image: url(images/fade-up.png);
+       background-position: left bottom;
+       background-repeat: repeat-x;
+       padding-bottom: 1px;
+       line-height: 1em;
+}
+
+.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
+       border: none;
+       background: none;
+}
+
+.oo-ui-toolbar-bottom .oo-ui-toolbar-bar {
+       position: absolute;
+}
+
+.oo-ui-toolbar-actions {
+       float: right;
+}
+
+.oo-ui-toolbar-tools {
+       float: left;
+}
+
+.oo-ui-toolbar-tools,
+.oo-ui-toolbar-actions,
+.oo-ui-toolbar-shadow {
+       -webkit-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       -o-user-select: none;
+       user-select: none;
+}
+
+.oo-ui-toolbar-actions .oo-ui-popupWidget {
+       -webkit-touch-callout: default;
+       -webkit-user-select: all;
+       -moz-user-select: all;
+       -ms-user-select: all;
+       user-select: all;
+}
+
+.oo-ui-toolbar-shadow {
+       /* @embed */
+       background-image: url(images/toolbar-shadow.png);
+       background-position: left top;
+       background-repeat: repeat-x;
+       position: absolute;
+       bottom: -9px;
+       height: 9px;
+       width: 100%;
+       pointer-events: none;
+       -webkit-transition: opacity 500ms ease-in-out;
+       -moz-transition: opacity 500ms ease-in-out;
+       -o-transition: opacity 500ms ease-in-out;
+       transition: opacity 500ms ease-in-out;
+       opacity: 0.125;
+}
+/* OO.ui.ToolGroup */
+
+.oo-ui-toolGroup {
+       display: inline-block;
+       margin: 0.3em;
+       vertical-align: middle;
+       border-radius: 0.25em;
+       border: solid 1px transparent;
+       -webkit-transition: border-color 300ms;
+       -moz-transition: border-color 300ms;
+       -o-transition: border-color 300ms;
+       transition: border-color 300ms;
+}
+
+.oo-ui-toolGroup:hover {
+       border-color: rgba(0,0,0,0.1);
+}
+
+.oo-ui-toolGroup-empty {
+       display: none;
+}
+
+.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-tool-title {
+       color: #000;
+}
+
+.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       background-position: center center;
+       background-repeat: no-repeat;
+}
+
+/* OO.ui.BarToolGroup */
+
+.oo-ui-barToolGroup > .oo-ui-iconedElement-icon,
+.oo-ui-barToolGroup > .oo-ui-iconedElement-label {
+       display: none;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool {
+       display: inline-block;
+       position: relative;
+       vertical-align: top;
+       margin: -1px 0 -1px -1px;
+       border: solid 1px transparent;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-link {
+       display: block;
+       height: 1.5em;
+       padding: 0.25em;
+       cursor: pointer;
+}
+
+.oo-ui-barToolGroup
+       .oo-ui-tool-active:not(.oo-ui-widget-disabled) +
+       .oo-ui-tool-active:not(.oo-ui-widget-disabled)
+{
+       border-left-color: rgba(0,0,0,0.1);
+}
+
+.oo-ui-barToolGroup .oo-ui-tool:first-child {
+       border-top-left-radius: 0.25em;
+       border-bottom-left-radius: 0.25em;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool:last-child {
+       margin-right: -1px;
+       border-top-right-radius: 0.25em;
+       border-bottom-right-radius: 0.25em;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) {
+       border-color: rgba(0,0,0,0.2);
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled) {
+       border-color: rgba(0,0,0,0.2);
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       display: block;
+       height: 1.5em;
+       width: 1.5em;
+       opacity: 0.8;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+       display: none;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+       cursor: default;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       opacity: 0.2;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       opacity: 0.8;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       opacity: 1;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-title {
+       display: none;
+}
+
+/* OO.ui.PopupToolGroup */
+
+.oo-ui-popupToolGroup {
+       position: relative;
+       height: 2em;
+       min-width: 2.5em;
+}
+
+.oo-ui-popupToolGroup.oo-ui-indicatedElement.oo-ui-iconedElement {
+       min-width: 3.5em;
+}
+
+.oo-ui-popupToolGroup-handle {
+       display: block;
+       cursor: pointer;
+}
+
+.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
+       position: absolute;
+       top: 0;
+       width: 2em;
+       height: 2em;
+       background-position: center center;
+       background-repeat: no-repeat;
+       opacity: 0.8;
+}
+
+.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator {
+       right: 0;
+}
+
+.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
+       left: 0.25em;
+}
+
+.oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
+       line-height: 2.6em;
+       font-size: 0.8em;
+       margin: 0 1em;
+}
+
+.oo-ui-popupToolGroup.oo-ui-iconedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
+       margin-left: 3.25em;
+}
+
+.oo-ui-popupToolGroup.oo-ui-indicatedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
+       margin-right: 2.25em;
+}
+
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+       display: none;
+       position: absolute;
+       top: 2em;
+       left: -1px;
+       z-index: 4;
+       border: solid 1px #ccc;
+       background-color: white;
+       box-shadow: 0 0.25em 1em rgba(0,0,0,0.25);
+}
+
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools .oo-ui-iconedElement-icon {
+       background-repeat: no-repeat;
+       background-position: center center;
+}
+
+.oo-ui-popupToolGroup-active:not(.oo-ui-widget-disabled) > .oo-ui-toolGroup-tools {
+       display: block;
+}
+
+.oo-ui-popupToolGroup-active:not(.oo-ui-widget-disabled) {
+       border-bottom-left-radius: 0;
+       border-bottom-right-radius: 0;
+}
+
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       display: inline-block;
+       vertical-align: middle;
+       height: 2em;
+       width: 2em;
+       margin-right: 0.5em;
+}
+
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+       display: inline-block;
+       vertical-align: middle;
+       line-height: 2em;
+       font-size: 0.8em;
+}
+
+.oo-ui-popupToolGroup .oo-ui-tool-accel {
+       display: none;
+}
+
+/* OO.ui.ListToolGroup */
+
+.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
+       padding: 0.25em;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool {
+       display: inline-block;
+       width: 100%;
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+       border: solid 1px transparent;
+       margin: -1px 0;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool-link {
+       display: block;
+       cursor: pointer;
+       white-space: nowrap;
+       padding-right: 0.5em;
+}
+
+.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
+       border-color: rgba(0,0,0,0.2);
+}
+
+.oo-ui-listToolGroup
+       .oo-ui-tool-active:not(.oo-ui-widget-disabled) +
+       .oo-ui-tool-active:not(.oo-ui-widget-disabled)
+{
+       border-top-color: rgba(0,0,0,0.1);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) {
+       border-color: rgba(0,0,0,0.2);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled) {
+       border-color: rgba(0,0,0,0.2);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+       cursor: default;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
+       color: #ccc;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       opacity: 0.2;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       opacity: 0.8;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       opacity: 1;
+}
+
+/* OO.ui.MenuToolGroup */
+
+.oo-ui-menuToolGroup {
+       border-color: rgba(0,0,0,0.1);
+}
+
+.oo-ui-menuToolGroup:hover {
+       border-color: rgba(0,0,0,0.2);
+}
+
+.oo-ui-menuToolGroup.oo-ui-popupToolGroup-active {
+       border-color: rgba(0,0,0,0.25);
+}
+
+.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+       min-width: 8em;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool {
+       display: block;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+       display: block;
+       cursor: pointer;
+       white-space: nowrap;
+       padding: 0.25em 1em 0.25em 0.25em;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       background-image: none;
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconedElement-icon {
+       /* @embed */
+       background-image: url(images/icons/check.png);
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool:hover {
+       background-color: #e1f3ff;
+}
+
+/* Common */
+
+.oo-ui-barToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled),
+.oo-ui-listToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled),
+.oo-ui-popupToolGroup-active:not(.oo-ui-widget-disabled) {
+       /* @embed */
+       background-image: url(images/fade-down.png);
+       background-position: left top;
+       background-repeat: repeat-x;
+       box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+}
+/* OO.ui.ButtonWidget */
+
+.oo-ui-buttonWidget {
+       display: inline-block;
+       vertical-align: middle;
+}
+
+/* OO.ui.PopupButtonWidget */
+
+.oo-ui-popupButtonWidget {
+       position: relative;
+}
+
+.oo-ui-popupButtonWidget .oo-ui-popupWidget {
+       position: absolute;
+       left: 1em;
+       cursor: auto;
+}
+
+/* OO.ui.ButtonGroupWidget */
+
+.oo-ui-buttonGroupWidget {
+       display: inline-block;
+       border-radius: 0.3em;
+       box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
+       border-radius: 0;
+       margin-bottom: -1px;
+       margin-left: -1px;
+       box-shadow: none;
+}
+
+.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:first-child .oo-ui-buttonedElement-button {
+       border-bottom-left-radius: 0.3em;
+       border-top-left-radius: 0.3em;
+       margin-left: 0;
+}
+
+.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:last-child .oo-ui-buttonedElement-button {
+       border-bottom-right-radius: 0.3em;
+       border-top-right-radius: 0.3em;
+}
+
+/* OO.ui.SelectWidget */
+
+.oo-ui-selectWidget {
+       list-style: none;
+       margin: 0;
+       padding: 0;
+}
+
+/* OO.ui.OptionWidget */
+
+.oo-ui-optionWidget {
+       position: relative;
+       display: block;
+       border: none;
+       list-style: none;
+       margin: 0;
+       padding: 0.5em 2em 0.5em 3em;
+       cursor: pointer;
+}
+
+.oo-ui-optionWidget .oo-ui-labeledElement-label {
+       line-height: 1.5em;
+       white-space: nowrap;
+       text-overflow: ellipsis;
+       overflow: hidden;
+}
+
+.oo-ui-optionWidget-highlighted {
+       background-color: #e1f3ff;
+}
+
+.oo-ui-optionWidget-selected {
+       background-color: #a7dcff;
+}
+
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+       cursor: default;
+}
+
+.oo-ui-optionWidget .oo-ui-iconedElement-icon,
+.oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
+       position: absolute;
+       top: 50%;
+       width: 2em;
+       height: 2em;
+       margin-top: -1em;
+       background-repeat: no-repeat;
+       background-position: center center;
+}
+
+.oo-ui-optionWidget .oo-ui-iconedElement-icon {
+       left: 0.5em;
+}
+
+.oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
+       right: 0.5em;
+}
+
+/* OO.ui.OutlineItemWidget */
+
+.oo-ui-outlineItemWidget {
+       position: relative;
+       padding: 0.75em 0.75em 0.75em 3.5em;
+       -webkit-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+       cursor: pointer;
+       font-size: 1.1em;
+}
+
+.oo-ui-outlineItemWidget-level-1 {
+       padding-left: 5em;
+}
+
+.oo-ui-outlineItemWidget-level-2 {
+       padding-left: 6.5em;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-optionWidget-selected {
+       background-color: #a7dcff;
+       text-shadow: 0 1px 1px rgba(255,255,255,0.5);
+}
+
+.oo-ui-outlineItemWidget-level-0 .oo-ui-iconedElement-icon {
+       left: 1em;
+}
+
+.oo-ui-outlineItemWidget-level-1 .oo-ui-iconedElement-icon {
+       left: 2.5em;
+}
+
+.oo-ui-outlineItemWidget-level-2 .oo-ui-iconedElement-icon {
+       left: 4em;
+}
+
+/* OO.ui.OutlineControlsWidget */
+
+.oo-ui-outlineControlsWidget {
+       height: 3em;
+       background-color: #fff;
+}
+
+.oo-ui-outlineControlsWidget-adders,
+.oo-ui-outlineControlsWidget-movers {
+       float: left;
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+       height: 3em;
+       padding: 0.5em;
+}
+
+.oo-ui-outlineControlsWidget-adders {
+       float: left;
+}
+.oo-ui-outlineControlsWidget-movers {
+       float: right;
+}
+
+.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget {
+       float: left;
+}
+
+.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
+       float: right;
+}
+
+.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget:first-child,
+.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget:first-child:hover {
+       opacity: 0.25;
+       cursor: default;
+}
+
+/* OO.ui.InputLabelWidget */
+
+.oo-ui-inputLabelWidget {
+       padding: 0.5em 0;
+}
+
+/* OO.ui.TextInputWidget */
+
+.oo-ui-textInputWidget {
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+       width: 20em;
+       position: relative;
+}
+
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget input:focus[readonly],
+.oo-ui-widget-disabled.oo-ui-textInputWidget input:focus,
+.oo-ui-textInputWidget textarea,
+.oo-ui-textInputWidget textarea:focus[readonly],
+.oo-ui-widget-disabled.oo-ui-textInputWidget textarea:focus {
+       display: inline-block;
+       font-size: 1em;
+       font-family: sans-serif;
+       background-color: #f7f7f7;
+       border: solid 1px #ccc;
+       box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+       padding: 0.5em;
+       border-radius: 0.25em;
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+       width: 100%;
+       resize: none;
+
+       /* Animation */
+       -webkit-transition: border-color 200ms, box-shadow 200ms, background-color 200ms;
+       -moz-transition: border-color 200ms, box-shadow 200ms, background-color 200ms;
+       -o-transition: border-color 200ms, box-shadow 200ms, background-color 200ms;
+       transition: border-color 200ms, box-shadow 200ms, background-color 200ms;
+}
+
+.oo-ui-textInputWidget-pending input,
+.oo-ui-textInputWidget-pending textarea {
+       background-color: transparent;
+}
+
+.oo-ui-textInputWidget input:focus,
+.oo-ui-textInputWidget textarea:focus {
+       outline: none;
+       border-color: #a7dcff;
+       box-shadow: 0 0 0.3em #a7dcff, 0 0 0 white;
+       background-color: #fff;
+}
+
+.oo-ui-textInputWidget input[readonly],
+.oo-ui-textInputWidget textarea[readonly] {
+       color: #777;
+       text-shadow: 0 1px 1px #fff;
+}
+
+.oo-ui-widget-disabled.oo-ui-textInputWidget input,
+.oo-ui-widget-disabled.oo-ui-textInputWidget input:focus,
+.oo-ui-widget-disabled.oo-ui-textInputWidget textarea,
+.oo-ui-widget-disabled.oo-ui-textInputWidget textarea:focus {
+       color: #ccc;
+       text-shadow: 0 1px 1px #fff;
+}
+
+.oo-ui-textInputWidget-decorated input,
+.oo-ui-textInputWidget-decorated textarea {
+       padding-left: 2em;
+}
+
+.oo-ui-textInputWidget-icon {
+       position: absolute;
+       top: 0;
+       left: 0;
+       width: 2em;
+       height: 100%;
+       background-position: right center;
+       background-repeat: no-repeat;
+}
+
+/* OO.ui.CheckboxWidget */
+.oo-ui-checkboxWidget .oo-ui-labeledElement-label {
+       display: inline-block;
+       vertical-align: middle;
+       padding-left: 0.5em;
+}
+
+.oo-ui-checkboxWidget input {
+       vertical-align: middle;
+}
+
+.oo-ui-checkboxWidget.oo-ui-widget-disabled .oo-ui-labeledElement-label {
+       opacity: 0.5;
+}
+
+/* OO.ui.MenuWidget */
+
+.oo-ui-menuWidget {
+       position: absolute;
+       background: #fff;
+       margin-top: -1px;
+       border: solid 1px #ccc;
+       border-radius: 0 0 0.25em 0.25em;
+       box-shadow: 0 0.15em 1em 0 rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-menuWidget input {
+       position: absolute;
+       width: 0;
+       height: 0;
+       overflow: hidden;
+       opacity: 0;
+}
+
+/* OO.ui.MenuItemWidget */
+
+.oo-ui-menuItemWidget {
+       position: relative;
+}
+
+.oo-ui-menuItemWidget .oo-ui-iconedElement-icon {
+       display: none;
+}
+
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconedElement-icon {
+       display: block;
+}
+
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
+       background-color: transparent;
+}
+
+.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted {
+       background-color: #e1f3ff;
+}
+
+/* OO.ui.MenuSectionItemWidget */
+
+.oo-ui-menuSectionItemWidget {
+       padding: 0.33em 0.75em;
+       color: #888;
+       cursor: default;
+}
+
+/* OO.ui.ButtonSelectWidget */
+
+.oo-ui-buttonSelectWidget {
+       display: inline-block;
+       border-radius: 0.3em;
+       box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
+       border-radius: 0;
+       margin-left: -1px;
+       box-shadow: none;
+}
+
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonedElement-button {
+       border-bottom-left-radius: 0.3em;
+       border-top-left-radius: 0.3em;
+       margin-left: 0;
+}
+
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonedElement-button {
+       border-bottom-right-radius: 0.3em;
+       border-top-right-radius: 0.3em;
+}
+
+/* OO.ui.ButtonOptionWidget */
+
+.oo-ui-buttonOptionWidget {
+       display: inline-block;
+       padding: 0;
+       background-color: transparent;
+}
+
+.oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
+       position: relative;
+       height: 1.9em;
+}
+
+.oo-ui-buttonOptionWidget.oo-ui-iconedElement .oo-ui-iconedElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatedElement .oo-ui-indicatedElement-indicator {
+       position: static;
+       display: inline-block;
+       vertical-align: middle;
+       height: 1.9em;
+       margin-top: 0;
+}
+
+/* OO.ui.PopupWidget */
+
+.oo-ui-popupWidget-popup {
+       position: absolute;
+       overflow: hidden;
+       border: solid 1px #ccc;
+       border-radius: 0.25em;
+       background-color: #fff;
+       box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-popupWidget-tail {
+       display: none;
+}
+
+.oo-ui-popupWidget-tailed .oo-ui-popupWidget-popup {
+       margin-top: 7px;
+}
+
+.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
+       display: block;
+       position: absolute;
+       /* @embed */
+       background-image: url(images/tail.svg);
+       background-repeat: no-repeat;
+       width: 15px;
+       height: 8px;
+       margin-left: -7px;
+}
+
+.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
+       -webkit-transition: width 100ms, height 100ms, left 100ms;
+       -moz-transition: width 100ms, height 100ms, left 100ms;
+       -o-transition: width 100ms, height 100ms, left 100ms;
+       transition: width 100ms, height 100ms, left 100ms;
+       -webkit-transition-timing-function: ease-in-out;
+       -moz-transition-timing-function: ease-in-out;
+       -o-transition-timing-function: ease-in-out;
+       transition-timing-function: ease-in-out;
+}
+
+.oo-ui-popupWidget-head {
+       height: 2.5em;
+       -webkit-touch-callout: none;
+       -webkit-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+       float: right;
+       margin: 0.25em;
+}
+
+.oo-ui-popupWidget-head .oo-ui-labeledElement-label {
+       float: left;
+       margin: 0.75em 1em;
+       cursor: default;
+}
+
+.oo-ui-popupWidget-body {
+       box-shadow: 0 0 0.66em rgba(0,0,0,0.25);
+}
+
+/* OO.ui.SearchWidget */
+
+.oo-ui-searchWidget-query {
+       position: absolute;
+       top: 0;
+       left: 0;
+       right: 0;
+       height: 4em;
+       padding: 0 1em;
+       box-shadow: 0 0 0.5em rgba(0,0,0,0.2);
+}
+
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+       width: 100%;
+       margin: 0.75em 0;
+}
+
+.oo-ui-searchWidget-results {
+       position: absolute;
+       top: 4em;
+       bottom: 0;
+       left: 0;
+       right: 0;
+       padding: 1em;
+       overflow-x: hidden;
+       overflow-y: auto;
+       line-height: 0;
+}
+
+/* OO.ui.ToggleSwitchWidget */
+
+.oo-ui-toggleSwitchWidget {
+       position: relative;
+       display: inline-block;
+       vertical-align: middle;
+       height: 2em;
+       width: 3em;
+       border-radius: 1em;
+       overflow: hidden;
+       box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+       border: solid 1px #ccc;
+       cursor: pointer;
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+       -webkit-transform: translateZ(0px);
+       -moz-transform: translateZ(0px);
+       -ms-transform: translateZ(0px);
+       -o-transform: translateZ(0px);
+       transform: translateZ(0px);
+
+       /* Gray */
+       background-color: #dddddd;
+       filter: progid:DXImageTransform.Microsoft.gradient(
+               GradientType=0,startColorstr=#dddddd, endColorstr=#ffffff
+       );
+       background-image: -webkit-gradient(
+               linear, right top, right bottom, color-stop(0%,#dddddd), color-stop(100%,#ffffff)
+       );
+       background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+       background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+       background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+       background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+       background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+}
+
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+       opacity: 0.5;
+}
+
+.oo-ui-toggleSwitchWidget-grip {
+       -webkit-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+       -moz-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+       -o-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+       transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+}
+
+.oo-ui-toggleSwitchWidget-grip {
+       position: absolute;
+       display: block;
+       top: 0.25em;
+       left: 0.25em;
+       width: 1.5em;
+       height: 1.5em;
+       border-radius: 1em;
+       box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+
+       /* Gray */
+       border: 1px #c9c9c9 solid;
+       background-color: #ffffff;
+       filter: progid:DXImageTransform.Microsoft.gradient(
+               GradientType=0,startColorstr=#ffffff, endColorstr=#dddddd
+       );
+       background-image: -webkit-gradient(
+               linear, right top, right bottom, color-stop(0%,#ffffff), color-stop(100%,#dddddd)
+       );
+       background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+       background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+       background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+       background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+       background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
+}
+
+.oo-ui-toggleSwitchWidget:not(.oo-ui-widget-disabled):hover,
+.oo-ui-toggleSwitchWidget:not(.oo-ui-widget-disabled):hover .oo-ui-toggleSwitchWidget-grip {
+       border-color: #aaa;
+}
+
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+       left: 1.25em;
+       margin-left: -2px;
+}
+
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+       left: 0.25em;
+       margin-left: 0;
+}
+
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-on {
+       position: absolute;
+       top: 0;
+       bottom: 0;
+       right: 0;
+       left: 0;
+       border-radius: 1em;
+       box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+       cursor: pointer;
+       -webkit-touch-callout: none;
+       -webkit-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+
+       -webkit-transition: opacity 200ms ease-in-out;
+       -moz-transition: opacity 200ms ease-in-out;
+       -o-transition: opacity 200ms ease-in-out;
+       transition: opacity 200ms ease-in-out;
+
+       /* Blue */
+       background-color: #eaf4fa;
+       filter: progid:DXImageTransform.Microsoft.gradient(
+               GradientType=0,startColorstr=#b0d9ee, endColorstr=#eaf4fa
+       );
+       background-image: -webkit-gradient(
+               linear, right top, right bottom, color-stop(0%,#b0d9ee), color-stop(100%,#eaf4fa)
+       );
+       background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+       background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+       background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+       background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+       background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+}
+
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-on {
+       opacity: 1;
+}
+
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-on {
+       opacity: 0;
+}
+.oo-ui-window-head {
+       -webkit-touch-callout: none;
+       -webkit-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+.oo-ui-window-body {
+       padding: 0 0.75em;
+}
+
+.oo-ui-window-icon {
+       float: left;
+       width: 2em;
+       height: 2em;
+       line-height: 2em;
+       margin-right: 0.5em;
+       background-position: right center;
+       background-repeat: no-repeat;
+}
+
+.oo-ui-window-title {
+       float: left;
+       line-height: 2em;
+       color: #333;
+       white-space: nowrap;
+       cursor: default;
+}
+
+.oo-ui-window-overlay {
+       font-family: sans-serif;
+       line-height: 1.5em;
+       font-size: 1em;
+       position: absolute;
+       top: 0;
+       left: 0;
+}
+/* Icons */
+
+.oo-ui-icon-add-item {
+       /* @embed */
+       background-image: url(images/icons/add-item.png);
+}
+
+.oo-ui-icon-advanced {
+       /* @embed */
+       background-image: url(images/icons/advanced.png);
+}
+
+.oo-ui-icon-alert {
+       /* @embed */
+       background-image: url(images/icons/alert.png);
+}
+
+.oo-ui-icon-check {
+       /* @embed */
+       background-image: url(images/icons/check.png);
+}
+
+.oo-ui-icon-clear {
+       /* @embed */
+       background-image: url(images/icons/clear.png);
+}
+
+.oo-ui-icon-close {
+       /* @embed */
+       background-image: url(images/icons/close.png);
+}
+
+.oo-ui-icon-code {
+       /* @embed */
+       background-image: url(images/icons/code.png);
+}
+
+.oo-ui-icon-collapse {
+       /* @embed */
+       background-image: url(images/icons/collapse.png);
+}
+
+.oo-ui-icon-comment {
+       /* @embed */
+       background-image: url(images/icons/comment.png);
+}
+
+.oo-ui-icon-expand {
+       /* @embed */
+       background-image: url(images/icons/expand.png);
+}
+
+.oo-ui-icon-help {
+       /* @embed */
+       background-image: url(images/icons/help.png);
+}
+
+.oo-ui-icon-link {
+       /* @embed */
+       background-image: url(images/icons/link.png);
+}
+
+.oo-ui-icon-menu {
+       /* @embed */
+       background-image: url(images/icons/menu.png);
+}
+
+.oo-ui-icon-next {
+       /* @embed */
+       background-image: url(images/icons/move-ltr.png);
+}
+
+.oo-ui-icon-picture {
+       /* @embed */
+       background-image: url(images/icons/picture.png);
+}
+
+.oo-ui-icon-previous {
+       /* @embed */
+       background-image: url(images/icons/move-rtl.png);
+}
+
+.oo-ui-icon-redo {
+       /* @embed */
+       background-image: url(images/icons/arched-arrow-ltr.png);
+}
+
+.oo-ui-icon-remove {
+       /* @embed */
+       background-image: url(images/icons/remove.png);
+}
+
+.oo-ui-icon-search {
+       /* @embed */
+       background-image: url(images/icons/search.png);
+}
+
+.oo-ui-icon-settings {
+       /* @embed */
+       background-image: url(images/icons/settings.png);
+}
+
+.oo-ui-icon-tag {
+       /* @embed */
+       background-image: url(images/icons/tag.png);
+}
+
+.oo-ui-icon-undo {
+       /* @embed */
+       background-image: url(images/icons/arched-arrow-rtl.png);
+}
+
+.oo-ui-icon-window {
+       /* @embed */
+       background-image: url(images/icons/window.png);
+}
+
+/* Indicators */
+
+.oo-ui-indicator-down {
+       /* @embed */
+       background-image: url(images/indicators/down.png);
+}
+
+.oo-ui-indicator-required {
+       /* @embed */
+       background-image: url(images/indicators/required.png);
+}
+
+.oo-ui-indicator-up {
+       /* @embed */
+       background-image: url(images/indicators/up.png);
+}
+/* Icons */
+
+.oo-ui-icon-add-item {
+       /* @embed */
+       background-image: url(images/icons/add-item.svg);
+}
+
+.oo-ui-icon-advanced {
+       /* @embed */
+       background-image: url(images/icons/advanced.svg);
+}
+
+.oo-ui-icon-alert {
+       /* @embed */
+       background-image: url(images/icons/alert.svg);
+}
+
+.oo-ui-icon-check {
+       /* @embed */
+       background-image: url(images/icons/check.svg);
+}
+
+.oo-ui-icon-clear {
+       /* @embed */
+       background-image: url(images/icons/clear.svg);
+}
+
+.oo-ui-icon-close {
+       /* @embed */
+       background-image: url(images/icons/close.svg);
+}
+
+.oo-ui-icon-code {
+       /* @embed */
+       background-image: url(images/icons/code.svg);
+}
+
+.oo-ui-icon-collapse {
+       /* @embed */
+       background-image: url(images/icons/collapse.svg);
+}
+
+.oo-ui-icon-comment {
+       /* @embed */
+       background-image: url(images/icons/comment.svg);
+}
+
+.oo-ui-icon-expand {
+       /* @embed */
+       background-image: url(images/icons/expand.svg);
+}
+
+.oo-ui-icon-help {
+       /* @embed */
+       background-image: url(images/icons/help.svg);
+}
+
+.oo-ui-icon-link {
+       /* @embed */
+       background-image: url(images/icons/link.svg);
+}
+
+.oo-ui-icon-menu {
+       /* @embed */
+       background-image: url(images/icons/menu.svg);
+}
+
+.oo-ui-icon-next {
+       /* @embed */
+       background-image: url(images/icons/move-ltr.svg);
+}
+
+.oo-ui-icon-picture {
+       /* @embed */
+       background-image: url(images/icons/picture.svg);
+}
+
+.oo-ui-icon-previous {
+       /* @embed */
+       background-image: url(images/icons/move-rtl.svg);
+}
+
+.oo-ui-icon-redo {
+       /* @embed */
+       background-image: url(images/icons/arched-arrow-ltr.svg);
+}
+
+.oo-ui-icon-remove {
+       /* @embed */
+       background-image: url(images/icons/remove.svg);
+}
+
+.oo-ui-icon-search {
+       /* @embed */
+       background-image: url(images/icons/search.svg);
+}
+
+.oo-ui-icon-settings {
+       /* @embed */
+       background-image: url(images/icons/settings.svg);
+}
+
+.oo-ui-icon-tag {
+       /* @embed */
+       background-image: url(images/icons/tag.svg);
+}
+
+.oo-ui-icon-undo {
+       /* @embed */
+       background-image: url(images/icons/arched-arrow-rtl.svg);
+}
+
+.oo-ui-icon-window {
+       /* @embed */
+       background-image: url(images/icons/window.svg);
+}
+
+/* Indicators */
+
+.oo-ui-indicator-down {
+       /* @embed */
+       background-image: url(images/indicators/down.svg);
+}
+
+.oo-ui-indicator-required {
+       /* @embed */
+       background-image: url(images/indicators/required.svg);
+}
+
+.oo-ui-indicator-up {
+       /* @embed */
+       background-image: url(images/indicators/up.svg);
+}
diff --git a/resources/oojs/.gitignore b/resources/oojs/.gitignore
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/resources/oojs/i18n/ace.json b/resources/oojs/i18n/ace.json
deleted file mode 100644 (file)
index 554ae57..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Si Gam Acèh"
-        ]
-    },
-    "ooui-dialog-action-close": "Tôp",
-    "ooui-outline-control-move-down": "Pinah item u yup",
-    "ooui-outline-control-move-up": "Pinah item u ateuëh",
-    "ooui-toolbar-more": "Lom"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/af.json b/resources/oojs/i18n/af.json
deleted file mode 100644 (file)
index a622f89..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Naudefj"
-        ]
-    },
-    "ooui-dialog-action-close": "Sluit",
-    "ooui-outline-control-move-down": "Skuif item af",
-    "ooui-outline-control-move-up": "Skuif item op"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/am.json b/resources/oojs/i18n/am.json
deleted file mode 100644 (file)
index 61e4ff6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Elfalem"
-        ]
-    },
-    "ooui-dialog-action-close": "ለመዝጋት"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ar.json b/resources/oojs/i18n/ar.json
deleted file mode 100644 (file)
index 65e1364..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ciphers",
-            "Claw eg",
-            "Elfalem",
-            "Jdforrester",
-            "Mido",
-            "OsamaK",
-            "زكريا",
-            "مشعل الحربي"
-        ]
-    },
-    "ooui-dialog-action-close": "أغلق",
-    "ooui-outline-control-move-down": "انقل العنصر للأسفل",
-    "ooui-outline-control-move-up": "انقل العنصر للأعلى",
-    "ooui-toolbar-more": "مزيد"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/arc.json b/resources/oojs/i18n/arc.json
deleted file mode 100644 (file)
index 0f9e75d..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Basharh"
-        ]
-    },
-    "ooui-dialog-action-close": "ܣܟܘܪ"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ast.json b/resources/oojs/i18n/ast.json
deleted file mode 100644 (file)
index 959ea23..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Basharh",
-            "Bishnu Saikia",
-            "Xuacu"
-        ]
-    },
-    "ooui-dialog-action-close": "Zarrar",
-    "ooui-outline-control-move-down": "Mover abaxo l'elementu",
-    "ooui-outline-control-move-up": "Mover arriba l'elementu",
-    "ooui-toolbar-more": "Más"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/az.json b/resources/oojs/i18n/az.json
deleted file mode 100644 (file)
index 8bfcf88..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cekli829",
-            "Interfase",
-            "Jduranboger"
-        ]
-    },
-    "ooui-dialog-action-close": "Bağla",
-    "ooui-outline-control-move-down": "Bəndi aşağı apar",
-    "ooui-outline-control-move-up": "Bəndi yuxarı apar"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ba.json b/resources/oojs/i18n/ba.json
deleted file mode 100644 (file)
index 4af0114..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "AiseluRB",
-            "Amire80",
-            "Assele",
-            "Haqmar",
-            "Sagan",
-            "Рустам Нурыев"
-        ]
-    },
-    "ooui-dialog-action-close": "Ябырға",
-    "ooui-outline-control-move-down": "Аҫҡа күсерергә",
-    "ooui-outline-control-move-up": "Өҫкә күсерергә"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/bcl.json b/resources/oojs/i18n/bcl.json
deleted file mode 100644 (file)
index aff451e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Geopoet",
-            "Sky Harbor"
-        ]
-    },
-    "ooui-dialog-action-close": "Seraduhon",
-    "ooui-outline-control-move-down": "Balyuhon an aytem paibaba",
-    "ooui-outline-control-move-up": "Balyuhon an aytem paitaas",
-    "ooui-toolbar-more": "Kadugangan"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/be-tarask.json b/resources/oojs/i18n/be-tarask.json
deleted file mode 100644 (file)
index 5922f61..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "EugeneZelenko",
-            "Wizardist",
-            "Чаховіч Уладзіслаў",
-            "Zedlik"
-        ]
-    },
-    "ooui-dialog-action-close": "Закрыць",
-    "ooui-outline-control-move-down": "Перасунуць ніжэй",
-    "ooui-outline-control-move-up": "Перасунуць вышэй",
-    "ooui-toolbar-more": "Болей"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/be.json b/resources/oojs/i18n/be.json
deleted file mode 100644 (file)
index 3058ab8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Чаховіч Уладзіслаў"
-        ]
-    },
-    "ooui-dialog-action-close": "Закрыць"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/bg.json b/resources/oojs/i18n/bg.json
deleted file mode 100644 (file)
index 67e664b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "DCLXVI",
-            "Hristofor.mirchev",
-            "පසිඳු කාවින්ද"
-        ]
-    },
-    "ooui-dialog-action-close": "Затваряне",
-    "ooui-toolbar-more": "Още"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/bn.json b/resources/oojs/i18n/bn.json
deleted file mode 100644 (file)
index c321ab1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Aftab1995",
-            "Bellayet",
-            "Jayantanth",
-            "Nasir8891",
-            "Runab",
-            "Sayak Sarkar"
-        ]
-    },
-    "ooui-dialog-action-close": "বন্ধ",
-    "ooui-outline-control-move-down": "আইটেম নিচে স্থানান্তর",
-    "ooui-outline-control-move-up": "আইটেম উপরে স্থানান্তর",
-    "ooui-toolbar-more": "আরও"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/br.json b/resources/oojs/i18n/br.json
deleted file mode 100644 (file)
index 38eb9e8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Fohanno",
-            "Fulup",
-            "Y-M D"
-        ]
-    },
-    "ooui-dialog-action-close": "Serriñ",
-    "ooui-outline-control-move-down": "Lakaat an elfenn da ziskenn",
-    "ooui-outline-control-move-up": "Lakaat an elfenn da bignat"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/bs.json b/resources/oojs/i18n/bs.json
deleted file mode 100644 (file)
index 7449f07..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "DzWiki"
-        ]
-    },
-    "ooui-dialog-action-close": "Zatvori",
-    "ooui-outline-control-move-down": "Premjesti stavku dole",
-    "ooui-outline-control-move-up": "Premjesti stavku gore",
-    "ooui-toolbar-more": "Više"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ca.json b/resources/oojs/i18n/ca.json
deleted file mode 100644 (file)
index 61bb1f6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Alvaro Vidal-Abarca",
-            "Amire80",
-            "Arnaugir",
-            "Pginer",
-            "QuimGil",
-            "SMP",
-            "Vriullop"
-        ]
-    },
-    "ooui-dialog-action-close": "Tanca",
-    "ooui-outline-control-move-down": "Baixa element",
-    "ooui-outline-control-move-up": "Puja element",
-    "ooui-toolbar-more": "Més"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ce.json b/resources/oojs/i18n/ce.json
deleted file mode 100644 (file)
index 1e145ea..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Amire80",
-            "Умар"
-        ]
-    },
-    "ooui-dialog-action-close": "ДӀачӀагӀа",
-    "ooui-outline-control-move-down": "Лаха яккха элемент",
-    "ooui-outline-control-move-up": "Лаккха яккха элемент",
-    "ooui-toolbar-more": "Кхин тӀе"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ckb.json b/resources/oojs/i18n/ckb.json
deleted file mode 100644 (file)
index 839f4a8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Calak",
-            "Muhammed taha"
-        ]
-    },
-    "ooui-dialog-action-close": "دایخە"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/co.json b/resources/oojs/i18n/co.json
deleted file mode 100644 (file)
index e5edb21..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Paulu"
-        ]
-    },
-    "ooui-dialog-action-close": "Chjude",
-    "ooui-outline-control-move-down": "Fà falà l'ogettu",
-    "ooui-outline-control-move-up": "Fà cullà l'ogettu"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/cs.json b/resources/oojs/i18n/cs.json
deleted file mode 100644 (file)
index 9661ec6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Chmee2",
-            "Jkjk",
-            "Juandev",
-            "Koo6",
-            "Littledogboy",
-            "Michaelbrabec",
-            "Mormegil",
-            "Polda18",
-            "Tchoř",
-            "ශ්වෙත"
-        ]
-    },
-    "ooui-dialog-action-close": "Zavřít",
-    "ooui-outline-control-move-down": "Přesunout položku dolů",
-    "ooui-outline-control-move-up": "Přesunout položku nahoru",
-    "ooui-toolbar-more": "Další"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/cu.json b/resources/oojs/i18n/cu.json
deleted file mode 100644 (file)
index fa9b1cf..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "ОйЛ"
-        ]
-    },
-    "ooui-dialog-action-close": "ꙁакрꙑи"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/cy.json b/resources/oojs/i18n/cy.json
deleted file mode 100644 (file)
index d37912d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Lloffiwr",
-            "Robin Owain",
-            "ОйЛ"
-        ]
-    },
-    "ooui-dialog-action-close": "Caeer",
-    "ooui-outline-control-move-down": "Symud yr eitem lawr",
-    "ooui-outline-control-move-up": "Symud yr eitem lan",
-    "ooui-toolbar-more": "Rhagor"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/da.json b/resources/oojs/i18n/da.json
deleted file mode 100644 (file)
index bf47bcb..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cgtdk",
-            "Christian List",
-            "EileenSanda",
-            "Laketown",
-            "Palnatoke",
-            "Simeondahl",
-            "Tehnix"
-        ]
-    },
-    "ooui-dialog-action-close": "Luk",
-    "ooui-outline-control-move-down": "Flyt ned",
-    "ooui-outline-control-move-up": "Flyt op",
-    "ooui-toolbar-more": "Mere"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/de.json b/resources/oojs/i18n/de.json
deleted file mode 100644 (file)
index 3a66648..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "APPER",
-            "G.Hagedorn",
-            "Inkowik",
-            "Jcornelius",
-            "Jdforrester",
-            "Kghbln",
-            "Metalhead64",
-            "Murma174",
-            "Se4598",
-            "Tomabrafix"
-        ]
-    },
-    "ooui-dialog-action-close": "Schließen",
-    "ooui-outline-control-move-down": "Element nach unten verschieben",
-    "ooui-outline-control-move-up": "Element nach oben verschieben",
-    "ooui-toolbar-more": "Mehr"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/diq.json b/resources/oojs/i18n/diq.json
deleted file mode 100644 (file)
index bb0ac35..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Erdemaslancan",
-            "Gorizon",
-            "Kghbln",
-            "Marmase",
-            "Mirzali",
-            "Se4598"
-        ]
-    },
-    "ooui-dialog-action-close": "Racnê",
-    "ooui-outline-control-move-down": "Bendi bere cêr",
-    "ooui-outline-control-move-up": "Bendi bere cor",
-    "ooui-toolbar-more": "Zewbi"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/dsb.json b/resources/oojs/i18n/dsb.json
deleted file mode 100644 (file)
index 0f47587..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Michawiki"
-        ]
-    },
-    "ooui-dialog-action-close": "Zacyniś",
-    "ooui-outline-control-move-down": "Element dołoj pśesunuś",
-    "ooui-outline-control-move-up": "Element górjej pśesunuś",
-    "ooui-toolbar-more": "Wěcej"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/el.json b/resources/oojs/i18n/el.json
deleted file mode 100644 (file)
index 66051f1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Astralnet",
-            "Dipa1965",
-            "Evropi",
-            "FocalPoint",
-            "Geraki",
-            "Glavkos",
-            "Nikosguard",
-            "Tifa93"
-        ]
-    },
-    "ooui-dialog-action-close": "Κλείσιμο",
-    "ooui-outline-control-move-down": "Μετακίνηση προς τα κάτω",
-    "ooui-outline-control-move-up": "Μετακίνηση προς τα πάνω",
-    "ooui-toolbar-more": "Περισσότερα"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/eml.json b/resources/oojs/i18n/eml.json
deleted file mode 100644 (file)
index 5dd09f5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Gloria sah",
-            "Lévi"
-        ]
-    },
-    "ooui-dialog-action-close": "Sèra",
-    "ooui-outline-control-move-down": "Spôsta in bâs",
-    "ooui-outline-control-move-up": "Spôsta in êlt",
-    "ooui-toolbar-more": "Êter"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/en.json b/resources/oojs/i18n/en.json
deleted file mode 100644 (file)
index d402de8..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-    "@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-dialog-action-close": "Close",
-    "ooui-outline-control-move-down": "Move item down",
-    "ooui-outline-control-move-up": "Move item up",
-    "ooui-toolbar-more": "More"
-}
diff --git a/resources/oojs/i18n/eo.json b/resources/oojs/i18n/eo.json
deleted file mode 100644 (file)
index 51f3261..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Happy5214",
-            "KuboF",
-            "Shirayuki",
-            "Yekrats"
-        ]
-    },
-    "ooui-dialog-action-close": "Fermi",
-    "ooui-outline-control-move-down": "Movi eron suben",
-    "ooui-outline-control-move-up": "Movi eron supren",
-    "ooui-toolbar-more": "Pli"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/es.json b/resources/oojs/i18n/es.json
deleted file mode 100644 (file)
index 0d822bc..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Armando-Martin",
-            "Aruizdr",
-            "Benfutbol10",
-            "DJ Nietzsche",
-            "Erdemaslancan",
-            "Fitoschido",
-            "Imre",
-            "Invadinado",
-            "Jdforrester",
-            "Jduranboger",
-            "PoLuX124",
-            "Ralgis",
-            "Thehelpfulone"
-        ]
-    },
-    "ooui-dialog-action-close": "Cerrar",
-    "ooui-outline-control-move-down": "Mover abajo",
-    "ooui-outline-control-move-up": "Mover arriba",
-    "ooui-toolbar-more": "Más"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/et.json b/resources/oojs/i18n/et.json
deleted file mode 100644 (file)
index 4af8dbe..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Avjoska",
-            "Pikne"
-        ]
-    },
-    "ooui-dialog-action-close": "Sule",
-    "ooui-outline-control-move-down": "Liiguta üksust allapoole",
-    "ooui-outline-control-move-up": "Liiguta üksust ülespoole",
-    "ooui-toolbar-more": "Veel"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/eu.json b/resources/oojs/i18n/eu.json
deleted file mode 100644 (file)
index 5d3f08b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "An13sa",
-            "Unai Fdz. de Betoño",
-            "Xabier Armendaritz"
-        ]
-    },
-    "ooui-dialog-action-close": "Itxi",
-    "ooui-outline-control-move-down": "Mugitu itema beherantz",
-    "ooui-outline-control-move-up": "Mugitu itema gorantz",
-    "ooui-toolbar-more": "Gehiago"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/fa.json b/resources/oojs/i18n/fa.json
deleted file mode 100644 (file)
index 173acd7..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Dalba",
-            "Ebraminio",
-            "Jdforrester",
-            "Ladsgroup",
-            "Mjbmr",
-            "Nojan Madinehi",
-            "Reza1615",
-            "Taha",
-            "درفش کاویانی"
-        ]
-    },
-    "ooui-dialog-action-close": "بستن",
-    "ooui-outline-control-move-down": "انتقال مورد به پایین",
-    "ooui-outline-control-move-up": "انتقال مورد به بالا",
-    "ooui-toolbar-more": "بیشتر"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/fi.json b/resources/oojs/i18n/fi.json
deleted file mode 100644 (file)
index dcd367f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Beluga",
-            "Crt",
-            "Harriv",
-            "Linnea",
-            "Nedergard",
-            "Nike",
-            "Olli",
-            "Pxos",
-            "Samoasambia",
-            "Silvonen",
-            "Skalman",
-            "Stryn",
-            "VezonThunder"
-        ]
-    },
-    "ooui-dialog-action-close": "Sulje",
-    "ooui-outline-control-move-down": "Siirrä kohdetta alaspäin",
-    "ooui-outline-control-move-up": "Siirrä kohdetta ylöspäin",
-    "ooui-toolbar-more": "Lisää"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/fo.json b/resources/oojs/i18n/fo.json
deleted file mode 100644 (file)
index 00a48ff..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "EileenSanda"
-        ]
-    },
-    "ooui-dialog-action-close": "Lat aftur",
-    "ooui-outline-control-move-down": "Flyt lutin niður",
-    "ooui-outline-control-move-up": "Flyt lutin upp",
-    "ooui-toolbar-more": "Meira"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/fr.json b/resources/oojs/i18n/fr.json
deleted file mode 100644 (file)
index eb24b5a..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-    "@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"
-        ]
-    },
-    "ooui-dialog-action-close": "Fermer",
-    "ooui-outline-control-move-down": "Faire descendre l’élément",
-    "ooui-outline-control-move-up": "Faire monter l’élément",
-    "ooui-toolbar-more": "Plus"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/frr.json b/resources/oojs/i18n/frr.json
deleted file mode 100644 (file)
index ee95b8a..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "ChrisPtDe",
-            "Murma174"
-        ]
-    },
-    "ooui-dialog-action-close": "Slütj",
-    "ooui-outline-control-move-down": "Element efter onern sküüw",
-    "ooui-outline-control-move-up": "Element efter boowen sküüw",
-    "ooui-toolbar-more": "Muar"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/fur.json b/resources/oojs/i18n/fur.json
deleted file mode 100644 (file)
index 18ea383..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Klenje",
-            "Tocaibon"
-        ]
-    },
-    "ooui-dialog-action-close": "Siere",
-    "ooui-outline-control-move-down": "sposte sot",
-    "ooui-outline-control-move-up": "sposte in su",
-    "ooui-toolbar-more": "Altri"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/gl.json b/resources/oojs/i18n/gl.json
deleted file mode 100644 (file)
index 5d0928f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Alison",
-            "Kscanne",
-            "Toliño"
-        ]
-    },
-    "ooui-dialog-action-close": "Pechar",
-    "ooui-outline-control-move-down": "Mover o elemento abaixo",
-    "ooui-outline-control-move-up": "Mover o elemento arriba",
-    "ooui-toolbar-more": "Máis"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/gu.json b/resources/oojs/i18n/gu.json
deleted file mode 100644 (file)
index 65ec22b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ashok modhvadia",
-            "KartikMistry",
-            "The Discoverer"
-        ]
-    },
-    "ooui-dialog-action-close": "બંધ કરો",
-    "ooui-outline-control-move-down": "વસ્તુ નીચે ખસેડો",
-    "ooui-outline-control-move-up": "વસ્તુ ઉપર ખસેડો",
-    "ooui-toolbar-more": "વધુ"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/he.json b/resources/oojs/i18n/he.json
deleted file mode 100644 (file)
index 31b693c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Amire80",
-            "ExampleTomer",
-            "Guycn2",
-            "Matanya",
-            "Mooeypoo",
-            "Orsa",
-            "Shimmin Beg",
-            "אור שפירא",
-            "חיים",
-            "ערן",
-            "פוילישער",
-            "קיפודנחש"
-        ]
-    },
-    "ooui-dialog-action-close": "סגירה",
-    "ooui-outline-control-move-down": "להזיז את הפריט מטה",
-    "ooui-outline-control-move-up": "להזיז את הפריט מעלה",
-    "ooui-toolbar-more": "עוד"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/hi.json b/resources/oojs/i18n/hi.json
deleted file mode 100644 (file)
index 8b79d34..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ansumang",
-            "Devayon",
-            "Rajesh",
-            "Siddhartha Ghai"
-        ]
-    },
-    "ooui-dialog-action-close": "बंद करें",
-    "ooui-outline-control-move-down": "प्रविष्टि नीचे ले जाएँ",
-    "ooui-outline-control-move-up": "प्रविष्टि ऊपर ले जाएँ",
-    "ooui-toolbar-more": "अधिक"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/hr.json b/resources/oojs/i18n/hr.json
deleted file mode 100644 (file)
index 1c3f925..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "MaGa",
-            "Roberta F.",
-            "SpeedyGonsales"
-        ]
-    },
-    "ooui-dialog-action-close": "zatvori",
-    "ooui-outline-control-move-down": "Premjesti stavku dolje",
-    "ooui-outline-control-move-up": "Premjesti stavku gore",
-    "ooui-toolbar-more": "Više mogućnosti"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/hsb.json b/resources/oojs/i18n/hsb.json
deleted file mode 100644 (file)
index 861c6e5..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "J budissin",
-            "Michawiki"
-        ]
-    },
-    "ooui-dialog-action-close": "Začinić"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/hu.json b/resources/oojs/i18n/hu.json
deleted file mode 100644 (file)
index 9f7b435..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Dj",
-            "Einstein2",
-            "Misibacsi",
-            "ViDam"
-        ]
-    },
-    "ooui-dialog-action-close": "Bezár",
-    "ooui-outline-control-move-down": "Elem mozgatása lefelé",
-    "ooui-outline-control-move-up": "Elem mozgatása felfelé",
-    "ooui-toolbar-more": "Tovább..."
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/hy.json b/resources/oojs/i18n/hy.json
deleted file mode 100644 (file)
index f6cb90b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Vacio",
-            "Xelgen"
-        ]
-    },
-    "ooui-dialog-action-close": "Փակել",
-    "ooui-outline-control-move-down": "Իջեցնել կետը",
-    "ooui-outline-control-move-up": "Բարձրացնել կետը",
-    "ooui-toolbar-more": "Ավելին"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ia.json b/resources/oojs/i18n/ia.json
deleted file mode 100644 (file)
index e335553..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "McDutchie"
-        ]
-    },
-    "ooui-dialog-action-close": "Clauder"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/id.json b/resources/oojs/i18n/id.json
deleted file mode 100644 (file)
index 6d3ba4d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Farras",
-            "Ilham151096",
-            "Iwan Novirion",
-            "Iyan",
-            "Kenrick95",
-            "McDutchie",
-            "Rv77ax",
-            "William Surya Permana"
-        ]
-    },
-    "ooui-dialog-action-close": "Tutup",
-    "ooui-outline-control-move-down": "Pindahkan butir ke bawah",
-    "ooui-outline-control-move-up": "Pindahkan butir ke atas",
-    "ooui-toolbar-more": "Lainnya"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ie.json b/resources/oojs/i18n/ie.json
deleted file mode 100644 (file)
index 84d002d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Makuba"
-        ]
-    },
-    "ooui-dialog-action-close": "Terminar",
-    "ooui-outline-control-move-down": "Mover element a infra",
-    "ooui-outline-control-move-up": "Mover element a supra",
-    "ooui-toolbar-more": "Plu"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ilo.json b/resources/oojs/i18n/ilo.json
deleted file mode 100644 (file)
index 15f42e5..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Lam-ang"
-        ]
-    },
-    "ooui-dialog-action-close": "Irekep",
-    "ooui-outline-control-move-down": "Ipababa ti banag",
-    "ooui-outline-control-move-up": "Ipangato ti banag",
-    "ooui-toolbar-more": "Adu pay"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/is.json b/resources/oojs/i18n/is.json
deleted file mode 100644 (file)
index efe0e67..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Maxí",
-            "Snævar"
-        ]
-    },
-    "ooui-dialog-action-close": "Loka",
-    "ooui-outline-control-move-down": "Færa atriða niður",
-    "ooui-outline-control-move-up": "Færa atriða upp",
-    "ooui-toolbar-more": "Fleira"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/it.json b/resources/oojs/i18n/it.json
deleted file mode 100644 (file)
index 6158cff..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Beta16",
-            "Darth Kule",
-            "Doc.mari",
-            "Eleonora negri",
-            "Elitre",
-            "F. Cosoleto",
-            "FRacco",
-            "Gianfranco",
-            "Minerva Titani",
-            "Raoli",
-            "Una giornata uggiosa '94"
-        ]
-    },
-    "ooui-dialog-action-close": "Chiudi",
-    "ooui-outline-control-move-down": "Sposta in basso",
-    "ooui-outline-control-move-up": "Sposta in alto",
-    "ooui-toolbar-more": "Altro"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ja.json b/resources/oojs/i18n/ja.json
deleted file mode 100644 (file)
index 789fbeb..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Fryed-peach",
-            "Miya",
-            "Penn Station",
-            "Shirayuki"
-        ]
-    },
-    "ooui-dialog-action-close": "閉じる",
-    "ooui-outline-control-move-down": "項目を下に移動させる",
-    "ooui-outline-control-move-up": "項目を上に移動させる",
-    "ooui-toolbar-more": "その他"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/jv.json b/resources/oojs/i18n/jv.json
deleted file mode 100644 (file)
index a362079..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Gleki",
-            "NoiX180",
-            "Pras"
-        ]
-    },
-    "ooui-dialog-action-close": "Tutup",
-    "ooui-outline-control-move-down": "Pindhahaken butir mangandhap"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ka.json b/resources/oojs/i18n/ka.json
deleted file mode 100644 (file)
index 78180af..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "BRUTE",
-            "David1010",
-            "Gleki",
-            "ITshnik",
-            "MIKHEIL",
-            "NoiX180",
-            "Pras"
-        ]
-    },
-    "ooui-dialog-action-close": "დახურვა",
-    "ooui-outline-control-move-down": "ელემენტის ქვემოთ გადატანა",
-    "ooui-outline-control-move-up": "ელემენტის ზემოთ გადატანა"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/kk-cyrl.json b/resources/oojs/i18n/kk-cyrl.json
deleted file mode 100644 (file)
index 4c27b07..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Arystanbek"
-        ]
-    },
-    "ooui-dialog-action-close": "Жабу",
-    "ooui-outline-control-move-down": "Элементті төмен жылжыту",
-    "ooui-outline-control-move-up": "Элементті жоғары жылжыту",
-    "ooui-toolbar-more": "толығырақ"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ko.json b/resources/oojs/i18n/ko.json
deleted file mode 100644 (file)
index f1f61df..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Freebiekr",
-            "Hym411",
-            "Kwj2772",
-            "LFM",
-            "아라"
-        ]
-    },
-    "ooui-dialog-action-close": "닫기",
-    "ooui-outline-control-move-down": "항목을 아래로 옮기기",
-    "ooui-outline-control-move-up": "항목을 위로 옮기기",
-    "ooui-toolbar-more": "더 보기"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/krc.json b/resources/oojs/i18n/krc.json
deleted file mode 100644 (file)
index f629139..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Iltever"
-        ]
-    },
-    "ooui-dialog-action-close": "Джаб",
-    "ooui-outline-control-move-down": "Элементни тюбюне кёчюр",
-    "ooui-outline-control-move-up": "Элементни башына кёчюр"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/kw.json b/resources/oojs/i18n/kw.json
deleted file mode 100644 (file)
index 95a9b91..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "George Animal",
-            "Nrowe",
-            "Purodha"
-        ]
-    },
-    "ooui-dialog-action-close": "Degea"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ky.json b/resources/oojs/i18n/ky.json
deleted file mode 100644 (file)
index 2d62bda..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Chorobek",
-            "George Animal",
-            "Nrowe",
-            "Tynchtyk Chorotegin",
-            "Викиней"
-        ]
-    },
-    "ooui-dialog-action-close": "Жабуу"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/lb.json b/resources/oojs/i18n/lb.json
deleted file mode 100644 (file)
index a18894e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Autokrator",
-            "Chorobek",
-            "Robby",
-            "Soued031",
-            "Tynchtyk Chorotegin",
-            "UV",
-            "Викиней"
-        ]
-    },
-    "ooui-dialog-action-close": "Zoumaachen",
-    "ooui-outline-control-move-down": "Element erof réckelen",
-    "ooui-outline-control-move-up": "Element erop réckelen",
-    "ooui-toolbar-more": "Méi"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/lmo.json b/resources/oojs/i18n/lmo.json
deleted file mode 100644 (file)
index e506b7a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ninonino"
-        ]
-    },
-    "ooui-dialog-action-close": "Sèra",
-    "ooui-outline-control-move-down": "Spòsta 'n zó",
-    "ooui-outline-control-move-up": "Spòsta 'n sö",
-    "ooui-toolbar-more": "Amò"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/lt.json b/resources/oojs/i18n/lt.json
deleted file mode 100644 (file)
index b3a16e8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Audriusa",
-            "Eitvys200"
-        ]
-    },
-    "ooui-dialog-action-close": "Uždaryti"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/lv.json b/resources/oojs/i18n/lv.json
deleted file mode 100644 (file)
index c633339..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Admresdeserv.",
-            "Audriusa",
-            "Eitvys200",
-            "Papuass",
-            "PeterisP"
-        ]
-    },
-    "ooui-dialog-action-close": "Aizvērt",
-    "ooui-outline-control-move-down": "Pārvietot vienumu uz leju",
-    "ooui-outline-control-move-up": "Pārvietot vienumu uz augšu",
-    "ooui-toolbar-more": "Vairāk"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/mg.json b/resources/oojs/i18n/mg.json
deleted file mode 100644 (file)
index dcb5fd5..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Jagwar"
-        ]
-    },
-    "ooui-dialog-action-close": "Hidiana"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/min.json b/resources/oojs/i18n/min.json
deleted file mode 100644 (file)
index 55174c0..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Iwan Novirion",
-            "Jagwar"
-        ]
-    },
-    "ooui-dialog-action-close": "Tutuik"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/mk.json b/resources/oojs/i18n/mk.json
deleted file mode 100644 (file)
index b363a45..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Bjankuloski06",
-            "Brest",
-            "Iwan Novirion"
-        ]
-    },
-    "ooui-dialog-action-close": "Затвори",
-    "ooui-outline-control-move-down": "Помести надолу",
-    "ooui-outline-control-move-up": "Помести нагоре",
-    "ooui-toolbar-more": "Повеќе"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ml.json b/resources/oojs/i18n/ml.json
deleted file mode 100644 (file)
index 355e337..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Kavya Manohar",
-            "Praveenp",
-            "Santhosh.thottingal",
-            "Vssun"
-        ]
-    },
-    "ooui-dialog-action-close": "അടയ്ക്കുക",
-    "ooui-outline-control-move-down": "ഇനം താഴേയ്ക്ക് മാറ്റുക",
-    "ooui-outline-control-move-up": "ഇനം മുകളിലേയ്ക്ക് മാറ്റുക",
-    "ooui-toolbar-more": "കൂടുതൽ"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/mr.json b/resources/oojs/i18n/mr.json
deleted file mode 100644 (file)
index d4db84f..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Kaajawa",
-            "Mahitgar",
-            "Praju23",
-            "V.narsikar",
-            "Ydyashad",
-            "संतोष दहिवळ"
-        ]
-    },
-    "ooui-dialog-action-close": "बंद करा",
-    "ooui-outline-control-move-down": "घटक (आयटम) खाली सरकवा",
-    "ooui-outline-control-move-up": "घटक (आयटम) वर सरकवा",
-    "ooui-toolbar-more": "अधिक"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ms.json b/resources/oojs/i18n/ms.json
deleted file mode 100644 (file)
index 21aef50..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Anakmalaysia",
-            "Aurora"
-        ]
-    },
-    "ooui-dialog-action-close": "Tutup",
-    "ooui-outline-control-move-down": "Alihkan perkara ke bawah",
-    "ooui-outline-control-move-up": "Alihkan perkara ke atas",
-    "ooui-toolbar-more": "Lagi"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/nap.json b/resources/oojs/i18n/nap.json
deleted file mode 100644 (file)
index 6b0b3ec..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Chelin",
-            "Chrisportelli",
-            "PiRSquared17"
-        ]
-    },
-    "ooui-dialog-action-close": "Chiure",
-    "ooui-toolbar-more": "Atro"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/nb.json b/resources/oojs/i18n/nb.json
deleted file mode 100644 (file)
index 7cdecaa..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Danmichaelo",
-            "Event",
-            "Jeblad",
-            "Laaknor",
-            "Njardarlogar"
-        ]
-    },
-    "ooui-dialog-action-close": "Lukk",
-    "ooui-outline-control-move-down": "Flytt ned",
-    "ooui-outline-control-move-up": "Flytt opp",
-    "ooui-toolbar-more": "Mer"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/nds-nl.json b/resources/oojs/i18n/nds-nl.json
deleted file mode 100644 (file)
index 81f8a43..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Servien"
-        ]
-    },
-    "ooui-dialog-action-close": "Sluten",
-    "ooui-outline-control-move-down": "Onderwarp ummeneer zetten",
-    "ooui-outline-control-move-up": "Onderwarp umhoge zetten"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/nds.json b/resources/oojs/i18n/nds.json
deleted file mode 100644 (file)
index d0806d0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Zylbath"
-        ]
-    },
-    "ooui-dialog-action-close": "Dichtmaken",
-    "ooui-outline-control-move-down": "Element na ünnen schuven",
-    "ooui-outline-control-move-up": "Element na baven schuven",
-    "ooui-toolbar-more": "Mehr"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ne.json b/resources/oojs/i18n/ne.json
deleted file mode 100644 (file)
index ae948c6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "RajeshPandey",
-            "सरोज कुमार ढकाल"
-        ]
-    }
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/nl.json b/resources/oojs/i18n/nl.json
deleted file mode 100644 (file)
index 75db0a7..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Bluyten",
-            "Breghtje",
-            "Catrope",
-            "Flightmare",
-            "Hansmuller",
-            "Jdforrester",
-            "Keegan",
-            "Konovalov",
-            "RajeshPandey",
-            "Romaine",
-            "SPQRobin",
-            "Saruman",
-            "Siebrand",
-            "Southparkfan",
-            "सरोज कुमार ढकाल"
-        ]
-    },
-    "ooui-dialog-action-close": "Sluiten",
-    "ooui-outline-control-move-down": "Item omlaag verplaatsen",
-    "ooui-outline-control-move-up": "Item omhoog verplaatsen",
-    "ooui-toolbar-more": "Meer"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/nn.json b/resources/oojs/i18n/nn.json
deleted file mode 100644 (file)
index dd86f5e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Jeblad",
-            "Njardarlogar"
-        ]
-    },
-    "ooui-dialog-action-close": "Lat att",
-    "ooui-outline-control-move-down": "Flytt element ned",
-    "ooui-outline-control-move-up": "Flytt element opp",
-    "ooui-toolbar-more": "Fleire"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/om.json b/resources/oojs/i18n/om.json
deleted file mode 100644 (file)
index dca7b7d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cedric31",
-            "Tumsaa"
-        ]
-    },
-    "ooui-dialog-action-close": "Cufi",
-    "ooui-outline-control-move-down": "Gad buusi",
-    "ooui-outline-control-move-up": "Ol baasi",
-    "ooui-toolbar-more": "Dabalata"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/or.json b/resources/oojs/i18n/or.json
deleted file mode 100644 (file)
index 35721a1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Odisha1",
-            "Psubhashish",
-            "ଶିତିକଣ୍ଠ ଦାଶ"
-        ]
-    },
-    "ooui-dialog-action-close": "ବନ୍ଦ କରିବେ"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/pa.json b/resources/oojs/i18n/pa.json
deleted file mode 100644 (file)
index 6c76d7f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Amikeco",
-            "Babanwalia",
-            "Bouron",
-            "Nasir8891"
-        ]
-    },
-    "ooui-dialog-action-close": "বন্ধ"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/pl.json b/resources/oojs/i18n/pl.json
deleted file mode 100644 (file)
index ba33322..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Babanwalia",
-            "Chrumps",
-            "Matma Rex",
-            "Mikołka",
-            "Nasir8891",
-            "Odie2",
-            "Rzuwig",
-            "Tar Lócesilion",
-            "Ty221",
-            "WTM",
-            "Woytecr",
-            "Wpedzich"
-        ]
-    },
-    "ooui-dialog-action-close": "Zamknij",
-    "ooui-outline-control-move-down": "Przenieś niżej",
-    "ooui-outline-control-move-up": "Przenieś wyżej",
-    "ooui-toolbar-more": "Więcej"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/pms.json b/resources/oojs/i18n/pms.json
deleted file mode 100644 (file)
index bb8f113..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Borichèt",
-            "Dragonòt",
-            "පසිඳු කාවින්ද"
-        ]
-    },
-    "ooui-dialog-action-close": "Saré",
-    "ooui-outline-control-move-down": "Fé calé giù l'element",
-    "ooui-outline-control-move-up": "Fé monté l'element",
-    "ooui-toolbar-more": "Ëd pi"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ps.json b/resources/oojs/i18n/ps.json
deleted file mode 100644 (file)
index 4f21707..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ahmed-Najib-Biabani-Ibrahimkhel"
-        ]
-    },
-    "ooui-dialog-action-close": "تړل",
-    "ooui-outline-control-move-down": "توکی ښکته راوړل",
-    "ooui-outline-control-move-up": "توکی پورته راوړل",
-    "ooui-toolbar-more": "نور"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/pt-br.json b/resources/oojs/i18n/pt-br.json
deleted file mode 100644 (file)
index f758660..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cainamarques",
-            "Dianakc",
-            "Fúlvio",
-            "Helder.wiki",
-            "HenriqueCrang",
-            "Jaideraf",
-            "Luckas",
-            "OTAVIO1981",
-            555
-        ]
-    },
-    "ooui-dialog-action-close": "Fechar",
-    "ooui-outline-control-move-down": "Mover item para baixo",
-    "ooui-outline-control-move-up": "Mover item para cima",
-    "ooui-toolbar-more": "Mais"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/pt.json b/resources/oojs/i18n/pt.json
deleted file mode 100644 (file)
index a4dba27..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cainamarques",
-            "Fúlvio",
-            "GoEThe",
-            "Hamilton Abreu",
-            "Helder.wiki",
-            "Jaideraf",
-            "Jdforrester",
-            "Luckas",
-            "Vitorvicentevalente"
-        ]
-    },
-    "ooui-dialog-action-close": "Fechar",
-    "ooui-outline-control-move-down": "Mover item para baixo",
-    "ooui-outline-control-move-up": "Mover item para cima",
-    "ooui-toolbar-more": "Mais"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/qqq.json b/resources/oojs/i18n/qqq.json
deleted file mode 100644 (file)
index 78a70d9..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Amire80",
-            "Beta16",
-            "Erik Moeller",
-            "Jdforrester",
-            "Lloffiwr",
-            "Mooeypoo",
-            "Mormegil",
-            "Nike",
-            "PoLuX124",
-            "Purodha",
-            "Raymond",
-            "Sagan",
-            "Sayak Sarkar",
-            "Shirayuki",
-            "Siebrand",
-            "Trevor Parscal"
-        ]
-    },
-    "ooui-dialog-action-close": "Label text for button to exit from dialog.\n\n{{Identical|Close}}",
-    "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-toolbar-more": "Label for the toolbar group that contains a list of all other available tools.\n{{Identical|More}}"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/qu.json b/resources/oojs/i18n/qu.json
deleted file mode 100644 (file)
index 9a412f5..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "AlimanRuna"
-        ]
-    },
-    "ooui-dialog-action-close": "Wichq'ay",
-    "ooui-outline-control-move-down": "Qallawata uraykuchiy",
-    "ooui-outline-control-move-up": "Qallawata huqariy",
-    "ooui-toolbar-more": "Aswan"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ro.json b/resources/oojs/i18n/ro.json
deleted file mode 100644 (file)
index 861b2fe..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "AlimanRuna",
-            "Firilacroco",
-            "Minisarm",
-            "Stelistcristi"
-        ]
-    },
-    "ooui-dialog-action-close": "Închide",
-    "ooui-outline-control-move-down": "Mută elementul mai jos",
-    "ooui-outline-control-move-up": "Mută elementul mai sus",
-    "ooui-toolbar-more": "Mai mult"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/roa-tara.json b/resources/oojs/i18n/roa-tara.json
deleted file mode 100644 (file)
index c7699d6..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Joetaras"
-        ]
-    },
-    "ooui-dialog-action-close": "Achiude",
-    "ooui-outline-control-move-down": "Spuèste 'a vôsce sotte",
-    "ooui-outline-control-move-up": "Spuèste 'a vôsce sus",
-    "ooui-toolbar-more": "De cchiù"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ru.json b/resources/oojs/i18n/ru.json
deleted file mode 100644 (file)
index be7c6a5..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Amire80",
-            "DR",
-            "Eugrus",
-            "Iluvatar",
-            "KPu3uC B Poccuu",
-            "Kalan",
-            "MaxBioHazard",
-            "NBS",
-            "Niklem",
-            "Okras",
-            "Ole Yves",
-            "Putnik",
-            "Sunpriat",
-            "Yury Katkov",
-            "Умар"
-        ]
-    },
-    "ooui-dialog-action-close": "Закрыть",
-    "ooui-outline-control-move-down": "Переместить элемент вниз",
-    "ooui-outline-control-move-up": "Переместить элемент вверх",
-    "ooui-toolbar-more": "Ещё"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/sah.json b/resources/oojs/i18n/sah.json
deleted file mode 100644 (file)
index 9b3fcc8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Gazeb",
-            "HalanTul"
-        ]
-    },
-    "ooui-dialog-action-close": "Сап"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/scn.json b/resources/oojs/i18n/scn.json
deleted file mode 100644 (file)
index a699911..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Gazeb",
-            "Gmelfi",
-            "HalanTul"
-        ]
-    },
-    "ooui-dialog-action-close": "Chiùi",
-    "ooui-outline-control-move-down": "Sposta di sutta",
-    "ooui-outline-control-move-up": "Sposta di supra",
-    "ooui-toolbar-more": "Àutri cosi"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/sh.json b/resources/oojs/i18n/sh.json
deleted file mode 100644 (file)
index 5e29980..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "OC Ripper"
-        ]
-    },
-    "ooui-dialog-action-close": "Zatvori",
-    "ooui-outline-control-move-down": "Pomakni stavku dolje",
-    "ooui-outline-control-move-up": "Pomakni stavku gore"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/si.json b/resources/oojs/i18n/si.json
deleted file mode 100644 (file)
index cf7a9fd..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Singhalawap",
-            "පසිඳු කාවින්ද",
-            "ශ්වෙත"
-        ]
-    },
-    "ooui-dialog-action-close": "නිමවන්න",
-    "ooui-outline-control-move-down": "අයිතමය පහලටදමන්න",
-    "ooui-outline-control-move-up": "අයිතමය ඉහලටදමන්න"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/sk.json b/resources/oojs/i18n/sk.json
deleted file mode 100644 (file)
index 60b6f43..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Mimarik",
-            "Teslaton"
-        ]
-    },
-    "ooui-dialog-action-close": "Zatvoriť",
-    "ooui-outline-control-move-down": "Posunúť položku nadol",
-    "ooui-outline-control-move-up": "Posunúť položku nahor",
-    "ooui-toolbar-more": "Viac"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/sl.json b/resources/oojs/i18n/sl.json
deleted file mode 100644 (file)
index d5bffd9..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Dbc334",
-            "Eleassar",
-            "Pinky sl",
-            "Yerpo"
-        ]
-    },
-    "ooui-dialog-action-close": "Zapri",
-    "ooui-outline-control-move-down": "Prestavi predmet nižje",
-    "ooui-outline-control-move-up": "Prestavi predmet višje",
-    "ooui-toolbar-more": "Več"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/sq.json b/resources/oojs/i18n/sq.json
deleted file mode 100644 (file)
index 424f1be..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Euriditi"
-        ]
-    },
-    "ooui-dialog-action-close": "Mbylle",
-    "ooui-outline-control-move-down": "Zhvendose artikullin më poshtë",
-    "ooui-outline-control-move-up": "Zhvendose artikullin më lart",
-    "ooui-toolbar-more": "Më tepër..."
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/sr-ec.json b/resources/oojs/i18n/sr-ec.json
deleted file mode 100644 (file)
index 973baec..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Milicevic01",
-            "Nikola Smolenski",
-            "Милан Јелисавчић"
-        ]
-    },
-    "ooui-dialog-action-close": "Затвори",
-    "ooui-outline-control-move-down": "Премести ставку на доле",
-    "ooui-outline-control-move-up": "Премести ставку на горе",
-    "ooui-toolbar-more": "Више"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/sv.json b/resources/oojs/i18n/sv.json
deleted file mode 100644 (file)
index 74d654b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ainali",
-            "Haxpett",
-            "Jopparn",
-            "Knuckles",
-            "Magol",
-            "Milicevic01",
-            "Per",
-            "Sendelbach",
-            "Skalman",
-            "WikiPhoenix"
-        ]
-    },
-    "ooui-dialog-action-close": "Stäng",
-    "ooui-outline-control-move-down": "Flytta ned objekt",
-    "ooui-outline-control-move-up": "Flytta upp objekt",
-    "ooui-toolbar-more": "Mer"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/sw.json b/resources/oojs/i18n/sw.json
deleted file mode 100644 (file)
index 1c61b06..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Lloffiwr",
-            "Muddyb Blast Producer"
-        ]
-    },
-    "ooui-dialog-action-close": "Funga",
-    "ooui-outline-control-move-down": "Sogeza kipengee chini",
-    "ooui-outline-control-move-up": "Sogeza kipengee juu",
-    "ooui-toolbar-more": "Zaidi"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ta.json b/resources/oojs/i18n/ta.json
deleted file mode 100644 (file)
index a9795fd..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Jayarathina",
-            "Sank",
-            "Shanmugamp7",
-            "மதனாஹரன்"
-        ]
-    },
-    "ooui-dialog-action-close": "மூடுக"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/te.json b/resources/oojs/i18n/te.json
deleted file mode 100644 (file)
index a1f1285..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Arjunaraoc",
-            "Jayarathina",
-            "Sank",
-            "Shanmugamp7",
-            "Veeven",
-            "Visdaviva",
-            "மதனாஹரன்"
-        ]
-    },
-    "ooui-dialog-action-close": "మూయి"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/th.json b/resources/oojs/i18n/th.json
deleted file mode 100644 (file)
index b7ee05a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Supasate",
-            "Taweetham"
-        ]
-    },
-    "ooui-dialog-action-close": "ปิด",
-    "ooui-outline-control-move-down": "เลื่อนรายการลง",
-    "ooui-outline-control-move-up": "ย้ายรายการขึ้น"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/tl.json b/resources/oojs/i18n/tl.json
deleted file mode 100644 (file)
index a073882..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "AnakngAraw",
-            "Sky Harbor"
-        ]
-    },
-    "ooui-dialog-action-close": "Isara",
-    "ooui-outline-control-move-down": "Ilipat ang aytem pababa",
-    "ooui-outline-control-move-up": "Ilipat ang aytem pataas",
-    "ooui-toolbar-more": "Marami pa"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/tr.json b/resources/oojs/i18n/tr.json
deleted file mode 100644 (file)
index 94d34a2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Emperyan",
-            "Incelemeelemani",
-            "LuCKY",
-            "Maidis",
-            "Rapsar",
-            "Talha Samil Cakir",
-            "TurkishStyles"
-        ]
-    },
-    "ooui-dialog-action-close": "Kapat",
-    "ooui-outline-control-move-down": "Ögeyi aşağı taşı",
-    "ooui-outline-control-move-up": "Ögeyi yukarı taşı",
-    "ooui-toolbar-more": "Daha fazla"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/tt-cyrl.json b/resources/oojs/i18n/tt-cyrl.json
deleted file mode 100644 (file)
index 1c0bd90..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Ajdar"
-        ]
-    },
-    "ooui-dialog-action-close": "Ябу",
-    "ooui-outline-control-move-down": "Элементны аска күчерү",
-    "ooui-outline-control-move-up": "Элементны өскә күчерү"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/ug-arab.json b/resources/oojs/i18n/ug-arab.json
deleted file mode 100644 (file)
index efba086..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Sahran",
-            "Tel'et",
-            "Tifinaghes"
-        ]
-    }
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/uk.json b/resources/oojs/i18n/uk.json
deleted file mode 100644 (file)
index 9a47ad7..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "AS",
-            "Aced",
-            "Ahonc",
-            "Andriykopanytsia",
-            "Base",
-            "Perohanych",
-            "RLuts",
-            "Sahran",
-            "Sergento",
-            "Steve.rusyn",
-            "SteveR",
-            "Tel'et",
-            "Tifinaghes",
-            "Ата"
-        ]
-    },
-    "ooui-dialog-action-close": "Закрити",
-    "ooui-outline-control-move-down": "Перемістити елемент униз",
-    "ooui-outline-control-move-up": "Перемістити елемент вгору",
-    "ooui-toolbar-more": "Більше"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/uz.json b/resources/oojs/i18n/uz.json
deleted file mode 100644 (file)
index 473fc75..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "CoderSI",
-            "Noor2020",
-            "Sociologist",
-            "පසිඳු කාවින්ද"
-        ]
-    },
-    "ooui-dialog-action-close": "Yopish",
-    "ooui-outline-control-move-down": "Elementni pastga koʻchirish",
-    "ooui-outline-control-move-up": "Elementni yuqoriga koʻchirish",
-    "ooui-toolbar-more": "Yana"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/vec.json b/resources/oojs/i18n/vec.json
deleted file mode 100644 (file)
index 01833f7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Candalua",
-            "GatoSelvadego"
-        ]
-    },
-    "ooui-dialog-action-close": "Sara",
-    "ooui-outline-control-move-down": "Sposta in baso",
-    "ooui-outline-control-move-up": "Sposta in sima",
-    "ooui-toolbar-more": "Altro"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/vi.json b/resources/oojs/i18n/vi.json
deleted file mode 100644 (file)
index b545ce6..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Cheers!",
-            "Jdforrester",
-            "Minh Nguyen"
-        ]
-    },
-    "ooui-dialog-action-close": "Đóng",
-    "ooui-outline-control-move-down": "Chuyển mục xuống",
-    "ooui-outline-control-move-up": "Chuyển mục lên",
-    "ooui-toolbar-more": "Thêm"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/vo.json b/resources/oojs/i18n/vo.json
deleted file mode 100644 (file)
index 2ed7e2f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Malafaya"
-        ]
-    },
-    "ooui-dialog-action-close": "Färmükön",
-    "ooui-toolbar-more": "Pluikos"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/wuu.json b/resources/oojs/i18n/wuu.json
deleted file mode 100644 (file)
index 72aa48b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Malafaya",
-            "十弌"
-        ]
-    },
-    "ooui-toolbar-more": "還多"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/yi.json b/resources/oojs/i18n/yi.json
deleted file mode 100644 (file)
index ab5c510..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Malafaya",
-            "פוילישער",
-            "十弌"
-        ]
-    },
-    "ooui-dialog-action-close": "שליסן",
-    "ooui-outline-control-move-down": "רוקן עלעמענט אראפ",
-    "ooui-outline-control-move-up": "רוקן עלעמענט ארויף",
-    "ooui-toolbar-more": "נאך"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/yo.json b/resources/oojs/i18n/yo.json
deleted file mode 100644 (file)
index f71d3dd..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Demmy"
-        ]
-    },
-    "ooui-dialog-action-close": "Ìpadé",
-    "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"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/zh-hans.json b/resources/oojs/i18n/zh-hans.json
deleted file mode 100644 (file)
index 46cbae3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Anakmalaysia",
-            "Bencmq",
-            "Demmy",
-            "Hydra",
-            "Hzy980512",
-            "Liangent",
-            "Liuxinyu970226",
-            "Qiyue2001",
-            "Shirayuki",
-            "Shizhao",
-            "TianyinLee",
-            "Xiaomingyan",
-            "Yfdyh000",
-            "Zhangjintao",
-            "乌拉跨氪"
-        ]
-    },
-    "ooui-dialog-action-close": "关闭",
-    "ooui-outline-control-move-down": "下移项",
-    "ooui-outline-control-move-up": "上移项",
-    "ooui-toolbar-more": "更多"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/zh-hant.json b/resources/oojs/i18n/zh-hant.json
deleted file mode 100644 (file)
index 9aace2f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-    "@metadata": {
-        "authors": [
-            "Anakmalaysia",
-            "Ch.Andrew",
-            "Hydra",
-            "Justincheng12345",
-            "Liflon",
-            "Liuxinyu970226",
-            "Qiyue2001",
-            "Radish10cm",
-            "Shirayuki",
-            "Simon Shek",
-            "Spring Roll Conan",
-            "Waihorace"
-        ]
-    },
-    "ooui-dialog-action-close": "關閉",
-    "ooui-outline-control-move-down": "向下移項",
-    "ooui-outline-control-move-up": "向上移項",
-    "ooui-toolbar-more": "更多"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/zh-hk.json b/resources/oojs/i18n/zh-hk.json
deleted file mode 100644 (file)
index 60e8fbd..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "@metadata": [],
-    "ooui-dialog-action-close": "關閉"
-}
\ No newline at end of file
diff --git a/resources/oojs/i18n/zh-tw.json b/resources/oojs/i18n/zh-tw.json
deleted file mode 100644 (file)
index f7987e5..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-    "@metadata": [],
-    "ooui-dialog-action-close": "關閉",
-    "ooui-outline-control-move-down": "向下移",
-    "ooui-outline-control-move-up": "向上移",
-    "ooui-toolbar-more": "更多"
-}
\ No newline at end of file
diff --git a/resources/oojs/images/fade-down.png b/resources/oojs/images/fade-down.png
deleted file mode 100644 (file)
index 50c7931..0000000
Binary files a/resources/oojs/images/fade-down.png and /dev/null differ
diff --git a/resources/oojs/images/fade-up.png b/resources/oojs/images/fade-up.png
deleted file mode 100644 (file)
index 7a0cb87..0000000
Binary files a/resources/oojs/images/fade-up.png and /dev/null differ
diff --git a/resources/oojs/images/icons/accept.png b/resources/oojs/images/icons/accept.png
deleted file mode 100644 (file)
index 1075110..0000000
Binary files a/resources/oojs/images/icons/accept.png and /dev/null differ
diff --git a/resources/oojs/images/icons/accept.svg b/resources/oojs/images/icons/accept.svg
deleted file mode 100644 (file)
index df78186..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="apply" style="opacity:0.75;">
-       <polygon id="check" style="fill-rule:evenodd;clip-rule:evenodd;" points="19.062,5.139 17.418,4 8.867,16.357 5.413,12.903 4,14.316 9.021,19.338"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/add-item.png b/resources/oojs/images/icons/add-item.png
deleted file mode 100644 (file)
index aa36cd0..0000000
Binary files a/resources/oojs/images/icons/add-item.png and /dev/null differ
diff --git a/resources/oojs/images/icons/add-item.svg b/resources/oojs/images/icons/add-item.svg
deleted file mode 100644 (file)
index ff95399..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="add-item">
-    <path d="M13,8 L11,8 L11,11 L8,11 L8,13 L11,13 L11,16 L13,16 L13,13 L16,13 L16,11 L13,11 z" fill="#000000"/>
-  </g>
-  <defs/>
-</svg>
diff --git a/resources/oojs/images/icons/advanced.png b/resources/oojs/images/icons/advanced.png
deleted file mode 100644 (file)
index 7f5ada5..0000000
Binary files a/resources/oojs/images/icons/advanced.png and /dev/null differ
diff --git a/resources/oojs/images/icons/advanced.svg b/resources/oojs/images/icons/advanced.svg
deleted file mode 100644 (file)
index 3e87cab..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="settings" style="opacity:0.75;">
-       <path id="gear" style="fill-rule:evenodd;clip-rule:evenodd;" d="M20.869,13.476C20.948,12.994,21,12.504,21,12
-               s-0.052-0.994-0.131-1.476l-2.463-0.259c-0.149-0.556-0.367-1.082-0.648-1.57l1.558-1.924c-0.576-0.806-1.281-1.511-2.087-2.087
-               l-1.924,1.558c-0.488-0.281-1.015-0.499-1.57-0.648l-0.259-2.463C12.994,3.052,12.504,3,12,3s-0.994,0.052-1.476,0.131
-               l-0.259,2.463C9.71,5.743,9.184,5.961,8.695,6.242L6.771,4.685C5.966,5.261,5.261,5.966,4.685,6.771l1.558,1.924
-               c-0.281,0.488-0.499,1.015-0.648,1.57l-2.463,0.259C3.052,11.006,3,11.496,3,12s0.052,0.994,0.131,1.476l2.463,0.259
-               c0.149,0.556,0.367,1.082,0.648,1.57l-1.558,1.924c0.576,0.806,1.281,1.511,2.087,2.087l1.924-1.558
-               c0.488,0.281,1.015,0.499,1.57,0.648l0.259,2.463C11.006,20.948,11.496,21,12,21s0.994-0.052,1.476-0.131l0.259-2.463
-               c0.556-0.149,1.082-0.367,1.57-0.648l1.924,1.558c0.806-0.576,1.511-1.281,2.087-2.087l-1.558-1.924
-               c0.281-0.488,0.499-1.015,0.648-1.57L20.869,13.476z M12,15.998c-2.209,0-3.998-1.789-3.998-3.998S9.791,8.002,12,8.002
-               S15.998,9.791,15.998,12S14.209,15.998,12,15.998z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/alert.png b/resources/oojs/images/icons/alert.png
deleted file mode 100644 (file)
index 992ea2a..0000000
Binary files a/resources/oojs/images/icons/alert.png and /dev/null differ
diff --git a/resources/oojs/images/icons/alert.svg b/resources/oojs/images/icons/alert.svg
deleted file mode 100644 (file)
index 886a7c0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="alert" style="opacity:0.75;">
-       <rect id="point" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
-       <polygon id="stroke" style="fill-rule:evenodd;clip-rule:evenodd;" points="13.516,10 10.516,10 11,15 13,15"/>
-       <path id="triangle" d="M12.017,5.974L19.536,19H4.496L12.017,5.974 M12.017,3.5c-0.544,0-1.088,0.357-1.5,1.071L2.532,18.402 C1.707,19.831,2.382,21,4.032,21H20c1.65,0,2.325-1.169,1.5-2.599L13.517,4.572C13.104,3.857,12.561,3.5,12.017,3.5L12.017,3.5z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/arched-arrow-ltr.png b/resources/oojs/images/icons/arched-arrow-ltr.png
deleted file mode 100644 (file)
index 5db1c4d..0000000
Binary files a/resources/oojs/images/icons/arched-arrow-ltr.png and /dev/null differ
diff --git a/resources/oojs/images/icons/arched-arrow-ltr.svg b/resources/oojs/images/icons/arched-arrow-ltr.svg
deleted file mode 100644 (file)
index 5b343a5..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="arched-arrow-ltr" style="opacity:0.75;">
-       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M19.925,14.937l-2.391-6.901l-1.48,2.329 c-0.964-0.845-2.699-1.85-5.513-1.823c-4.887,0.046-6.524,4.244-6.524,4.244s2.753-2.639,6.925-1.949 c1.729,0.286,3.007,1.206,3.675,1.791l-1.474,2.319L19.925,14.937z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/arched-arrow-rtl.png b/resources/oojs/images/icons/arched-arrow-rtl.png
deleted file mode 100644 (file)
index 7931971..0000000
Binary files a/resources/oojs/images/icons/arched-arrow-rtl.png and /dev/null differ
diff --git a/resources/oojs/images/icons/arched-arrow-rtl.svg b/resources/oojs/images/icons/arched-arrow-rtl.svg
deleted file mode 100644 (file)
index bb5f10e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="arched-arrow-rtl" style="opacity:0.75;">
-       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M13.401,8.542c-2.814-0.027-4.549,0.978-5.513,1.823 l-1.48-2.329l-2.391,6.901l6.782,0.009l-1.474-2.319c0.668-0.584,1.945-1.504,3.675-1.791c4.172-0.69,6.925,1.949,6.925,1.949 S18.288,8.588,13.401,8.542z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/check.png b/resources/oojs/images/icons/check.png
deleted file mode 100644 (file)
index 82c3cb4..0000000
Binary files a/resources/oojs/images/icons/check.png and /dev/null differ
diff --git a/resources/oojs/images/icons/check.svg b/resources/oojs/images/icons/check.svg
deleted file mode 100644 (file)
index e67cd6c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="check">
-    <path d="M7.105,13.473 L8.527,12.05 L10.428,13.952 L15.238,7 L16.895,8.148 L10.635,17 z" fill="#000000"/>
-  </g>
-  <defs/>
-</svg>
diff --git a/resources/oojs/images/icons/clear.png b/resources/oojs/images/icons/clear.png
deleted file mode 100644 (file)
index 697dd62..0000000
Binary files a/resources/oojs/images/icons/clear.png and /dev/null differ
diff --git a/resources/oojs/images/icons/clear.svg b/resources/oojs/images/icons/clear.svg
deleted file mode 100644 (file)
index d83eb02..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="clear" style="opacity:0.75;">
-       <path id="circle_with_strike" style="fill-rule:evenodd;clip-rule:evenodd;" d="M11.999,5.022c-3.853,0-6.977,3.124-6.977,6.978 c0,3.853,3.124,6.978,6.977,6.978c3.854,0,6.979-3.125,6.979-6.978C18.978,8.146,15.853,5.022,11.999,5.022z M6.886,12 c0-1.092,0.572-3.25,0.93-2.929l7.113,7.113c0.488,0.525-1.837,0.931-2.93,0.931C9.174,17.114,6.886,14.824,6.886,12z M16.184,14.929L9.07,7.816c-0.445-0.483,1.837-0.931,2.929-0.931c2.827,0,5.115,2.289,5.115,5.114 C17.114,13.092,16.75,15.542,16.184,14.929z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/close.png b/resources/oojs/images/icons/close.png
deleted file mode 100644 (file)
index f7eed9f..0000000
Binary files a/resources/oojs/images/icons/close.png and /dev/null differ
diff --git a/resources/oojs/images/icons/close.svg b/resources/oojs/images/icons/close.svg
deleted file mode 100644 (file)
index a0118c2..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="close" style="opacity:0.75;">
-       <polygon id="x" style="fill-rule:evenodd;clip-rule:evenodd;" points="18.717,6.697 17.303,5.283 12,10.586 6.697,5.283 5.283,6.697 10.586,12 5.283,17.303 6.697,18.717 12,13.414 17.303,18.717 18.717,17.303 13.414,12            "/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/code.png b/resources/oojs/images/icons/code.png
deleted file mode 100644 (file)
index a5ebdbf..0000000
Binary files a/resources/oojs/images/icons/code.png and /dev/null differ
diff --git a/resources/oojs/images/icons/code.svg b/resources/oojs/images/icons/code.svg
deleted file mode 100644 (file)
index 6f1ed53..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-        width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
-<g id="code" opacity="0.75">
-       <path id="left-bracket" d="M4,12v-1h1c1,0,1,0,1-1V7.614C6,7.1,6.024,6.718,6.073,6.472C6.127,6.22,6.212,6.009,6.33,5.839
-               C6.534,5.56,6.803,5.364,7.138,5.255C7.473,5.14,8.01,5,8.973,5H10v1H9.248c-0.457,0-0.77,0.191-0.936,0.408
-               C8.145,6.623,8,6.853,8,7.476v1.857c0,0.729-0.041,1.18-0.244,1.493c-0.2,0.307-0.562,0.529-1.09,0.667
-               c0.535,0.155,0.9,0.385,1.096,0.688C7.961,12.484,8,12.938,8,13.665v1.862c0,0.619,0.145,0.848,0.312,1.062
-               c0.166,0.22,0.479,0.407,0.936,0.407L10,17l0,0v1H8.973c-0.963,0-1.5-0.133-1.835-0.248c-0.335-0.109-0.604-0.307-0.808-0.591
-               c-0.118-0.165-0.203-0.374-0.257-0.625C6.024,16.283,6,15.9,6,15.387V13c0-1,0-1-1-1H4z"/>
-       <use transform="matrix(-1,0,0,1,24,0)" id="right-bracket" x="0" y="0" width="24" height="24" xlink:href="#left-bracket" />
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/collapse.png b/resources/oojs/images/icons/collapse.png
deleted file mode 100644 (file)
index 38b796f..0000000
Binary files a/resources/oojs/images/icons/collapse.png and /dev/null differ
diff --git a/resources/oojs/images/icons/collapse.svg b/resources/oojs/images/icons/collapse.svg
deleted file mode 100644 (file)
index a89cebf..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="collapse" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="6.697,15.714 12,10.412 17.303,15.714 18.717,14.3 12,7.583 5.283,14.3"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/comment.png b/resources/oojs/images/icons/comment.png
deleted file mode 100644 (file)
index 9546455..0000000
Binary files a/resources/oojs/images/icons/comment.png and /dev/null differ
diff --git a/resources/oojs/images/icons/comment.svg b/resources/oojs/images/icons/comment.svg
deleted file mode 100644 (file)
index e052935..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="comment" style="opacity:0.75;">
-       <path id="speech_bubble" style="fill-rule:evenodd;clip-rule:evenodd;" d="M15,6H9C7.343,6,6,7.344,6,9v4c0,1.656,1.343,3,3,3v3 l3-3h3c1.657,0,3-1.344,3-3V9C18,7.344,16.657,6,15,6z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/expand.png b/resources/oojs/images/icons/expand.png
deleted file mode 100644 (file)
index e90aca1..0000000
Binary files a/resources/oojs/images/icons/expand.png and /dev/null differ
diff --git a/resources/oojs/images/icons/expand.svg b/resources/oojs/images/icons/expand.svg
deleted file mode 100644 (file)
index b542f5f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="expand" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="17.303,8.283 12,13.586 6.697,8.283 5.283,9.697 12,16.414 18.717,9.697"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/help.png b/resources/oojs/images/icons/help.png
deleted file mode 100644 (file)
index dca745b..0000000
Binary files a/resources/oojs/images/icons/help.png and /dev/null differ
diff --git a/resources/oojs/images/icons/help.svg b/resources/oojs/images/icons/help.svg
deleted file mode 100644 (file)
index c68bdda..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="help" style="opacity:0.75;">
-       <path id="circle" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12.001,2.085c-5.478,0-9.916,4.438-9.916,9.916 c0,5.476,4.438,9.914,9.916,9.914c5.476,0,9.914-4.438,9.914-9.914C21.915,6.523,17.477,2.085,12.001,2.085z M12.002,20.085 c-4.465,0-8.084-3.619-8.084-8.083c0-4.465,3.619-8.084,8.084-8.084c4.464,0,8.083,3.619,8.083,8.084 C20.085,16.466,16.466,20.085,12.002,20.085z"/>
-       <g id="question_mark">
-               <path id="top" style="fill-rule:evenodd;clip-rule:evenodd;" d="M11.766,6.688c-2.5,0-3.219,2.188-3.219,2.188l1.411,0.854 c0,0,0.298-0.791,0.901-1.229c0.516-0.375,1.625-0.625,2.219,0.125c0.701,0.885-0.17,1.587-1.078,2.719 C11.047,12.531,11,15,11,15h1.969c0,0,0.135-2.318,1.041-3.381c0.603-0.707,1.443-1.338,1.443-2.494S14.266,6.688,11.766,6.688z"/>
-               <rect id="bottom" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
-       </g>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/history.png b/resources/oojs/images/icons/history.png
deleted file mode 100644 (file)
index c049931..0000000
Binary files a/resources/oojs/images/icons/history.png and /dev/null differ
diff --git a/resources/oojs/images/icons/history.svg b/resources/oojs/images/icons/history.svg
deleted file mode 100644 (file)
index 40c0ae3..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="history" style="opacity:0.75;">
-       <path id="clock_hands" style="fill-rule:evenodd;clip-rule:evenodd;" d="M17.26,15.076c0,0-2.385-1.935-4.005-3.062 c0.72-2.397,1.702-6.559,1.702-6.559s-4.35,5.363-4.877,6.699c-0.463,1.168,1.459,2.209,2.346,1.678 C14.326,14.383,17.26,15.076,17.26,15.076z"/>
-       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12.086,2.085c-5.478,0-9.916,4.438-9.916,9.916 c0,1.783,0.476,3.454,1.301,4.898l-2.223,2.04h5.688v-5.219l-2.066,1.896c-0.55-1.088-0.866-2.312-0.866-3.615 c0-4.465,3.619-8.084,8.084-8.084c4.464,0,8.083,3.619,8.083,8.084c0,4.464-3.619,8.083-8.083,8.083 c-1.145,0-2.228-0.247-3.213-0.678l-0.833,1.634c1.235,0.557,2.602,0.874,4.045,0.874c5.476,0,9.914-4.438,9.914-9.914 C22,6.523,17.562,2.085,12.086,2.085z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/link.png b/resources/oojs/images/icons/link.png
deleted file mode 100644 (file)
index 7dfa268..0000000
Binary files a/resources/oojs/images/icons/link.png and /dev/null differ
diff --git a/resources/oojs/images/icons/link.svg b/resources/oojs/images/icons/link.svg
deleted file mode 100644 (file)
index dadf69c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="link" style="opacity:0.75;">
-       <path id="right" d="M19.188,12.001c0,1.1-0.891,2.015-1.988,2.015l-4.195-0.015C13.543,15.089,13.968,16,15.002,16h3
-               C19.658,16,21,13.657,21,12s-1.342-4-2.998-4h-3c-1.034,0-1.459,0.911-1.998,1.999l4.195-0.015
-               C18.297,9.984,19.188,10.901,19.188,12.001z"/>
-       <path id="center" d="M8,12c0,0.535,0.42,1,0.938,1h6.109c0.518,0,0.938-0.465,0.938-1c0-0.534-0.42-1-0.938-1H8.938
-               C8.42,11,8,11.466,8,12z"/>
-       <path id="left" d="M4.816,11.999c0-1.1,0.891-2.015,1.988-2.015L11,9.999C10.461,8.911,10.036,8,9.002,8h-3
-               c-1.656,0-2.998,2.343-2.998,4s1.342,4,2.998,4h3c1.034,0,1.459-0.911,1.998-1.999l-4.195,0.015
-               C5.707,14.016,4.816,13.099,4.816,11.999z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/menu.png b/resources/oojs/images/icons/menu.png
deleted file mode 100644 (file)
index b5ac60f..0000000
Binary files a/resources/oojs/images/icons/menu.png and /dev/null differ
diff --git a/resources/oojs/images/icons/menu.svg b/resources/oojs/images/icons/menu.svg
deleted file mode 100644 (file)
index 657fab2..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="menu" style="opacity:0.75;">
-       <path id="lines" d="M6,15h12c0.553,0,1,0.447,1,1v1c0,0.553-0.447,1-1,1H6c-0.553,0-1-0.447-1-1v-1C5,15.447,5.447,15,6,15z M5,11v1
-               c0,0.553,0.447,1,1,1h12c0.553,0,1-0.447,1-1v-1c0-0.553-0.447-1-1-1H6C5.447,10,5,10.447,5,11z M5,6v1c0,0.553,0.447,1,1,1h12
-               c0.553,0,1-0.447,1-1V6c0-0.553-0.447-1-1-1H6C5.447,5,5,5.447,5,6z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/move-ltr.png b/resources/oojs/images/icons/move-ltr.png
deleted file mode 100644 (file)
index ded5f05..0000000
Binary files a/resources/oojs/images/icons/move-ltr.png and /dev/null differ
diff --git a/resources/oojs/images/icons/move-ltr.svg b/resources/oojs/images/icons/move-ltr.svg
deleted file mode 100644 (file)
index a378a5d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="move-ltr" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="8.935,7.181 14.237,12.483 8.935,17.786
-               10.349,19.2 17.065,12.483 10.349,5.767"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/move-rtl.png b/resources/oojs/images/icons/move-rtl.png
deleted file mode 100644 (file)
index fc6e62d..0000000
Binary files a/resources/oojs/images/icons/move-rtl.png and /dev/null differ
diff --git a/resources/oojs/images/icons/move-rtl.svg b/resources/oojs/images/icons/move-rtl.svg
deleted file mode 100644 (file)
index c0b334b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="move-rtl" style="opacity:0.75;">
-       <polygon id="arrow_9_" style="fill-rule:evenodd;clip-rule:evenodd;" points="15.065,17.786 9.763,12.483 15.065,7.181
-               13.651,5.767 6.935,12.483 13.651,19.2"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/picture.png b/resources/oojs/images/icons/picture.png
deleted file mode 100644 (file)
index faf8af9..0000000
Binary files a/resources/oojs/images/icons/picture.png and /dev/null differ
diff --git a/resources/oojs/images/icons/picture.svg b/resources/oojs/images/icons/picture.svg
deleted file mode 100644 (file)
index 078ce10..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="picture" style="opacity:0.75;">
-       <path id="frame" style="fill-rule:evenodd;clip-rule:evenodd;" d="M18,4H6C4,3.993,3,4.993,3,6.993L3.014,16C3,18,4,18.988,6,19h12
-               c2-0.012,2.994-1,3-3.006V6.993C20.994,4.993,20,3.993,18,4z M19,17H5V6h14V17z"/>
-       <polygon id="mountains" style="fill-rule:evenodd;clip-rule:evenodd;" points="6,13.5 9.5,10 11.828,12.312 10.516,13.406
-               11.391,14.438 15.5,11 18,13 18,16 6,16"/>
-       <polygon id="sky" style="fill-rule:evenodd;clip-rule:evenodd;" points="6,12 9.516,7.844 12.562,11.016 15.5,9 18,11 18,7 6,7"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/remove-item.png b/resources/oojs/images/icons/remove-item.png
deleted file mode 100644 (file)
index 2f11db3..0000000
Binary files a/resources/oojs/images/icons/remove-item.png and /dev/null differ
diff --git a/resources/oojs/images/icons/remove-item.svg b/resources/oojs/images/icons/remove-item.svg
deleted file mode 100644 (file)
index b95e7d3..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="remove-item">
-    <path d="M8,11 L16,11 L16,13 L8,13 z" fill="#000000"/>
-  </g>
-  <defs/>
-</svg>
diff --git a/resources/oojs/images/icons/remove.png b/resources/oojs/images/icons/remove.png
deleted file mode 100644 (file)
index d7e116c..0000000
Binary files a/resources/oojs/images/icons/remove.png and /dev/null differ
diff --git a/resources/oojs/images/icons/remove.svg b/resources/oojs/images/icons/remove.svg
deleted file mode 100644 (file)
index 17c8d39..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="remove" style="opacity:0.75;">
-       <path id="trash_can" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12,10h-1v6h1V10z M10,10H9v6h1V10z M14,10h-1v6h1V10z
-                M14,6V5H9v1H6v3h1v7.966l1,1.031v-0.074V18h6.984L15,17.982v0.015l1-1.031V9h1V6H14z M15,17H8V9h7V17z M16,8H7V7h9V8z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/search.png b/resources/oojs/images/icons/search.png
deleted file mode 100644 (file)
index df29792..0000000
Binary files a/resources/oojs/images/icons/search.png and /dev/null differ
diff --git a/resources/oojs/images/icons/search.svg b/resources/oojs/images/icons/search.svg
deleted file mode 100644 (file)
index 37feda4..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="search" style="opacity:0.75;">
-       <path id="magnifying_glass" d="M16.021,15.96l-2.374-2.375c-0.048-0.047-0.105-0.079-0.169-0.099c0.403-0.566,0.643-1.26,0.643-2.009
-               C14.12,9.557,12.563,8,10.644,8c-1.921,0-3.478,1.557-3.478,3.478c0,1.92,1.557,3.477,3.478,3.477c0.749,0,1.442-0.239,2.01-0.643
-               c0.019,0.063,0.051,0.121,0.098,0.169l2.375,2.374c0.19,0.189,0.543,0.143,0.79-0.104S16.21,16.15,16.021,15.96z M10.644,13.69
-               c-1.221,0-2.213-0.991-2.213-2.213c0-1.221,0.992-2.213,2.213-2.213c1.222,0,2.213,0.992,2.213,2.213
-               C12.856,12.699,11.865,13.69,10.644,13.69z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/settings.png b/resources/oojs/images/icons/settings.png
deleted file mode 100644 (file)
index b1b35e9..0000000
Binary files a/resources/oojs/images/icons/settings.png and /dev/null differ
diff --git a/resources/oojs/images/icons/settings.svg b/resources/oojs/images/icons/settings.svg
deleted file mode 100644 (file)
index 1464a79..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="settings" opacity="0.75">
-    <path d="M3,4 L6,4 L6,6 L3,6 z" fill="#000000"/>
-    <path d="M12,4 L21,4 L21,6 L12,6 z" fill="#000000"/>
-    <path d="M8,3 L10,3 C10.552,3 11,3.448 11,4 L11,6 C11,6.552 10.552,7 10,7 L8,7 C7.448,7 7,6.552 7,6 L7,4 C7,3.448 7.448,3 8,3 z" fill="#000000"/>
-    <path d="M3,11 L12,11 L12,13 L3,13 z" fill="#000000"/>
-    <path d="M18,11 L21,11 L21,13 L18,13 z" fill="#000000"/>
-    <path d="M14,10 L16,10 C16.552,10 17,10.448 17,11 L17,13 C17,13.552 16.552,14 16,14 L14,14 C13.448,14 13,13.552 13,13 L13,11 C13,10.448 13.448,10 14,10 z" fill="#000000"/>
-    <path d="M3,18 L9,18 L9,20 L3,20 z" fill="#000000"/>
-    <path d="M15,18 L21,18 L21,20 L15,20 z" fill="#000000"/>
-    <path d="M11,17 L13,17 C13.552,17 14,17.448 14,18 L14,20 C14,20.552 13.552,21 13,21 L11,21 C10.448,21 10,20.552 10,20 L10,18 C10,17.448 10.448,17 11,17 z" fill="#000000"/>
-  </g>
-  <defs/>
-</svg>
diff --git a/resources/oojs/images/icons/tag.png b/resources/oojs/images/icons/tag.png
deleted file mode 100644 (file)
index 722f4d7..0000000
Binary files a/resources/oojs/images/icons/tag.png and /dev/null differ
diff --git a/resources/oojs/images/icons/tag.svg b/resources/oojs/images/icons/tag.svg
deleted file mode 100644 (file)
index d21e5e3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="tag" style="opacity:0.75;">
-       <path d="M18.748,11.717c0.389,0.389,0.389,1.025,0,1.414l-4.949,4.95c-0.389,0.389-1.025,0.389-1.414,0l-6.01-6.01
-               c-0.389-0.389-0.707-1.157-0.707-1.707L5.667,6c0-0.55,0.45-1,1-1h4.364c0.55,0,1.318,0.318,1.707,0.707L18.748,11.717z
-                M8.104,7.456C7.525,8.032,7.526,8.97,8.103,9.549c0.578,0.577,1.516,0.577,2.095,0.001c0.576-0.578,0.576-1.517,0-2.095
-               C9.617,6.879,8.68,6.878,8.104,7.456z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/icons/window.png b/resources/oojs/images/icons/window.png
deleted file mode 100644 (file)
index 3d48a3c..0000000
Binary files a/resources/oojs/images/icons/window.png and /dev/null differ
diff --git a/resources/oojs/images/icons/window.svg b/resources/oojs/images/icons/window.svg
deleted file mode 100644 (file)
index 621cf2c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="window" style="opacity:0.75;">
-       <rect id="title" x="7" y="10" width="10" height="1"/>
-       <path id="window" d="M16,19H8c-2.206,0-4-1.794-4-4V9c0-2.206,1.794-4,4-4h8c2.206,0,4,1.794,4,4v6C20,17.206,18.206,19,16,19z
-                M8,7C6.897,7,6,7.897,6,9v6c0,1.103,0.897,2,2,2h8c1.103,0,2-0.897,2-2V9c0-1.103-0.897-2-2-2H8z"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/indicators/down.png b/resources/oojs/images/indicators/down.png
deleted file mode 100644 (file)
index 47ff54c..0000000
Binary files a/resources/oojs/images/indicators/down.png and /dev/null differ
diff --git a/resources/oojs/images/indicators/down.svg b/resources/oojs/images/indicators/down.svg
deleted file mode 100644 (file)
index c871f60..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
-        height="12px" viewBox="0 0 12 12" style="enable-background:new 0 0 12 12;" xml:space="preserve">
-<g id="down" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="2.023,3 5.512,8.953 9,3"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/indicators/required.png b/resources/oojs/images/indicators/required.png
deleted file mode 100644 (file)
index aeb35a3..0000000
Binary files a/resources/oojs/images/indicators/required.png and /dev/null differ
diff --git a/resources/oojs/images/indicators/required.svg b/resources/oojs/images/indicators/required.svg
deleted file mode 100644 (file)
index 7c60ec0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12" height="12" viewBox="0, 0, 12, 12">
-  <g id="required" opacity="0.75">
-    <path d="M7,0 L7,4.268 L10.696,2.134 L11.696,3.866 L8,6 L11.696,8.134 L10.696,9.866 L7,7.732 L7,12 L5,12 L5,7.732 L1.304,9.866 L0.304,8.134 L4,6 L0.304,3.866 L1.304,2.134 L5,4.268 L5,0 z" fill="#000000"/>
-  </g>
-  <defs/>
-</svg>
diff --git a/resources/oojs/images/indicators/up.png b/resources/oojs/images/indicators/up.png
deleted file mode 100644 (file)
index b827f6d..0000000
Binary files a/resources/oojs/images/indicators/up.png and /dev/null differ
diff --git a/resources/oojs/images/indicators/up.svg b/resources/oojs/images/indicators/up.svg
deleted file mode 100644 (file)
index a5d7f38..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
-        height="12px" viewBox="0 0 12 12" style="enable-background:new 0 0 12 12;" xml:space="preserve">
-<g id="up" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="5.512,2.006 2,8 9.024,8                "/>
-</g>
-</svg>
diff --git a/resources/oojs/images/tail.svg b/resources/oojs/images/tail.svg
deleted file mode 100644 (file)
index 4df8bb2..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-        width="15px" height="8px" viewBox="0 0 15 8" style="enable-background:new 0 0 15 8;" xml:space="preserve">
-<g id="tail">
-       <polygon id="outline" style="fill-rule:evenodd;clip-rule:evenodd;fill:#808080;" points="7.609,2.499 2.096,8 13.125,8"/>
-       <polygon id="fill" style="fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;" points="7.609,3 2.598,8 12.622,8"/>
-</g>
-</svg>
diff --git a/resources/oojs/images/textures/pending.gif b/resources/oojs/images/textures/pending.gif
deleted file mode 100644 (file)
index 1194eed..0000000
Binary files a/resources/oojs/images/textures/pending.gif and /dev/null differ
diff --git a/resources/oojs/images/textures/transparency.png b/resources/oojs/images/textures/transparency.png
deleted file mode 100644 (file)
index b8e36d3..0000000
Binary files a/resources/oojs/images/textures/transparency.png and /dev/null differ
diff --git a/resources/oojs/images/toolbar-shadow.png b/resources/oojs/images/toolbar-shadow.png
deleted file mode 100644 (file)
index 97e8d13..0000000
Binary files a/resources/oojs/images/toolbar-shadow.png and /dev/null differ
diff --git a/resources/oojs/oojs-ui.js b/resources/oojs/oojs-ui.js
deleted file mode 100644 (file)
index a58f65d..0000000
+++ /dev/null
@@ -1,7325 +0,0 @@
-/*!
- * OOjs UI v0.1.0-pre (a290673bbd)
- * https://www.mediawiki.org/wiki/OOjs_UI
- *
- * Copyright 2011–2014 OOjs Team and other contributors.
- * Released under the MIT license
- * http://oojs.mit-license.org
- *
- * Date: Wed Feb 12 2014 13:52:08 GMT-0800 (PST)
- */
-( function () {
-
-'use strict';
-/**
- * Namespace for all classes, static methods and static properties.
- *
- * @class
- * @singleton
- */
-OO.ui = {};
-
-OO.ui.bind = $.proxy;
-
-/**
- * Get the user's language and any fallback languages.
- *
- * These language codes are used to localize user interface elements in the user's language.
- *
- * In environments that provide a localization system, this function should be overridden to
- * return the user's language(s). The default implementation returns English (en) only.
- *
- * @returns {string[]} Language codes, in descending order of priority
- */
-OO.ui.getUserLanguages = function () {
-       return [ 'en' ];
-};
-
-/**
- * Get a value in an object keyed by language code.
- *
- * @param {Object.<string,Mixed>} obj Object keyed by language code
- * @param {string|null} [lang] Language code, if omitted or null defaults to any user language
- * @param {string} [fallback] Fallback code, used if no matching language can be found
- * @returns {Mixed} Local value
- */
-OO.ui.getLocalValue = function ( obj, lang, fallback ) {
-       var i, len, langs;
-
-       // Requested language
-       if ( obj[lang] ) {
-               return obj[lang];
-       }
-       // Known user language
-       langs = OO.ui.getUserLanguages();
-       for ( i = 0, len = langs.length; i < len; i++ ) {
-               lang = langs[i];
-               if ( obj[lang] ) {
-                       return obj[lang];
-               }
-       }
-       // Fallback language
-       if ( obj[fallback] ) {
-               return obj[fallback];
-       }
-       // First existing language
-       for ( lang in obj ) {
-               return obj[lang];
-       }
-
-       return undefined;
-};
-
-( function () {
-
-/**
- * Message store for the default implementation of OO.ui.msg
- *
- * Environments that provide a localization system should not use this, but should override
- * OO.ui.msg altogether.
- *
- * @private
- */
-var messages = {
-       // Label text for button to exit from dialog
-       'ooui-dialog-action-close': 'Close',
-       // Tool tip for a button that moves items in a list down one place
-       'ooui-outline-control-move-down': 'Move item down',
-       // Tool tip for a button that moves items in a list up one place
-       'ooui-outline-control-move-up': 'Move item up',
-       // Label for the toolbar group that contains a list of all other available tools
-       'ooui-toolbar-more': 'More'
-};
-
-/**
- * Get a localized message.
- *
- * In environments that provide a localization system, this function should be overridden to
- * return the message translated in the user's language. The default implementation always returns
- * English messages.
- *
- * After the message key, message parameters may optionally be passed. In the default implementation,
- * any occurrences of $1 are replaced with the first parameter, $2 with the second parameter, etc.
- * Alternative implementations of OO.ui.msg may use any substitution system they like, as long as
- * they support unnamed, ordered message parameters.
- *
- * @abstract
- * @param {string} key Message key
- * @param {Mixed...} [params] Message parameters
- * @returns {string} Translated message with parameters substituted
- */
-OO.ui.msg = function ( key ) {
-       var message = messages[key], params = Array.prototype.slice.call( arguments, 1 );
-       if ( typeof message === 'string' ) {
-               // Perform $1 substitution
-               message = message.replace( /\$(\d+)/g, function ( unused, n ) {
-                       var i = parseInt( n, 10 );
-                       return params[i - 1] !== undefined ? params[i - 1] : '$' + n;
-               } );
-       } else {
-               // Return placeholder if message not found
-               message = '[' + key + ']';
-       }
-       return message;
-};
-
-OO.ui.deferMsg = function ( key ) {
-       return function () {
-               return OO.ui.msg( key );
-       };
-};
-
-OO.ui.resolveMsg = function ( msg ) {
-       if ( $.isFunction( msg ) ) {
-               return msg();
-       }
-       return msg;
-};
-
-} )();
-
-// Add more as you need
-OO.ui.Keys = {
-       'UNDEFINED': 0,
-       'BACKSPACE': 8,
-       'DELETE': 46,
-       'LEFT': 37,
-       'RIGHT': 39,
-       'UP': 38,
-       'DOWN': 40,
-       'ENTER': 13,
-       'END': 35,
-       'HOME': 36,
-       'TAB': 9,
-       'PAGEUP': 33,
-       'PAGEDOWN': 34,
-       'ESCAPE': 27,
-       'SHIFT': 16,
-       'SPACE': 32
-};
-/**
- * DOM element abstraction.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {Function} [$] jQuery for the frame the widget is in
- * @cfg {string[]} [classes] CSS class names
- * @cfg {jQuery} [$content] Content elements to append
- */
-OO.ui.Element = function OoUiElement( config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Properties
-       this.$ = config.$ || OO.ui.Element.getJQuery( document );
-       this.$element = this.$( this.$.context.createElement( this.getTagName() ) );
-
-       // Initialization
-       if ( Array.isArray( config.classes ) ) {
-               this.$element.addClass( config.classes.join( ' ' ) );
-       }
-       if ( config.$content ) {
-               this.$element.append( config.$content );
-       }
-};
-
-/* Static Properties */
-
-/**
- * @static
- * @property
- * @inheritable
- */
-OO.ui.Element.static = {};
-
-/**
- * HTML tag name.
- *
- * This may be ignored if getTagName is overridden.
- *
- * @static
- * @property {string}
- * @inheritable
- */
-OO.ui.Element.static.tagName = 'div';
-
-/* Static Methods */
-
-/**
- * Gets a jQuery function within a specific document.
- *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} context Context to bind the function to
- * @param {OO.ui.Frame} [frame] Frame of the document context
- * @returns {Function} Bound jQuery function
- */
-OO.ui.Element.getJQuery = function ( context, frame ) {
-       function wrapper( selector ) {
-               return $( selector, wrapper.context );
-       }
-
-       wrapper.context = this.getDocument( context );
-
-       if ( frame ) {
-               wrapper.frame = frame;
-       }
-
-       return wrapper;
-};
-
-/**
- * Get the document of an element.
- *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Object to get the document for
- * @returns {HTMLDocument} Document object
- * @throws {Error} If context is invalid
- */
-OO.ui.Element.getDocument = function ( obj ) {
-       var doc =
-               // jQuery - selections created "offscreen" won't have a context, so .context isn't reliable
-               ( obj[0] && obj[0].ownerDocument ) ||
-               // Empty jQuery selections might have a context
-               obj.context ||
-               // HTMLElement
-               obj.ownerDocument ||
-               // Window
-               obj.document ||
-               // HTMLDocument
-               ( obj.nodeType === 9 && obj );
-
-       if ( doc ) {
-               return doc;
-       }
-
-       throw new Error( 'Invalid context' );
-};
-
-/**
- * Get the window of an element or document.
- *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the window for
- * @returns {Window} Window object
- */
-OO.ui.Element.getWindow = function ( obj ) {
-       var doc = this.getDocument( obj );
-       return doc.parentWindow || doc.defaultView;
-};
-
-/**
- * Get the direction of an element or document.
- *
- * @static
- * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the direction for
- * @returns {string} Text direction, either `ltr` or `rtl`
- */
-OO.ui.Element.getDir = function ( obj ) {
-       var isDoc, isWin;
-
-       if ( obj instanceof jQuery ) {
-               obj = obj[0];
-       }
-       isDoc = obj.nodeType === 9;
-       isWin = obj.document !== undefined;
-       if ( isDoc || isWin ) {
-               if ( isWin ) {
-                       obj = obj.document;
-               }
-               obj = obj.body;
-       }
-       return $( obj ).css( 'direction' );
-};
-
-/**
- * Get the offset between two frames.
- *
- * TODO: Make this function not use recursion.
- *
- * @static
- * @param {Window} from Window of the child frame
- * @param {Window} [to=window] Window of the parent frame
- * @param {Object} [offset] Offset to start with, used internally
- * @returns {Object} Offset object, containing left and top properties
- */
-OO.ui.Element.getFrameOffset = function ( from, to, offset ) {
-       var i, len, frames, frame, rect;
-
-       if ( !to ) {
-               to = window;
-       }
-       if ( !offset ) {
-               offset = { 'top': 0, 'left': 0 };
-       }
-       if ( from.parent === from ) {
-               return offset;
-       }
-
-       // Get iframe element
-       frames = from.parent.document.getElementsByTagName( 'iframe' );
-       for ( i = 0, len = frames.length; i < len; i++ ) {
-               if ( frames[i].contentWindow === from ) {
-                       frame = frames[i];
-                       break;
-               }
-       }
-
-       // Recursively accumulate offset values
-       if ( frame ) {
-               rect = frame.getBoundingClientRect();
-               offset.left += rect.left;
-               offset.top += rect.top;
-               if ( from !== to ) {
-                       this.getFrameOffset( from.parent, offset );
-               }
-       }
-       return offset;
-};
-
-/**
- * Get the offset between two elements.
- *
- * @static
- * @param {jQuery} $from
- * @param {jQuery} $to
- * @returns {Object} Translated position coordinates, containing top and left properties
- */
-OO.ui.Element.getRelativePosition = function ( $from, $to ) {
-       var from = $from.offset(),
-               to = $to.offset();
-       return { 'top': Math.round( from.top - to.top ), 'left': Math.round( from.left - to.left ) };
-};
-
-/**
- * Get element border sizes.
- *
- * @static
- * @param {HTMLElement} el Element to measure
- * @return {Object} Dimensions object with `top`, `left`, `bottom` and `right` properties
- */
-OO.ui.Element.getBorders = function ( el ) {
-       var doc = el.ownerDocument,
-               win = doc.parentWindow || doc.defaultView,
-               style = win && win.getComputedStyle ?
-                       win.getComputedStyle( el, null ) :
-                       el.currentStyle,
-               $el = $( el ),
-               top = parseFloat( style ? style.borderTopWidth : $el.css( 'borderTopWidth' ) ) || 0,
-               left = parseFloat( style ? style.borderLeftWidth : $el.css( 'borderLeftWidth' ) ) || 0,
-               bottom = parseFloat( style ? style.borderBottomWidth : $el.css( 'borderBottomWidth' ) ) || 0,
-               right = parseFloat( style ? style.borderRightWidth : $el.css( 'borderRightWidth' ) ) || 0;
-
-       return {
-               'top': Math.round( top ),
-               'left': Math.round( left ),
-               'bottom': Math.round( bottom ),
-               'right': Math.round( right )
-       };
-};
-
-/**
- * Get dimensions of an element or window.
- *
- * @static
- * @param {HTMLElement|Window} el Element to measure
- * @return {Object} Dimensions object with `borders`, `scroll`, `scrollbar` and `rect` properties
- */
-OO.ui.Element.getDimensions = function ( el ) {
-       var $el, $win,
-               doc = el.ownerDocument || el.document,
-               win = doc.parentWindow || doc.defaultView;
-
-       if ( win === el || el === doc.documentElement ) {
-               $win = $( win );
-               return {
-                       'borders': { 'top': 0, 'left': 0, 'bottom': 0, 'right': 0 },
-                       'scroll': {
-                               'top': $win.scrollTop(),
-                               'left': $win.scrollLeft()
-                       },
-                       'scrollbar': { 'right': 0, 'bottom': 0 },
-                       'rect': {
-                               'top': 0,
-                               'left': 0,
-                               'bottom': $win.innerHeight(),
-                               'right': $win.innerWidth()
-                       }
-               };
-       } else {
-               $el = $( el );
-               return {
-                       'borders': this.getBorders( el ),
-                       'scroll': {
-                               'top': $el.scrollTop(),
-                               'left': $el.scrollLeft()
-                       },
-                       'scrollbar': {
-                               'right': $el.innerWidth() - el.clientWidth,
-                               'bottom': $el.innerHeight() - el.clientHeight
-                       },
-                       'rect': el.getBoundingClientRect()
-               };
-       }
-};
-
-/**
- * Get closest scrollable container.
- *
- * Traverses up until either a scrollable element or the root is reached, in which case the window
- * will be returned.
- *
- * @static
- * @param {HTMLElement} el Element to find scrollable container for
- * @param {string} [dimension] Dimension of scrolling to look for; `x`, `y` or omit for either
- * @return {HTMLElement|Window} Closest scrollable container
- */
-OO.ui.Element.getClosestScrollableContainer = function ( el, dimension ) {
-       var i, val,
-               props = [ 'overflow' ],
-               $parent = $( el ).parent();
-
-       if ( dimension === 'x' || dimension === 'y' ) {
-               props.push( 'overflow-' + dimension );
-       }
-
-       while ( $parent.length ) {
-               if ( $parent[0] === el.ownerDocument.body ) {
-                       return $parent[0];
-               }
-               i = props.length;
-               while ( i-- ) {
-                       val = $parent.css( props[i] );
-                       if ( val === 'auto' || val === 'scroll' ) {
-                               return $parent[0];
-                       }
-               }
-               $parent = $parent.parent();
-       }
-       return this.getDocument( el ).body;
-};
-
-/**
- * Scroll element into view
- *
- * @static
- * @param {HTMLElement} el Element to scroll into view
- * @param {Object} [config={}] Configuration config
- * @param {string} [config.duration] jQuery animation duration value
- * @param {string} [config.direction] Scroll in only one direction, e.g. 'x' or 'y', omit
- *  to scroll in both directions
- * @param {Function} [config.complete] Function to call when scrolling completes
- */
-OO.ui.Element.scrollIntoView = function ( el, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       var anim = {},
-               callback = typeof config.complete === 'function' && config.complete,
-               sc = this.getClosestScrollableContainer( el, config.direction ),
-               $sc = $( sc ),
-               eld = this.getDimensions( el ),
-               scd = this.getDimensions( sc ),
-               rel = {
-                       'top': eld.rect.top - ( scd.rect.top + scd.borders.top ),
-                       'bottom': scd.rect.bottom - scd.borders.bottom - scd.scrollbar.bottom - eld.rect.bottom,
-                       'left': eld.rect.left - ( scd.rect.left + scd.borders.left ),
-                       'right': scd.rect.right - scd.borders.right - scd.scrollbar.right - eld.rect.right
-               };
-
-       if ( !config.direction || config.direction === 'y' ) {
-               if ( rel.top < 0 ) {
-                       anim.scrollTop = scd.scroll.top + rel.top;
-               } else if ( rel.top > 0 && rel.bottom < 0 ) {
-                       anim.scrollTop = scd.scroll.top + Math.min( rel.top, -rel.bottom );
-               }
-       }
-       if ( !config.direction || config.direction === 'x' ) {
-               if ( rel.left < 0 ) {
-                       anim.scrollLeft = scd.scroll.left + rel.left;
-               } else if ( rel.left > 0 && rel.right < 0 ) {
-                       anim.scrollLeft = scd.scroll.left + Math.min( rel.left, -rel.right );
-               }
-       }
-       if ( !$.isEmptyObject( anim ) ) {
-               $sc.stop( true ).animate( anim, config.duration || 'fast' );
-               if ( callback ) {
-                       $sc.queue( function ( next ) {
-                               callback();
-                               next();
-                       } );
-               }
-       } else {
-               if ( callback ) {
-                       callback();
-               }
-       }
-};
-
-/* Methods */
-
-/**
- * Get the HTML tag name.
- *
- * Override this method to base the result on instance information.
- *
- * @returns {string} HTML tag name
- */
-OO.ui.Element.prototype.getTagName = function () {
-       return this.constructor.static.tagName;
-};
-
-/**
- * Get the DOM document.
- *
- * @returns {HTMLDocument} Document object
- */
-OO.ui.Element.prototype.getElementDocument = function () {
-       return OO.ui.Element.getDocument( this.$element );
-};
-
-/**
- * Get the DOM window.
- *
- * @returns {Window} Window object
- */
-OO.ui.Element.prototype.getElementWindow = function () {
-       return OO.ui.Element.getWindow( this.$element );
-};
-
-/**
- * Get closest scrollable container.
- *
- * @method
- * @see #static-method-getClosestScrollableContainer
- */
-OO.ui.Element.prototype.getClosestScrollableElementContainer = function () {
-       return OO.ui.Element.getClosestScrollableContainer( this.$element[0] );
-};
-
-/**
- * Scroll element into view
- *
- * @method
- * @see #static-method-scrollIntoView
- * @param {Object} [config={}]
- */
-OO.ui.Element.prototype.scrollElementIntoView = function ( config ) {
-       return OO.ui.Element.scrollIntoView( this.$element[0], config );
-};
-
-( function () {
-       // Static
-       var specialFocusin;
-
-       function handler( e ) {
-               jQuery.event.simulate( 'focusin', e.target, jQuery.event.fix( e ), /* bubble = */ true );
-       }
-
-       specialFocusin = {
-               setup: function () {
-                       var doc = this.ownerDocument || this,
-                               attaches = $.data( doc, 'ooui-focusin-attaches' );
-                       if ( !attaches ) {
-                               doc.addEventListener( 'focus', handler, true );
-                       }
-                       $.data( doc, 'ooui-focusin-attaches', ( attaches || 0 ) + 1 );
-               },
-               teardown: function () {
-                       var doc = this.ownerDocument || this,
-                               attaches = $.data( doc, 'ooui-focusin-attaches' ) - 1;
-                       if ( !attaches ) {
-                               doc.removeEventListener( 'focus', handler, true );
-                               $.removeData( doc, 'ooui-focusin-attaches' );
-                       } else {
-                               $.data( doc, 'ooui-focusin-attaches', attaches );
-                       }
-               }
-       };
-
-       /**
-        * Bind a handler for an event on the DOM element.
-        *
-        * Uses jQuery internally for everything except for events which are
-        * known to have issues in the browser or in jQuery. This method
-        * should become obsolete eventually.
-        *
-        * @param {string} event
-        * @param {Function} callback
-        */
-       OO.ui.Element.prototype.onDOMEvent = function ( event, callback ) {
-               var orig;
-
-               if ( event === 'focusin' ) {
-                       // jQuery 1.8.3 has a bug with handling focusin events inside iframes.
-                       // Firefox doesn't support focusin at all, so we listen for 'focus' on the
-                       // document, and simulate a 'focusin' event on the target element and make
-                       // it bubble from there.
-                       //
-                       // - http://jsfiddle.net/sw3hr/
-                       // - http://bugs.jquery.com/ticket/14180
-                       // - https://github.com/jquery/jquery/commit/1cecf64e5aa4153
-
-                       // Replace jQuery's override with our own
-                       orig = $.event.special.focusin;
-                       $.event.special.focusin = specialFocusin;
-
-                       this.$element.on( event, callback );
-
-                       // Restore
-                       $.event.special.focusin = orig;
-
-               } else {
-                       this.$element.on( event, callback );
-               }
-       };
-
-       /**
-        * @param {string} event
-        * @param {Function} callback
-        */
-       OO.ui.Element.prototype.offDOMEvent = function ( event, callback ) {
-               var orig;
-               if ( event === 'focusin' ) {
-                       orig = $.event.special.focusin;
-                       $.event.special.focusin = specialFocusin;
-                       this.$element.off( event, callback );
-                       $.event.special.focusin = orig;
-               } else {
-                       this.$element.off( event, callback );
-               }
-       };
-}() );
-/**
- * Embedded iframe with the same styles as its parent.
- *
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.Frame = function OoUiFrame( config ) {
-       // Parent constructor
-       OO.ui.Element.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-
-       // Properties
-       this.initialized = false;
-       this.config = config;
-
-       // Initialize
-       this.$element
-               .addClass( 'oo-ui-frame' )
-               .attr( { 'frameborder': 0, 'scrolling': 'no' } );
-
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Frame, OO.ui.Element );
-
-OO.mixinClass( OO.ui.Frame, OO.EventEmitter );
-
-/* Static Properties */
-
-OO.ui.Frame.static.tagName = 'iframe';
-
-/* Events */
-
-/**
- * @event initialize
- */
-
-/* Static Methods */
-
-/**
- * Transplant the CSS styles from as parent document to a frame's document.
- *
- * This loops over the style sheets in the parent document, and copies their nodes to the
- * frame's document. It then polls the document to see when all styles have loaded, and once they
- * have, invokes the callback.
- *
- * If the styles still haven't loaded after a long time (5 seconds by default), we give up waiting
- * and invoke the callback anyway. This protects against cases like a display: none; iframe in
- * Firefox, where the styles won't load until the iframe becomes visible.
- *
- * For details of how we arrived at the strategy used in this function, see #load.
- *
- * @static
- * @method
- * @inheritable
- * @param {HTMLDocument} parentDoc Document to transplant styles from
- * @param {HTMLDocument} frameDoc Document to transplant styles to
- * @param {Function} [callback] Callback to execute once styles have loaded
- * @param {number} [timeout=5000] How long to wait before giving up (in ms). If 0, never give up.
- */
-OO.ui.Frame.static.transplantStyles = function ( parentDoc, frameDoc, callback, timeout ) {
-       var i, numSheets, styleNode, newNode, timeoutID, pollNodeId, $pendingPollNodes,
-               $pollNodes = $( [] ),
-               // Fake font-family value
-               fontFamily = 'oo-ui-frame-transplantStyles-loaded';
-
-       for ( i = 0, numSheets = parentDoc.styleSheets.length; i < numSheets; i++ ) {
-               styleNode = parentDoc.styleSheets[i].ownerNode;
-               if ( callback && styleNode.nodeName.toLowerCase() === 'link' ) {
-                       // External stylesheet
-                       // Create a node with a unique ID that we're going to monitor to see when the CSS
-                       // has loaded
-                       pollNodeId = 'oo-ui-frame-transplantStyles-loaded-' + i;
-                       $pollNodes = $pollNodes.add( $( '<div>', frameDoc )
-                               .attr( 'id', pollNodeId )
-                               .appendTo( frameDoc.body )
-                       );
-
-                       // Add <style>@import url(...); #pollNodeId { font-family: ... }</style>
-                       // The font-family rule will only take effect once the @import finishes
-                       newNode = frameDoc.createElement( 'style' );
-                       newNode.textContent = '@import url(' + styleNode.href + ');\n' +
-                               '#' + pollNodeId + ' { font-family: ' + fontFamily + '; }';
-               } else {
-                       // Not an external stylesheet, or no polling required; just copy the node over
-                       newNode = frameDoc.importNode( styleNode, true );
-               }
-               frameDoc.head.appendChild( newNode );
-       }
-
-       if ( callback ) {
-               // Poll every 100ms until all external stylesheets have loaded
-               $pendingPollNodes = $pollNodes;
-               timeoutID = setTimeout( function pollExternalStylesheets() {
-                       while (
-                               $pendingPollNodes.length > 0 &&
-                               $pendingPollNodes.eq( 0 ).css( 'font-family' ) === fontFamily
-                       ) {
-                               $pendingPollNodes = $pendingPollNodes.slice( 1 );
-                       }
-
-                       if ( $pendingPollNodes.length === 0 ) {
-                               // We're done!
-                               if ( timeoutID !== null ) {
-                                       timeoutID = null;
-                                       $pollNodes.remove();
-                                       callback();
-                               }
-                       } else {
-                               timeoutID = setTimeout( pollExternalStylesheets, 100 );
-                       }
-               }, 100 );
-               // ...but give up after a while
-               if ( timeout !== 0 ) {
-                       setTimeout( function () {
-                               if ( timeoutID ) {
-                                       clearTimeout( timeoutID );
-                                       timeoutID = null;
-                                       $pollNodes.remove();
-                                       callback();
-                               }
-                       }, timeout || 5000 );
-               }
-       }
-};
-
-/* Methods */
-
-/**
- * Load the frame contents.
- *
- * Once the iframe's stylesheets are loaded, the `initialize` event will be emitted.
- *
- * Sounds simple right? Read on...
- *
- * When you create a dynamic iframe using open/write/close, the window.load event for the
- * iframe is triggered when you call close, and there's no further load event to indicate that
- * everything is actually loaded.
- *
- * In Chrome, stylesheets don't show up in document.styleSheets until they have loaded, so we could
- * just poll that array and wait for it to have the right length. However, in Firefox, stylesheets
- * are added to document.styleSheets immediately, and the only way you can determine whether they've
- * loaded is to attempt to access .cssRules and wait for that to stop throwing an exception. But
- * cross-domain stylesheets never allow .cssRules to be accessed even after they have loaded.
- *
- * The workaround is to change all `<link href="...">` tags to `<style>@import url(...)</style>` tags.
- * Because `@import` is blocking, Chrome won't add the stylesheet to document.styleSheets until
- * the `@import` has finished, and Firefox won't allow .cssRules to be accessed until the `@import`
- * has finished. And because the contents of the `<style>` tag are from the same origin, accessing
- * .cssRules is allowed.
- *
- * However, now that we control the styles we're injecting, we might as well do away with
- * browser-specific polling hacks like document.styleSheets and .cssRules, and instead inject
- * `<style>@import url(...); #foo { font-family: someValue; }</style>`, then create `<div id="foo">`
- * and wait for its font-family to change to someValue. Because `@import` is blocking, the font-family
- * rule is not applied until after the `@import` finishes.
- *
- * All this stylesheet injection and polling magic is in #transplantStyles.
- *
- * @fires initialize
- */
-OO.ui.Frame.prototype.load = function () {
-       var win = this.$element.prop( 'contentWindow' ),
-               doc = win.document,
-               frame = this;
-
-       // Figure out directionality:
-       this.dir = this.$element.closest( '[dir]' ).prop( 'dir' ) || 'ltr';
-
-       // Initialize contents
-       doc.open();
-       doc.write(
-               '<!doctype html>' +
-               '<html>' +
-                       '<body class="oo-ui-frame-body oo-ui-' + this.dir + '" style="direction:' + this.dir + ';" dir="' + this.dir + '">' +
-                               '<div class="oo-ui-frame-content"></div>' +
-                       '</body>' +
-               '</html>'
-       );
-       doc.close();
-
-       // Properties
-       this.$ = OO.ui.Element.getJQuery( doc, this );
-       this.$content = this.$( '.oo-ui-frame-content' );
-       this.$document = this.$( doc );
-
-       this.constructor.static.transplantStyles( this.getElementDocument(), this.$document[0],
-               function () {
-                       frame.initialized = true;
-                       frame.emit( 'initialize' );
-               }
-       );
-};
-
-/**
- * Run a callback as soon as the frame has been initialized.
- *
- * @param {Function} callback
- */
-OO.ui.Frame.prototype.run = function ( callback ) {
-       if ( this.initialized ) {
-               callback();
-       } else {
-               this.once( 'initialize', callback );
-       }
-};
-
-/**
- * Sets the size of the frame.
- *
- * @method
- * @param {number} width Frame width in pixels
- * @param {number} height Frame height in pixels
- * @chainable
- */
-OO.ui.Frame.prototype.setSize = function ( width, height ) {
-       this.$element.css( { 'width': width, 'height': height } );
-       return this;
-};
-/**
- * Container for elements in a child frame.
- *
- * There are two ways to specify a title: set the static `title` property or provide a `title`
- * property in the configuration options. The latter will override the former.
- *
- * @class
- * @abstract
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
- *
- * @constructor
- * @param {OO.ui.WindowSet} windowSet Window set this dialog is part of
- * @param {Object} [config] Configuration options
- * @cfg {string|Function} [title] Title string or function that returns a string
- * @cfg {string} [icon] Symbolic name of icon
- * @fires initialize
- */
-OO.ui.Window = function OoUiWindow( windowSet, config ) {
-       // Parent constructor
-       OO.ui.Element.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-
-       // Properties
-       this.windowSet = windowSet;
-       this.visible = false;
-       this.opening = false;
-       this.closing = false;
-       this.title = OO.ui.resolveMsg( config.title || this.constructor.static.title );
-       this.icon = config.icon || this.constructor.static.icon;
-       this.frame = new OO.ui.Frame( { '$': this.$ } );
-       this.$frame = this.$( '<div>' );
-       this.$ = function () {
-               throw new Error( 'this.$() cannot be used until the frame has been initialized.' );
-       };
-
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-window' )
-               // Hide the window using visibility: hidden; while the iframe is still loading
-               // Can't use display: none; because that prevents the iframe from loading in Firefox
-               .css( 'visibility', 'hidden' )
-               .append( this.$frame );
-       this.$frame
-               .addClass( 'oo-ui-window-frame' )
-               .append( this.frame.$element );
-
-       // Events
-       this.frame.connect( this, { 'initialize': 'initialize' } );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Window, OO.ui.Element );
-
-OO.mixinClass( OO.ui.Window, OO.EventEmitter );
-
-/* Events */
-
-/**
- * Initialize contents.
- *
- * Fired asynchronously after construction when iframe is ready.
- *
- * @event initialize
- */
-
-/**
- * Open window.
- *
- * Fired after window has been opened.
- *
- * @event open
- * @param {Object} data Window opening data
- */
-
-/**
- * Close window.
- *
- * Fired after window has been closed.
- *
- * @event close
- * @param {Object} data Window closing data
- */
-
-/* Static Properties */
-
-/**
- * Symbolic name of icon.
- *
- * @static
- * @inheritable
- * @property {string}
- */
-OO.ui.Window.static.icon = 'window';
-
-/**
- * Window title.
- *
- * @static
- * @inheritable
- * @property {string|Function} Title string or function that returns a string
- */
-OO.ui.Window.static.title = null;
-
-/* Methods */
-
-/**
- * Check if window is visible.
- *
- * @method
- * @returns {boolean} Window is visible
- */
-OO.ui.Window.prototype.isVisible = function () {
-       return this.visible;
-};
-
-/**
- * Check if window is opening.
- *
- * @method
- * @returns {boolean} Window is opening
- */
-OO.ui.Window.prototype.isOpening = function () {
-       return this.opening;
-};
-
-/**
- * Check if window is closing.
- *
- * @method
- * @returns {boolean} Window is closing
- */
-OO.ui.Window.prototype.isClosing = function () {
-       return this.closing;
-};
-
-/**
- * Get the window frame.
- *
- * @method
- * @returns {OO.ui.Frame} Frame of window
- */
-OO.ui.Window.prototype.getFrame = function () {
-       return this.frame;
-};
-
-/**
- * Get the window set.
- *
- * @method
- * @returns {OO.ui.WindowSet} Window set
- */
-OO.ui.Window.prototype.getWindowSet = function () {
-       return this.windowSet;
-};
-
-/**
- * Get the window title.
- *
- * @returns {string} Title text
- */
-OO.ui.Window.prototype.getTitle = function () {
-       return this.title;
-};
-
-/**
- * Get the window icon.
- *
- * @returns {string} Symbolic name of icon
- */
-OO.ui.Window.prototype.getIcon = function () {
-       return this.icon;
-};
-
-/**
- * Set the size of window frame.
- *
- * @param {number} [width=auto] Custom width
- * @param {number} [height=auto] Custom height
- * @chainable
- */
-OO.ui.Window.prototype.setSize = function ( width, height ) {
-       if ( !this.frame.$content ) {
-               return;
-       }
-
-       this.frame.$element.css( {
-               'width': width === undefined ? 'auto' : width,
-               'height': height === undefined ? 'auto' : height
-       } );
-
-       return this;
-};
-
-/**
- * Set the title of the window.
- *
- * @param {string|Function} title Title text or a function that returns text
- * @chainable
- */
-OO.ui.Window.prototype.setTitle = function ( title ) {
-       this.title = OO.ui.resolveMsg( title );
-       if ( this.$title ) {
-               this.$title.text( title );
-       }
-       return this;
-};
-
-/**
- * Set the icon of the window.
- *
- * @param {string} icon Symbolic name of icon
- * @chainable
- */
-OO.ui.Window.prototype.setIcon = function ( icon ) {
-       if ( this.$icon ) {
-               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
-       }
-       this.icon = icon;
-       if ( this.$icon ) {
-               this.$icon.addClass( 'oo-ui-icon-' + this.icon );
-       }
-
-       return this;
-};
-
-/**
- * Set the position of window to fit with contents..
- *
- * @param {string} left Left offset
- * @param {string} top Top offset
- * @chainable
- */
-OO.ui.Window.prototype.setPosition = function ( left, top ) {
-       this.$element.css( { 'left': left, 'top': top } );
-       return this;
-};
-
-/**
- * Set the height of window to fit with contents.
- *
- * @param {number} [min=0] Min height
- * @param {number} [max] Max height (defaults to content's outer height)
- * @chainable
- */
-OO.ui.Window.prototype.fitHeightToContents = function ( min, max ) {
-       var height = this.frame.$content.outerHeight();
-
-       this.frame.$element.css(
-               'height', Math.max( min || 0, max === undefined ? height : Math.min( max, height ) )
-       );
-
-       return this;
-};
-
-/**
- * Set the width of window to fit with contents.
- *
- * @param {number} [min=0] Min height
- * @param {number} [max] Max height (defaults to content's outer width)
- * @chainable
- */
-OO.ui.Window.prototype.fitWidthToContents = function ( min, max ) {
-       var width = this.frame.$content.outerWidth();
-
-       this.frame.$element.css(
-               'width', Math.max( min || 0, max === undefined ? width : Math.min( max, width ) )
-       );
-
-       return this;
-};
-
-/**
- * Initialize window contents.
- *
- * The first time the window is opened, #initialize is called when it's safe to begin populating
- * its contents. See #setup for a way to make changes each time the window opens.
- *
- * Once this method is called, this.$$ can be used to create elements within the frame.
- *
- * @method
- * @fires initialize
- * @chainable
- */
-OO.ui.Window.prototype.initialize = function () {
-       // Properties
-       this.$ = this.frame.$;
-       this.$title = this.$( '<div class="oo-ui-window-title"></div>' )
-               .text( this.title );
-       this.$icon = this.$( '<div class="oo-ui-window-icon"></div>' )
-               .addClass( 'oo-ui-icon-' + this.icon );
-       this.$head = this.$( '<div class="oo-ui-window-head"></div>' );
-       this.$body = this.$( '<div class="oo-ui-window-body"></div>' );
-       this.$foot = this.$( '<div class="oo-ui-window-foot"></div>' );
-       this.$overlay = this.$( '<div class="oo-ui-window-overlay"></div>' );
-
-       // Initialization
-       this.frame.$content.append(
-               this.$head.append( this.$icon, this.$title ),
-               this.$body,
-               this.$foot,
-               this.$overlay
-       );
-
-       // Undo the visibility: hidden; hack from the constructor and apply display: none;
-       // We can do this safely now that the iframe has initialized
-       this.$element.hide().css( 'visibility', '' );
-
-       this.emit( 'initialize' );
-
-       return this;
-};
-
-/**
- * Setup window for use.
- *
- * Each time the window is opened, once it's ready to be interacted with, this will set it up for
- * use in a particular context, based on the `data` argument.
- *
- * When you override this method, you must call the parent method at the very beginning.
- *
- * @method
- * @abstract
- * @param {Object} [data] Window opening data
- */
-OO.ui.Window.prototype.setup = function () {
-       // Override to do something
-};
-
-/**
- * Tear down window after use.
- *
- * Each time the window is closed, and it's done being interacted with, this will tear it down and
- * do something with the user's interactions within the window, based on the `data` argument.
- *
- * When you override this method, you must call the parent method at the very end.
- *
- * @method
- * @abstract
- * @param {Object} [data] Window closing data
- */
-OO.ui.Window.prototype.teardown = function () {
-       // Override to do something
-};
-
-/**
- * Open window.
- *
- * Do not override this method. See #setup for a way to make changes each time the window opens.
- *
- * @method
- * @param {Object} [data] Window opening data
- * @fires open
- * @chainable
- */
-OO.ui.Window.prototype.open = function ( data ) {
-       if ( !this.opening && !this.closing && !this.visible ) {
-               this.opening = true;
-               this.frame.run( OO.ui.bind( function () {
-                       this.$element.show();
-                       this.visible = true;
-                       this.frame.$element.focus();
-                       this.emit( 'opening', data );
-                       this.setup( data );
-                       this.emit( 'open', data );
-                       this.opening = false;
-               }, this ) );
-       }
-
-       return this;
-};
-
-/**
- * Close window.
- *
- * See #teardown for a way to do something each time the window closes.
- *
- * @method
- * @param {Object} [data] Window closing data
- * @fires close
- * @chainable
- */
-OO.ui.Window.prototype.close = function ( data ) {
-       if ( !this.opening && !this.closing && this.visible ) {
-               this.frame.$content.find( ':focus' ).blur();
-               this.closing = true;
-               this.$element.hide();
-               this.visible = false;
-               this.emit( 'closing', data );
-               this.teardown( data );
-               this.emit( 'close', data );
-               this.closing = false;
-       }
-
-       return this;
-};
-/**
- * Set of mutually exclusive windows.
- *
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
- *
- * @constructor
- * @param {OO.Factory} factory Window factory
- * @param {Object} [config] Configuration options
- */
-OO.ui.WindowSet = function OoUiWindowSet( factory, config ) {
-       // Parent constructor
-       OO.ui.Element.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-
-       // Properties
-       this.factory = factory;
-       this.windows = {};
-       this.currentWindow = null;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-windowSet' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.WindowSet, OO.ui.Element );
-
-OO.mixinClass( OO.ui.WindowSet, OO.EventEmitter );
-
-/* Events */
-
-/**
- * @event opening
- * @param {OO.ui.Window} win Window that's being opened
- * @param {Object} config Window opening information
- */
-
-/**
- * @event open
- * @param {OO.ui.Window} win Window that's been opened
- * @param {Object} config Window opening information
- */
-
-/**
- * @event closing
- * @param {OO.ui.Window} win Window that's being closed
- * @param {Object} config Window closing information
- */
-
-/**
- * @event close
- * @param {OO.ui.Window} win Window that's been closed
- * @param {Object} config Window closing information
- */
-
-/* Methods */
-
-/**
- * Handle a window that's being opened.
- *
- * @method
- * @param {OO.ui.Window} win Window that's being opened
- * @param {Object} [config] Window opening information
- * @fires opening
- */
-OO.ui.WindowSet.prototype.onWindowOpening = function ( win, config ) {
-       if ( this.currentWindow && this.currentWindow !== win ) {
-               this.currentWindow.close();
-       }
-       this.currentWindow = win;
-       this.emit( 'opening', win, config );
-};
-
-/**
- * Handle a window that's been opened.
- *
- * @method
- * @param {OO.ui.Window} win Window that's been opened
- * @param {Object} [config] Window opening information
- * @fires open
- */
-OO.ui.WindowSet.prototype.onWindowOpen = function ( win, config ) {
-       this.emit( 'open', win, config );
-};
-
-/**
- * Handle a window that's being closed.
- *
- * @method
- * @param {OO.ui.Window} win Window that's being closed
- * @param {Object} [config] Window closing information
- * @fires closing
- */
-OO.ui.WindowSet.prototype.onWindowClosing = function ( win, config ) {
-       this.currentWindow = null;
-       this.emit( 'closing', win, config );
-};
-
-/**
- * Handle a window that's been closed.
- *
- * @method
- * @param {OO.ui.Window} win Window that's been closed
- * @param {Object} [config] Window closing information
- * @fires close
- */
-OO.ui.WindowSet.prototype.onWindowClose = function ( win, config ) {
-       this.emit( 'close', win, config );
-};
-
-/**
- * Get the current window.
- *
- * @method
- * @returns {OO.ui.Window} Current window
- */
-OO.ui.WindowSet.prototype.getCurrentWindow = function () {
-       return this.currentWindow;
-};
-
-/**
- * Return a given window.
- *
- * @param {string} name Symbolic name of window
- * @return {OO.ui.Window} Window with specified name
- */
-OO.ui.WindowSet.prototype.getWindow = function ( name ) {
-       var win;
-
-       if ( !this.factory.lookup( name ) ) {
-               throw new Error( 'Unknown window: ' + name );
-       }
-       if ( !( name in this.windows ) ) {
-               win = this.windows[name] = this.factory.create( name, this, { '$': this.$ } );
-               win.connect( this, {
-                       'opening': [ 'onWindowOpening', win ],
-                       'open': [ 'onWindowOpen', win ],
-                       'closing': [ 'onWindowClosing', win ],
-                       'close': [ 'onWindowClose', win ]
-               } );
-               this.$element.append( win.$element );
-               win.getFrame().load();
-       }
-       return this.windows[name];
-};
-/**
- * Modal dialog box.
- *
- * @class
- * @abstract
- * @extends OO.ui.Window
- *
- * @constructor
- * @param {OO.ui.WindowSet} windowSet Window set this dialog is part of
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [footless] Hide foot
- * @cfg {boolean} [small] Make the dialog small
- */
-OO.ui.Dialog = function OoUiDialog( windowSet, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Window.call( this, windowSet, config );
-
-       // Properties
-       this.visible = false;
-       this.footless = !!config.footless;
-       this.small = !!config.small;
-       this.onWindowMouseWheelHandler = OO.ui.bind( this.onWindowMouseWheel, this );
-       this.onDocumentKeyDownHandler = OO.ui.bind( this.onDocumentKeyDown, this );
-
-       // Events
-       this.$element.on( 'mousedown', false );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-dialog' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Dialog, OO.ui.Window );
-
-/* Static Properties */
-
-/**
- * Symbolic name of dialog.
- *
- * @abstract
- * @static
- * @property {string}
- * @inheritable
- */
-OO.ui.Dialog.static.name = '';
-
-/* Methods */
-
-/**
- * Handle close button click events.
- *
- * @method
- */
-OO.ui.Dialog.prototype.onCloseButtonClick = function () {
-       this.close( { 'action': 'cancel' } );
-};
-
-/**
- * Handle window mouse wheel events.
- *
- * @method
- * @param {jQuery.Event} e Mouse wheel event
- */
-OO.ui.Dialog.prototype.onWindowMouseWheel = function () {
-       return false;
-};
-
-/**
- * Handle document key down events.
- *
- * @method
- * @param {jQuery.Event} e Key down event
- */
-OO.ui.Dialog.prototype.onDocumentKeyDown = function ( e ) {
-       switch ( e.which ) {
-               case OO.ui.Keys.PAGEUP:
-               case OO.ui.Keys.PAGEDOWN:
-               case OO.ui.Keys.END:
-               case OO.ui.Keys.HOME:
-               case OO.ui.Keys.LEFT:
-               case OO.ui.Keys.UP:
-               case OO.ui.Keys.RIGHT:
-               case OO.ui.Keys.DOWN:
-                       // Prevent any key events that might cause scrolling
-                       return false;
-       }
-};
-
-/**
- * Handle frame document key down events.
- *
- * @method
- * @param {jQuery.Event} e Key down event
- */
-OO.ui.Dialog.prototype.onFrameDocumentKeyDown = function ( e ) {
-       if ( e.which === OO.ui.Keys.ESCAPE ) {
-               this.close( { 'action': 'cancel' } );
-               return false;
-       }
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.Dialog.prototype.initialize = function () {
-       // Parent method
-       OO.ui.Window.prototype.initialize.call( this );
-
-       // Properties
-       this.closeButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'close',
-               'title': OO.ui.msg( 'ooui-dialog-action-close' )
-       } );
-
-       // Events
-       this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
-       this.frame.$document.on( 'keydown', OO.ui.bind( this.onFrameDocumentKeyDown, this ) );
-
-       // Initialization
-       this.frame.$content.addClass( 'oo-ui-dialog-content' );
-       if ( this.footless ) {
-               this.frame.$content.addClass( 'oo-ui-dialog-content-footless' );
-       }
-       if ( this.small ) {
-               this.$frame.addClass( 'oo-ui-window-frame-small' );
-       }
-       this.closeButton.$element.addClass( 'oo-ui-window-closeButton' );
-       this.$head.append( this.closeButton.$element );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.Dialog.prototype.setup = function ( data ) {
-       // Parent method
-       OO.ui.Window.prototype.setup.call( this, data );
-
-       // Prevent scrolling in top-level window
-       this.$( window ).on( 'mousewheel', this.onWindowMouseWheelHandler );
-       this.$( document ).on( 'keydown', this.onDocumentKeyDownHandler );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.Dialog.prototype.teardown = function ( data ) {
-       // Parent method
-       OO.ui.Window.prototype.teardown.call( this, data );
-
-       // Allow scrolling in top-level window
-       this.$( window ).off( 'mousewheel', this.onWindowMouseWheelHandler );
-       this.$( document ).off( 'keydown', this.onDocumentKeyDownHandler );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.Dialog.prototype.close = function ( data ) {
-       if ( !this.opening && !this.closing && this.visible ) {
-               // Trigger transition
-               this.$element.addClass( 'oo-ui-dialog-closing' );
-               // Allow transition to complete before actually closing
-               setTimeout( OO.ui.bind( function () {
-                       this.$element.removeClass( 'oo-ui-dialog-closing' );
-                       // Parent method
-                       OO.ui.Window.prototype.close.call( this, data );
-               }, this ), 250 );
-       }
-};
-/**
- * Container for elements.
- *
- * @class
- * @abstract
- * @extends OO.ui.Element
- * @mixin OO.EventEmitter
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.Layout = function OoUiLayout( config ) {
-       // Initialize config
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Element.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-layout' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Layout, OO.ui.Element );
-
-OO.mixinClass( OO.ui.Layout, OO.EventEmitter );
-/**
- * User interface control.
- *
- * @class
- * @abstract
- * @extends OO.ui.Element
- * @mixin OO.EventEmitter
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [disabled=false] Disable
- */
-OO.ui.Widget = function OoUiWidget( config ) {
-       // Initialize config
-       config = $.extend( { 'disabled': false }, config );
-
-       // Parent constructor
-       OO.ui.Element.call( this, config );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-
-       // Properties
-       this.disabled = config.disabled;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-widget' );
-       this.setDisabled( this.disabled );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Widget, OO.ui.Element );
-
-OO.mixinClass( OO.ui.Widget, OO.EventEmitter );
-
-/* Methods */
-
-/**
- * Check if the widget is disabled.
- *
- * @method
- * @param {boolean} Button is disabled
- */
-OO.ui.Widget.prototype.isDisabled = function () {
-       return this.disabled;
-};
-
-/**
- * Set the disabled state of the widget.
- *
- * This should probably change the widgets's appearance and prevent it from being used.
- *
- * @method
- * @param {boolean} disabled Disable button
- * @chainable
- */
-OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
-       this.disabled = !!disabled;
-       if ( this.disabled ) {
-               this.$element.addClass( 'oo-ui-widget-disabled' );
-       } else {
-               this.$element.removeClass( 'oo-ui-widget-disabled' );
-       }
-       return this;
-};
-/**
- * Element with a button.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $button Button node, assigned to #$button
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [frameless] Render button without a frame
- * @cfg {number} [tabIndex] Button's tab index
- */
-OO.ui.ButtonedElement = function OoUiButtonedElement( $button, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Properties
-       this.$button = $button;
-       this.tabIndex = null;
-       this.active = false;
-       this.onMouseUpHandler = OO.ui.bind( this.onMouseUp, this );
-
-       // Events
-       this.$button.on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-buttonedElement' );
-       this.$button
-               .addClass( 'oo-ui-buttonedElement-button' )
-               .attr( 'role', 'button' )
-               .prop( 'tabIndex', config.tabIndex || 0 );
-       if ( config.frameless ) {
-               this.$element.addClass( 'oo-ui-buttonedElement-frameless' );
-       } else {
-               this.$element.addClass( 'oo-ui-buttonedElement-framed' );
-       }
-};
-
-/* Methods */
-
-/**
- * Handles mouse down events.
- *
- * @method
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.ButtonedElement.prototype.onMouseDown = function () {
-       this.tabIndex = this.$button.attr( 'tabIndex' );
-       // Remove the tab-index while the button is down to prevent the button from stealing focus
-       this.$button.removeAttr( 'tabIndex' );
-       this.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true );
-};
-
-/**
- * Handles mouse up events.
- *
- * @method
- * @param {jQuery.Event} e Mouse up event
- */
-OO.ui.ButtonedElement.prototype.onMouseUp = function () {
-       // Restore the tab-index after the button is up to restore the button's accesssibility
-       this.$button.attr( 'tabIndex', this.tabIndex );
-       this.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true );
-};
-
-/**
- * Set active state.
- *
- * @method
- * @param {boolean} [value] Make button active
- * @chainable
- */
-OO.ui.ButtonedElement.prototype.setActive = function ( value ) {
-       this.$element.toggleClass( 'oo-ui-buttonedElement-active', !!value );
-       return this;
-};
-/**
- * Element that can be automatically clipped to visible boundaies.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $clippable Nodes to clip, assigned to #$clippable
- */
-OO.ui.ClippableElement = function OoUiClippableElement( $clippable ) {
-       // Properties
-       this.$clippable = $clippable;
-       this.clipping = false;
-       this.clipped = false;
-       this.$clippableContainer = null;
-       this.$clippableScroller = null;
-       this.$clippableWindow = null;
-       this.idealWidth = null;
-       this.idealHeight = null;
-       this.onClippableContainerScrollHandler = OO.ui.bind( this.clip, this );
-       this.onClippableWindowResizeHandler = OO.ui.bind( this.clip, this );
-
-       // Initialization
-       this.$clippable.addClass( 'oo-ui-clippableElement-clippable' );
-};
-
-/* Methods */
-
-/**
- * Set clipping.
- *
- * @method
- * @param {boolean} value Enable clipping
- * @chainable
- */
-OO.ui.ClippableElement.prototype.setClipping = function ( value ) {
-       value = !!value;
-
-       if ( this.clipping !== value ) {
-               this.clipping = value;
-               if ( this.clipping ) {
-                       this.$clippableContainer = this.$( this.getClosestScrollableElementContainer() );
-                       // If the clippable container is the body, we have to listen to scroll events and check
-                       // jQuery.scrollTop on the window because of browser inconsistencies
-                       this.$clippableScroller = this.$clippableContainer.is( 'body' ) ?
-                               this.$( OO.ui.Element.getWindow( this.$clippableContainer ) ) :
-                               this.$clippableContainer;
-                       this.$clippableScroller.on( 'scroll', this.onClippableContainerScrollHandler );
-                       this.$clippableWindow = this.$( this.getElementWindow() )
-                               .on( 'resize', this.onClippableWindowResizeHandler );
-                       // Initial clip after visible
-                       setTimeout( OO.ui.bind( this.clip, this ) );
-               } else {
-                       this.$clippableContainer = null;
-                       this.$clippableScroller.off( 'scroll', this.onClippableContainerScrollHandler );
-                       this.$clippableScroller = null;
-                       this.$clippableWindow.off( 'resize', this.onClippableWindowResizeHandler );
-                       this.$clippableWindow = null;
-               }
-       }
-
-       return this;
-};
-
-/**
- * Check if the element will be clipped to fit the visible area of the nearest scrollable container.
- *
- * @method
- * @return {boolean} Element will be clipped to the visible area
- */
-OO.ui.ClippableElement.prototype.isClipping = function () {
-       return this.clipping;
-};
-
-/**
- * Check if the bottom or right of the element is being clipped by the nearest scrollable container.
- *
- * @method
- * @return {boolean} Part of the element is being clipped
- */
-OO.ui.ClippableElement.prototype.isClipped = function () {
-       return this.clipped;
-};
-
-/**
- * Set the ideal size.
- *
- * @method
- * @param {number|string} [width] Width as a number of pixels or CSS string with unit suffix
- * @param {number|string} [height] Height as a number of pixels or CSS string with unit suffix
- */
-OO.ui.ClippableElement.prototype.setIdealSize = function ( width, height ) {
-       this.idealWidth = width;
-       this.idealHeight = height;
-};
-
-/**
- * Clip element to visible boundaries and allow scrolling when needed.
- *
- * Element will be clipped the bottom or right of the element is within 10px of the edge of, or
- * overlapped by, the visible area of the nearest scrollable container.
- *
- * @method
- * @chainable
- */
-OO.ui.ClippableElement.prototype.clip = function () {
-       if ( !this.clipping ) {
-               // this.$clippableContainer and this.$clippableWindow are null, so the below will fail
-               return this;
-       }
-
-       var buffer = 10,
-               cOffset = this.$clippable.offset(),
-               ccOffset = this.$clippableContainer.offset() || { 'top': 0, 'left': 0 },
-               ccHeight = this.$clippableContainer.innerHeight() - buffer,
-               ccWidth = this.$clippableContainer.innerWidth() - buffer,
-               scrollTop = this.$clippableScroller.scrollTop(),
-               scrollLeft = this.$clippableScroller.scrollLeft(),
-               desiredWidth = ( ccOffset.left + scrollLeft + ccWidth ) - cOffset.left,
-               desiredHeight = ( ccOffset.top + scrollTop + ccHeight ) - cOffset.top,
-               naturalWidth = this.$clippable.prop( 'scrollWidth' ),
-               naturalHeight = this.$clippable.prop( 'scrollHeight' ),
-               clipWidth = desiredWidth < naturalWidth,
-               clipHeight = desiredHeight < naturalHeight;
-
-       if ( clipWidth ) {
-               this.$clippable.css( { 'overflow-x': 'auto', 'width': desiredWidth } );
-       } else {
-               this.$clippable.css( { 'overflow-x': '', 'width': this.idealWidth || '' } );
-       }
-       if ( clipHeight ) {
-               this.$clippable.css( { 'overflow-y': 'auto', 'height': desiredHeight } );
-       } else {
-               this.$clippable.css( { 'overflow-y': '', 'height': this.idealHeight || '' } );
-       }
-
-       this.clipped = clipWidth || clipHeight;
-
-       return this;
-};
-/**
- * Element with named flags, used for styling, that can be added, removed and listed and checked.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string[]} [flags=[]] Styling flags, e.g. 'primary', 'destructive' or 'constructive'
- */
-OO.ui.FlaggableElement = function OoUiFlaggableElement( config ) {
-       // Config initialization
-       config = config || {};
-
-       // Properties
-       this.flags = {};
-
-       // Initialization
-       this.setFlags( config.flags );
-};
-
-/* Methods */
-
-/**
- * Check if a flag is set.
- *
- * @method
- * @param {string} flag Flag name to check
- * @returns {boolean} Has flag
- */
-OO.ui.FlaggableElement.prototype.hasFlag = function ( flag ) {
-       return flag in this.flags;
-};
-
-/**
- * Get the names of all flags.
- *
- * @method
- * @returns {string[]} flags Flag names
- */
-OO.ui.FlaggableElement.prototype.getFlags = function () {
-       return Object.keys( this.flags );
-};
-
-/**
- * Add one or more flags.
- *
- * @method
- * @param {string[]|Object.<string, boolean>} flags List of flags to add, or list of set/remove
- *  values, keyed by flag name
- * @chainable
- */
-OO.ui.FlaggableElement.prototype.setFlags = function ( flags ) {
-       var i, len, flag,
-               classPrefix = 'oo-ui-flaggableElement-';
-
-       if ( Array.isArray( flags ) ) {
-               for ( i = 0, len = flags.length; i < len; i++ ) {
-                       flag = flags[i];
-                       // Set
-                       this.flags[flag] = true;
-                       this.$element.addClass( classPrefix + flag );
-               }
-       } else if ( OO.isPlainObject( flags ) ) {
-               for ( flag in flags ) {
-                       if ( flags[flags] ) {
-                               // Set
-                               this.flags[flag] = true;
-                               this.$element.addClass( classPrefix + flag );
-                       } else {
-                               // Remove
-                               delete this.flags[flag];
-                               this.$element.removeClass( classPrefix + flag );
-                       }
-               }
-       }
-       return this;
-};
-/**
- * Element containing a sequence of child elements.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $group Container node, assigned to #$group
- * @param {Object} [config] Configuration options
- * @cfg {Object.<string,string>} [aggregations] Events to aggregate, keyed by item event name
- */
-OO.ui.GroupElement = function OoUiGroupElement( $group, config ) {
-       // Configuration
-       config = config || {};
-
-       // Properties
-       this.$group = $group;
-       this.items = [];
-       this.$items = this.$( [] );
-       this.aggregate = !$.isEmptyObject( config.aggregations );
-       this.aggregations = config.aggregations || {};
-};
-
-/* Methods */
-
-/**
- * Get items.
- *
- * @method
- * @returns {OO.ui.Element[]} Items
- */
-OO.ui.GroupElement.prototype.getItems = function () {
-       return this.items.slice( 0 );
-};
-
-/**
- * Add items.
- *
- * @method
- * @param {OO.ui.Element[]} items Item
- * @param {number} [index] Index to insert items at
- * @chainable
- */
-OO.ui.GroupElement.prototype.addItems = function ( items, index ) {
-       var i, len, item, event, events, currentIndex,
-               $items = this.$( [] );
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-
-               // Check if item exists then remove it first, effectively "moving" it
-               currentIndex = this.items.indexOf( item );
-               if ( currentIndex >= 0 ) {
-                       this.removeItems( [ item ] );
-                       // Adjust index to compensate for removal
-                       if ( currentIndex < index ) {
-                               index--;
-                       }
-               }
-               // Add the item
-               if ( this.aggregate ) {
-                       events = {};
-                       for ( event in this.aggregations ) {
-                               events[event] = [ 'emit', this.aggregations[event], item ];
-                       }
-                       item.connect( this, events );
-               }
-               $items = $items.add( item.$element );
-       }
-
-       if ( index === undefined || index < 0 || index >= this.items.length ) {
-               this.$group.append( $items );
-               this.items.push.apply( this.items, items );
-       } else if ( index === 0 ) {
-               this.$group.prepend( $items );
-               this.items.unshift.apply( this.items, items );
-       } else {
-               this.$items.eq( index ).before( $items );
-               this.items.splice.apply( this.items, [ index, 0 ].concat( items ) );
-       }
-
-       this.$items = this.$items.add( $items );
-
-       return this;
-};
-
-/**
- * Remove items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @param {OO.ui.Element[]} items Items to remove
- * @chainable
- */
-OO.ui.GroupElement.prototype.removeItems = function ( items ) {
-       var i, len, item, index;
-
-       // Remove specific items
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               index = this.items.indexOf( item );
-               if ( index !== -1 ) {
-                       if ( this.aggregate ) {
-                               item.disconnect( this );
-                       }
-                       this.items.splice( index, 1 );
-                       item.$element.detach();
-                       this.$items = this.$items.not( item.$element );
-               }
-       }
-
-       return this;
-};
-
-/**
- * Clear all items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @chainable
- */
-OO.ui.GroupElement.prototype.clearItems = function () {
-       var i, len, item;
-
-       // Remove all items
-       if ( this.aggregate ) {
-               for ( i = 0, len = this.items.length; i < len; i++ ) {
-                       item.disconnect( this );
-               }
-       }
-       this.items = [];
-       this.$items.detach();
-       this.$items = this.$( [] );
-};
-/**
- * Element containing an icon.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $icon Icon node, assigned to #$icon
- * @param {Object} [config] Configuration options
- * @cfg {Object|string} [icon=''] Symbolic icon name, or map of icon names keyed by language ID;
- *  use the 'default' key to specify the icon to be used when there is no icon in the user's
- *  language
- */
-OO.ui.IconedElement = function OoUiIconedElement( $icon, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.$icon = $icon;
-       this.icon = null;
-
-       // Initialization
-       this.$icon.addClass( 'oo-ui-iconedElement-icon' );
-       this.setIcon( config.icon || this.constructor.static.icon );
-};
-
-/* Static Properties */
-
-OO.ui.IconedElement.static = {};
-
-/**
- * Icon.
- *
- * Value should be the unique portion of an icon CSS class name, such as 'up' for 'oo-ui-icon-up'.
- *
- * For i18n purposes, this property can be an object containing a `default` icon name property and
- * additional icon names keyed by language code.
- *
- * Example of i18n icon definition:
- *     { 'default': 'bold-a', 'en': 'bold-b', 'de': 'bold-f' }
- *
- * @static
- * @inheritable
- * @property {Object|string} Symbolic icon name, or map of icon names keyed by language ID;
- *  use the 'default' key to specify the icon to be used when there is no icon in the user's
- *  language
- */
-OO.ui.IconedElement.static.icon = null;
-
-/* Methods */
-
-/**
- * Set icon.
- *
- * @method
- * @param {Object|string} icon Symbolic icon name, or map of icon names keyed by language ID;
- *  use the 'default' key to specify the icon to be used when there is no icon in the user's
- *  language
- * @chainable
- */
-OO.ui.IconedElement.prototype.setIcon = function ( icon ) {
-       icon = OO.isPlainObject( icon ) ? OO.ui.getLocalValue( icon, null, 'default' ) : icon;
-
-       if ( this.icon ) {
-               this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
-       }
-       if ( typeof icon === 'string' ) {
-               icon = icon.trim();
-               if ( icon.length ) {
-                       this.$icon.addClass( 'oo-ui-icon-' + icon );
-                       this.icon = icon;
-               }
-       }
-       this.$element.toggleClass( 'oo-ui-iconedElement', !!this.icon );
-
-       return this;
-};
-
-/**
- * Get icon.
- *
- * @method
- * @returns {string} Icon
- */
-OO.ui.IconedElement.prototype.getIcon = function () {
-       return this.icon;
-};
-/**
- * Element containing an indicator.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $indicator Indicator node, assigned to #$indicator
- * @param {Object} [config] Configuration options
- * @cfg {string} [indicator] Symbolic indicator name
- * @cfg {string} [indicatorTitle] Indicator title text or a function that return text
- */
-OO.ui.IndicatedElement = function OoUiIndicatedElement( $indicator, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.$indicator = $indicator;
-       this.indicator = null;
-       this.indicatorLabel = null;
-
-       // Initialization
-       this.$indicator.addClass( 'oo-ui-indicatedElement-indicator' );
-       this.setIndicator( config.indicator || this.constructor.static.indicator );
-       this.setIndicatorTitle( config.indicatorTitle  || this.constructor.static.indicatorTitle );
-};
-
-/* Static Properties */
-
-OO.ui.IndicatedElement.static = {};
-
-/**
- * indicator.
- *
- * @static
- * @inheritable
- * @property {string|null} Symbolic indicator name or null for no indicator
- */
-OO.ui.IndicatedElement.static.indicator = null;
-
-/**
- * Indicator title.
- *
- * @static
- * @inheritable
- * @property {string|Function|null} Indicator title text, a function that return text or null for no
- *  indicator title
- */
-OO.ui.IndicatedElement.static.indicatorTitle = null;
-
-/* Methods */
-
-/**
- * Set indicator.
- *
- * @method
- * @param {string|null} indicator Symbolic name of indicator to use or null for no indicator
- * @chainable
- */
-OO.ui.IndicatedElement.prototype.setIndicator = function ( indicator ) {
-       if ( this.indicator ) {
-               this.$indicator.removeClass( 'oo-ui-indicator-' + this.indicator );
-               this.indicator = null;
-       }
-       if ( typeof indicator === 'string' ) {
-               indicator = indicator.trim();
-               if ( indicator.length ) {
-                       this.$indicator.addClass( 'oo-ui-indicator-' + indicator );
-                       this.indicator = indicator;
-               }
-       }
-       this.$element.toggleClass( 'oo-ui-indicatedElement', !!this.indicator );
-
-       return this;
-};
-
-/**
- * Set indicator label.
- *
- * @method
- * @param {string|Function|null} indicator Indicator title text, a function that return text or null
- *  for no indicator title
- * @chainable
- */
-OO.ui.IndicatedElement.prototype.setIndicatorTitle = function ( indicatorTitle ) {
-       this.indicatorTitle = indicatorTitle = OO.ui.resolveMsg( indicatorTitle );
-
-       if ( typeof indicatorTitle === 'string' && indicatorTitle.length ) {
-               this.$indicator.attr( 'title', indicatorTitle );
-       } else {
-               this.$indicator.removeAttr( 'title' );
-       }
-
-       return this;
-};
-
-/**
- * Get indicator.
- *
- * @method
- * @returns {string} title Symbolic name of indicator
- */
-OO.ui.IndicatedElement.prototype.getIndicator = function () {
-       return this.indicator;
-};
-
-/**
- * Get indicator title.
- *
- * @method
- * @returns {string} Indicator title text
- */
-OO.ui.IndicatedElement.prototype.getIndicatorTitle = function () {
-       return this.indicatorTitle;
-};
-/**
- * Element containing a label.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $label Label node, assigned to #$label
- * @param {Object} [config] Configuration options
- * @cfg {jQuery|string|Function} [label] Label nodes, text or a function that returns nodes or text
- */
-OO.ui.LabeledElement = function OoUiLabeledElement( $label, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.$label = $label;
-       this.label = null;
-
-       // Initialization
-       this.$label.addClass( 'oo-ui-labeledElement-label' );
-       this.setLabel( config.label || this.constructor.static.label );
-};
-
-/* Static Properties */
-
-OO.ui.LabeledElement.static = {};
-
-/**
- * Label.
- *
- * @static
- * @inheritable
- * @property {string|Function|null} Label text; a function that returns a nodes or text; or null for
- *  no label
- */
-OO.ui.LabeledElement.static.label = null;
-
-/* Methods */
-
-/**
- * Set the label.
- *
- * @method
- * @param {jQuery|string|Function|null} label Label nodes; text; a function that retuns nodes or
- *  text; or null for no label
- * @chainable
- */
-OO.ui.LabeledElement.prototype.setLabel = function ( label ) {
-       var empty = false;
-
-       this.label = label = OO.ui.resolveMsg( label ) || null;
-       if ( typeof label === 'string' && label.trim() ) {
-               this.$label.text( label );
-       } else if ( label instanceof jQuery ) {
-               this.$label.empty().append( label );
-       } else {
-               this.$label.empty();
-               empty = true;
-       }
-       this.$element.toggleClass( 'oo-ui-labeledElement', !empty );
-       this.$label.css( 'display', empty ? 'none' : '' );
-
-       return this;
-};
-
-/**
- * Get the label.
- *
- * @method
- * @returns {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
- *  text; or null for no label
- */
-OO.ui.LabeledElement.prototype.getLabel = function () {
-       return this.label;
-};
-
-/**
- * Fit the label.
- *
- * @method
- * @chainable
- */
-OO.ui.LabeledElement.prototype.fitLabel = function () {
-       if ( this.$label.autoEllipsis ) {
-               this.$label.autoEllipsis( { 'hasSpan': false, 'tooltip': true } );
-       }
-       return this;
-};
-/**
- * Popuppable element.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {number} [popupWidth=320] Width of popup
- * @cfg {number} [popupHeight] Height of popup
- * @cfg {Object} [popup] Configuration to pass to popup
- */
-OO.ui.PopuppableElement = function OoUiPopuppableElement( config ) {
-       // Configuration initialization
-       config = $.extend( { 'popupWidth': 320 }, config );
-
-       // Properties
-       this.popup = new OO.ui.PopupWidget( $.extend(
-               { 'align': 'center', 'autoClose': true },
-               config.popup,
-               { '$': this.$, '$autoCloseIgnore': this.$element }
-       ) );
-       this.popupWidth = config.popupWidth;
-       this.popupHeight = config.popupHeight;
-};
-
-/* Methods */
-
-/**
- * Get popup.
- *
- * @method
- * @returns {OO.ui.PopupWidget} Popup widget
- */
-OO.ui.PopuppableElement.prototype.getPopup = function () {
-       return this.popup;
-};
-
-/**
- * Show popup.
- *
- * @method
- */
-OO.ui.PopuppableElement.prototype.showPopup = function () {
-       this.popup.show().display( this.popupWidth, this.popupHeight );
-};
-
-/**
- * Hide popup.
- *
- * @method
- */
-OO.ui.PopuppableElement.prototype.hidePopup = function () {
-       this.popup.hide();
-};
-/**
- * Element with a title.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {jQuery} $label Titled node, assigned to #$titled
- * @param {Object} [config] Configuration options
- * @cfg {string|Function} [title] Title text or a function that returns text
- */
-OO.ui.TitledElement = function OoUiTitledElement( $titled, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.$titled = $titled;
-       this.title = null;
-
-       // Initialization
-       this.setTitle( config.title || this.constructor.static.title );
-};
-
-/* Static Properties */
-
-OO.ui.TitledElement.static = {};
-
-/**
- * Title.
- *
- * @static
- * @inheritable
- * @property {string|Function} Title text or a function that returns text
- */
-OO.ui.TitledElement.static.title = null;
-
-/* Methods */
-
-/**
- * Set title.
- *
- * @method
- * @param {string|Function|null} title Title text, a function that returns text or null for no title
- * @chainable
- */
-OO.ui.TitledElement.prototype.setTitle = function ( title ) {
-       this.title = title = OO.ui.resolveMsg( title ) || null;
-
-       if ( typeof title === 'string' && title.length ) {
-               this.$titled.attr( 'title', title );
-       } else {
-               this.$titled.removeAttr( 'title' );
-       }
-
-       return this;
-};
-
-/**
- * Get title.
- *
- * @method
- * @returns {string} Title string
- */
-OO.ui.TitledElement.prototype.getTitle = function () {
-       return this.title;
-};
-/**
- * Generic toolbar tool.
- *
- * @class
- * @abstract
- * @extends OO.ui.Widget
- * @mixins OO.ui.IconedElement
- *
- * @constructor
- * @param {OO.ui.ToolGroup} toolGroup
- * @param {Object} [config] Configuration options
- * @cfg {string|Function} [title] Title text or a function that returns text
- */
-OO.ui.Tool = function OoUiTool( toolGroup, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-
-       // Properties
-       this.toolGroup = toolGroup;
-       this.toolbar = this.toolGroup.getToolbar();
-       this.active = false;
-       this.$title = this.$( '<span>' );
-       this.$link = this.$( '<a>' );
-       this.title = null;
-
-       // Events
-       this.toolbar.connect( this, { 'updateState': 'onUpdateState' } );
-
-       // Initialization
-       this.$title.addClass( 'oo-ui-tool-title' );
-       this.$link
-               .addClass( 'oo-ui-tool-link' )
-               .append( this.$icon, this.$title );
-       this.$element
-               .data( 'oo-ui-tool', this )
-               .addClass(
-                       'oo-ui-tool ' + 'oo-ui-tool-name-' +
-                       this.constructor.static.name.replace( /^([^\/]+)\/([^\/]+).*$/, '$1-$2' )
-               )
-               .append( this.$link );
-       this.setTitle( config.title || this.constructor.static.title );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Tool, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.Tool, OO.ui.IconedElement );
-
-/* Events */
-
-/**
- * @event select
- */
-
-/* Static Properties */
-
-OO.ui.Tool.static.tagName = 'span';
-
-/**
- * Symbolic name of tool.
- *
- * @abstract
- * @static
- * @property {string}
- * @inheritable
- */
-OO.ui.Tool.static.name = '';
-
-/**
- * Tool group.
- *
- * @abstract
- * @static
- * @property {string}
- * @inheritable
- */
-OO.ui.Tool.static.group = '';
-
-/**
- * Tool title.
- *
- * Title is used as a tooltip when the tool is part of a bar tool group, or a label when the tool
- * is part of a list or menu tool group. If a trigger is associated with an action by the same name
- * as the tool, a description of its keyboard shortcut for the appropriate platform will be
- * appended to the title if the tool is part of a bar tool group.
- *
- * @abstract
- * @static
- * @property {string|Function} Title text or a function that returns text
- * @inheritable
- */
-OO.ui.Tool.static.title = '';
-
-/**
- * Tool can be automatically added to tool groups.
- *
- * @static
- * @property {boolean}
- * @inheritable
- */
-OO.ui.Tool.static.autoAdd = true;
-
-/**
- * Check if this tool is compatible with given data.
- *
- * @method
- * @static
- * @inheritable
- * @param {Mixed} data Data to check
- * @returns {boolean} Tool can be used with data
- */
-OO.ui.Tool.static.isCompatibleWith = function () {
-       return false;
-};
-
-/* Methods */
-
-/**
- * Handle the toolbar state being updated.
- *
- * This is an abstract method that must be overridden in a concrete subclass.
- *
- * @abstract
- * @method
- */
-OO.ui.Tool.prototype.onUpdateState = function () {
-       throw new Error(
-               'OO.ui.Tool.onUpdateState not implemented in this subclass:' + this.constructor
-       );
-};
-
-/**
- * Handle the tool being selected.
- *
- * This is an abstract method that must be overridden in a concrete subclass.
- *
- * @abstract
- * @method
- */
-OO.ui.Tool.prototype.onSelect = function () {
-       throw new Error(
-               'OO.ui.Tool.onSelect not implemented in this subclass:' + this.constructor
-       );
-};
-
-/**
- * Check if the button is active.
- *
- * @method
- * @param {boolean} Button is active
- */
-OO.ui.Tool.prototype.isActive = function () {
-       return this.active;
-};
-
-/**
- * Make the button appear active or inactive.
- *
- * @method
- * @param {boolean} state Make button appear active
- */
-OO.ui.Tool.prototype.setActive = function ( state ) {
-       this.active = !!state;
-       if ( this.active ) {
-               this.$element.addClass( 'oo-ui-tool-active' );
-       } else {
-               this.$element.removeClass( 'oo-ui-tool-active' );
-       }
-};
-
-/**
- * Get the tool title.
- *
- * @method
- * @param {string|Function} title Title text or a function that returns text
- * @chainable
- */
-OO.ui.Tool.prototype.setTitle = function ( title ) {
-       this.title = OO.ui.resolveMsg( title );
-       this.updateTitle();
-       return this;
-};
-
-/**
- * Get the tool title.
- *
- * @method
- * @returns {string} Title text
- */
-OO.ui.Tool.prototype.getTitle = function () {
-       return this.title;
-};
-
-/**
- * Get the tool's symbolic name.
- *
- * @method
- * @returns {string} Symbolic name of tool
- */
-OO.ui.Tool.prototype.getName = function () {
-       return this.constructor.static.name;
-};
-
-/**
- * Update the title.
- *
- * @method
- */
-OO.ui.Tool.prototype.updateTitle = function () {
-       var titleTooltips = this.toolGroup.constructor.static.titleTooltips,
-               accelTooltips = this.toolGroup.constructor.static.accelTooltips,
-               accel = this.toolbar.getToolAccelerator( this.constructor.static.name ),
-               tooltipParts = [];
-
-       this.$title.empty()
-               .text( this.title )
-               .append(
-                       this.$( '<span>' )
-                               .addClass( 'oo-ui-tool-accel' )
-                               .text( accel )
-               );
-
-       if ( titleTooltips && typeof this.title === 'string' && this.title.length ) {
-               tooltipParts.push( this.title );
-       }
-       if ( accelTooltips && typeof accel === 'string' && accel.length ) {
-               tooltipParts.push( accel );
-       }
-       if ( tooltipParts.length ) {
-               this.$link.attr( 'title', tooltipParts.join( ' ' ) );
-       } else {
-               this.$link.removeAttr( 'title' );
-       }
-};
-
-/**
- * Destroy tool.
- *
- * @method
- */
-OO.ui.Tool.prototype.destroy = function () {
-       this.toolbar.disconnect( this );
-       this.$element.remove();
-};
-/**
- * Collection of tool groups.
- *
- * @class
- * @extends OO.ui.Element
- * @mixins OO.EventEmitter
- * @mixins OO.ui.GroupElement
- *
- * @constructor
- * @param {OO.Factory} toolFactory Factory for creating tools
- * @param {Object} [options] Configuration options
- * @cfg {boolean} [actions] Add an actions section opposite to the tools
- * @cfg {boolean} [shadow] Add a shadow below the toolbar
- */
-OO.ui.Toolbar = function OoUiToolbar( toolFactory, options ) {
-       // Configuration initialization
-       options = options || {};
-
-       // Parent constructor
-       OO.ui.Element.call( this, options );
-
-       // Mixin constructors
-       OO.EventEmitter.call( this );
-       OO.ui.GroupElement.call( this, this.$( '<div>' ) );
-
-       // Properties
-       this.toolFactory = toolFactory;
-       this.groups = [];
-       this.tools = {};
-       this.$bar = this.$( '<div>' );
-       this.$actions = this.$( '<div>' );
-       this.initialized = false;
-
-       // Events
-       this.$element
-               .add( this.$bar ).add( this.$group ).add( this.$actions )
-               .on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
-
-       // Initialization
-       this.$group.addClass( 'oo-ui-toolbar-tools' );
-       this.$bar.addClass( 'oo-ui-toolbar-bar' ).append( this.$group );
-       if ( options.actions ) {
-               this.$actions.addClass( 'oo-ui-toolbar-actions' );
-               this.$bar.append( this.$actions );
-       }
-       this.$bar.append( '<div style="clear:both"></div>' );
-       if ( options.shadow ) {
-               this.$bar.append( '<div class="oo-ui-toolbar-shadow"></div>' );
-       }
-       this.$element.addClass( 'oo-ui-toolbar' ).append( this.$bar );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.Toolbar, OO.ui.Element );
-
-OO.mixinClass( OO.ui.Toolbar, OO.EventEmitter );
-OO.mixinClass( OO.ui.Toolbar, OO.ui.GroupElement );
-
-/* Methods */
-
-/**
- * Get the tool factory.
- *
- * @method
- * @returns {OO.Factory} Tool factory
- */
-OO.ui.Toolbar.prototype.getToolFactory = function () {
-       return this.toolFactory;
-};
-
-/**
- * Handles mouse down events.
- *
- * @method
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.Toolbar.prototype.onMouseDown = function ( e ) {
-       var $closestWidgetToEvent = this.$( e.target ).closest( '.oo-ui-widget' ),
-               $closestWidgetToToolbar = this.$element.closest( '.oo-ui-widget' );
-       if ( !$closestWidgetToEvent.length || $closestWidgetToEvent[0] === $closestWidgetToToolbar[0] ) {
-               return false;
-       }
-};
-
-/**
- * Sets up handles and preloads required information for the toolbar to work.
- * This must be called immediately after it is attached to a visible document.
- */
-OO.ui.Toolbar.prototype.initialize = function () {
-       this.initialized = true;
-};
-
-/**
- * Setup toolbar.
- *
- * Tools can be specified in the following ways:
- *  - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
- *  - All tools in a group: `{ 'group': 'group-name' }`
- *  - All tools: `'*'` - Using this will make the group a list with a "More" label by default
- *
- * @method
- * @param {Object.<string,Array>} groups List of tool group configurations
- * @param {Array|string} [groups.include] Tools to include
- * @param {Array|string} [groups.exclude] Tools to exclude
- * @param {Array|string} [groups.promote] Tools to promote to the beginning
- * @param {Array|string} [groups.demote] Tools to demote to the end
- */
-OO.ui.Toolbar.prototype.setup = function ( groups ) {
-       var i, len, type, group,
-               items = [],
-               // TODO: Use a registry instead
-               defaultType = 'bar',
-               constructors = {
-                       'bar': OO.ui.BarToolGroup,
-                       'list': OO.ui.ListToolGroup,
-                       'menu': OO.ui.MenuToolGroup
-               };
-
-       // Cleanup previous groups
-       this.reset();
-
-       // Build out new groups
-       for ( i = 0, len = groups.length; i < len; i++ ) {
-               group = groups[i];
-               if ( group.include === '*' ) {
-                       // Apply defaults to catch-all groups
-                       if ( group.type === undefined ) {
-                               group.type = 'list';
-                       }
-                       if ( group.label === undefined ) {
-                               group.label = 'ooui-toolbar-more';
-                       }
-               }
-               type = constructors[group.type] ? group.type : defaultType;
-               items.push(
-                       new constructors[type]( this, $.extend( { '$': this.$ }, group ) )
-               );
-       }
-       this.addItems( items );
-};
-
-/**
- * Remove all tools and groups from the toolbar.
- */
-OO.ui.Toolbar.prototype.reset = function () {
-       var i, len;
-
-       this.groups = [];
-       this.tools = {};
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               this.items[i].destroy();
-       }
-       this.clearItems();
-};
-
-/**
- * Destroys toolbar, removing event handlers and DOM elements.
- *
- * Call this whenever you are done using a toolbar.
- */
-OO.ui.Toolbar.prototype.destroy = function () {
-       this.reset();
-       this.$element.remove();
-};
-
-/**
- * Check if tool has not been used yet.
- *
- * @param {string} name Symbolic name of tool
- * @return {boolean} Tool is available
- */
-OO.ui.Toolbar.prototype.isToolAvailable = function ( name ) {
-       return !this.tools[name];
-};
-
-/**
- * Prevent tool from being used again.
- *
- * @param {OO.ui.Tool} tool Tool to reserve
- */
-OO.ui.Toolbar.prototype.reserveTool = function ( tool ) {
-       this.tools[tool.getName()] = tool;
-};
-
-/**
- * Allow tool to be used again.
- *
- * @param {OO.ui.Tool} tool Tool to release
- */
-OO.ui.Toolbar.prototype.releaseTool = function ( tool ) {
-       delete this.tools[tool.getName()];
-};
-
-/**
- * Get accelerator label for tool.
- *
- * This is a stub that should be overridden to provide access to accelerator information.
- *
- * @param {string} name Symbolic name of tool
- * @returns {string|undefined} Tool accelerator label if available
- */
-OO.ui.Toolbar.prototype.getToolAccelerator = function () {
-       return undefined;
-};
-/**
- * Factory for tools.
- *
- * @class
- * @extends OO.Factory
- * @constructor
- */
-OO.ui.ToolFactory = function OoUiToolFactory() {
-       // Parent constructor
-       OO.Factory.call( this );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ToolFactory, OO.Factory );
-
-/* Methods */
-
-OO.ui.ToolFactory.prototype.getTools = function ( include, exclude, promote, demote ) {
-       var i, len, included, promoted, demoted,
-               auto = [],
-               used = {};
-
-       // Collect included and not excluded tools
-       included = OO.simpleArrayDifference( this.extract( include ), this.extract( exclude ) );
-
-       // Promotion
-       promoted = this.extract( promote, used );
-       demoted = this.extract( demote, used );
-
-       // Auto
-       for ( i = 0, len = included.length; i < len; i++ ) {
-               if ( !used[included[i]] ) {
-                       auto.push( included[i] );
-               }
-       }
-
-       return promoted.concat( auto ).concat( demoted );
-};
-
-/**
- * Get a flat list of names from a list of names or groups.
- *
- * Tools can be specified in the following ways:
- *  - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
- *  - All tools in a group: `{ 'group': 'group-name' }`
- *  - All tools: `'*'`
- *
- * @private
- * @param {Array|string} collection List of tools
- * @param {Object} [used] Object with names that should be skipped as properties; extracted
- *   names will be added as properties
- * @return {string[]} List of extracted names
- */
-OO.ui.ToolFactory.prototype.extract = function ( collection, used ) {
-       var i, len, item, name, tool,
-               names = [];
-
-       if ( collection === '*' ) {
-               for ( name in this.registry ) {
-                       tool = this.registry[name];
-                       if (
-                               // Only add tools by group name when auto-add is enabled
-                               tool.static.autoAdd &&
-                               // Exclude already used tools
-                               ( !used || !used[name] )
-                       ) {
-                               names.push( name );
-                               if ( used ) {
-                                       used[name] = true;
-                               }
-                       }
-               }
-       } else if ( Array.isArray( collection ) ) {
-               for ( i = 0, len = collection.length; i < len; i++ ) {
-                       item = collection[i];
-                       // Allow plain strings as shorthand for named tools
-                       if ( typeof item === 'string' ) {
-                               item = { 'name': item };
-                       }
-                       if ( OO.isPlainObject( item ) ) {
-                               if ( item.group ) {
-                                       for ( name in this.registry ) {
-                                               tool = this.registry[name];
-                                               if (
-                                                       // Include tools with matching group
-                                                       tool.static.group === item.group &&
-                                                       // Only add tools by group name when auto-add is enabled
-                                                       tool.static.autoAdd &&
-                                                       // Exclude already used tools
-                                                       ( !used || !used[name] )
-                                               ) {
-                                                       names.push( name );
-                                                       if ( used ) {
-                                                               used[name] = true;
-                                                       }
-                                               }
-                                       }
-                               }
-                               // Include tools with matching name and exclude already used tools
-                               else if ( item.name && ( !used || !used[item.name] ) ) {
-                                       names.push( item.name );
-                                       if ( used ) {
-                                               used[item.name] = true;
-                                       }
-                               }
-                       }
-               }
-       }
-       return names;
-};
-/**
- * Collection of tools.
- *
- * @class
- * @abstract
- * @extends OO.ui.Widget
- * @mixins OO.ui.GroupElement
- *
- * Tools can be specified in the following ways:
- *  - A specific tool: `{ 'name': 'tool-name' }` or `'tool-name'`
- *  - All tools in a group: `{ 'group': 'group-name' }`
- *  - All tools: `'*'`
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- * @cfg {Array|string} [include=[]] List of tools to include
- * @cfg {Array|string} [exclude=[]] List of tools to exclude
- * @cfg {Array|string} [promote=[]] List of tools to promote to the beginning
- * @cfg {Array|string} [demote=[]] List of tools to demote to the end
- */
-OO.ui.ToolGroup = function OoUiToolGroup( toolbar, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$( '<div>' ) );
-
-       // Properties
-       this.toolbar = toolbar;
-       this.tools = {};
-       this.pressed = null;
-       this.include = config.include || [];
-       this.exclude = config.exclude || [];
-       this.promote = config.promote || [];
-       this.demote = config.demote || [];
-       this.onCapturedMouseUpHandler = OO.ui.bind( this.onCapturedMouseUp, this );
-
-       // Events
-       this.$element.on( {
-               'mousedown': OO.ui.bind( this.onMouseDown, this ),
-               'mouseup': OO.ui.bind( this.onMouseUp, this ),
-               'mouseover': OO.ui.bind( this.onMouseOver, this ),
-               'mouseout': OO.ui.bind( this.onMouseOut, this )
-       } );
-       this.toolbar.getToolFactory().connect( this, { 'register': 'onToolFactoryRegister' } );
-
-       // Initialization
-       this.$group.addClass( 'oo-ui-toolGroup-tools' );
-       this.$element
-               .addClass( 'oo-ui-toolGroup' )
-               .append( this.$group );
-       this.populate();
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ToolGroup, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.ToolGroup, OO.ui.GroupElement );
-
-/* Events */
-
-/**
- * @event update
- */
-
-/* Static Properties */
-
-/**
- * Show labels in tooltips.
- *
- * @static
- * @property {boolean}
- * @inheritable
- */
-OO.ui.ToolGroup.static.titleTooltips = false;
-
-/**
- * Show acceleration labels in tooltips.
- *
- * @static
- * @property {boolean}
- * @inheritable
- */
-OO.ui.ToolGroup.static.accelTooltips = false;
-
-/* Methods */
-
-/**
- * Handle mouse down events.
- *
- * @method
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.ToolGroup.prototype.onMouseDown = function ( e ) {
-       if ( !this.disabled && e.which === 1 ) {
-               this.pressed = this.getTargetTool( e );
-               if ( this.pressed ) {
-                       this.pressed.setActive( true );
-                       this.getElementDocument().addEventListener(
-                               'mouseup', this.onCapturedMouseUpHandler, true
-                       );
-                       return false;
-               }
-       }
-};
-
-/**
- * Handle captured mouse up events.
- *
- * @method
- * @param {Event} e Mouse up event
- */
-OO.ui.ToolGroup.prototype.onCapturedMouseUp = function ( e ) {
-       this.getElementDocument().removeEventListener( 'mouseup', this.onCapturedMouseUpHandler, true );
-       // onMouseUp may be called a second time, depending on where the mouse is when the button is
-       // released, but since `this.pressed` will no longer be true, the second call will be ignored.
-       this.onMouseUp( e );
-};
-
-/**
- * Handle mouse up events.
- *
- * @method
- * @param {jQuery.Event} e Mouse up event
- */
-OO.ui.ToolGroup.prototype.onMouseUp = function ( e ) {
-       var tool = this.getTargetTool( e );
-
-       if ( !this.disabled && e.which === 1 && this.pressed && this.pressed === tool ) {
-               this.pressed.onSelect();
-       }
-
-       this.pressed = null;
-       return false;
-};
-
-/**
- * Handle mouse over events.
- *
- * @method
- * @param {jQuery.Event} e Mouse over event
- */
-OO.ui.ToolGroup.prototype.onMouseOver = function ( e ) {
-       var tool = this.getTargetTool( e );
-
-       if ( this.pressed && this.pressed === tool ) {
-               this.pressed.setActive( true );
-       }
-};
-
-/**
- * Handle mouse out events.
- *
- * @method
- * @param {jQuery.Event} e Mouse out event
- */
-OO.ui.ToolGroup.prototype.onMouseOut = function ( e ) {
-       var tool = this.getTargetTool( e );
-
-       if ( this.pressed && this.pressed === tool ) {
-               this.pressed.setActive( false );
-       }
-};
-
-/**
- * Get the closest tool to a jQuery.Event.
- *
- * Only tool links are considered, which prevents other elements in the tool such as popups from
- * triggering tool group interactions.
- *
- * @method
- * @private
- * @param {jQuery.Event} e
- * @returns {OO.ui.Tool|null} Tool, `null` if none was found
- */
-OO.ui.ToolGroup.prototype.getTargetTool = function ( e ) {
-       var tool,
-               $item = this.$( e.target ).closest( '.oo-ui-tool-link' );
-
-       if ( $item.length ) {
-               tool = $item.parent().data( 'oo-ui-tool' );
-       }
-
-       return tool && !tool.isDisabled() ? tool : null;
-};
-
-/**
- * Handle tool registry register events.
- *
- * If a tool is registered after the group is created, we must repopulate the list to account for:
- * - a tool being added that may be included
- * - a tool already included being overridden
- *
- * @param {string} name Symbolic name of tool
- */
-OO.ui.ToolGroup.prototype.onToolFactoryRegister = function () {
-       this.populate();
-};
-
-/**
- * Get the toolbar this group is in.
- *
- * @return {OO.ui.Toolbar} Toolbar of group
- */
-OO.ui.ToolGroup.prototype.getToolbar = function () {
-       return this.toolbar;
-};
-
-/**
- * Add and remove tools based on configuration.
- *
- * @method
- */
-OO.ui.ToolGroup.prototype.populate = function () {
-       var i, len, name, tool,
-               toolFactory = this.toolbar.getToolFactory(),
-               names = {},
-               add = [],
-               remove = [],
-               list = this.toolbar.getToolFactory().getTools(
-                       this.include, this.exclude, this.promote, this.demote
-               );
-
-       // Build a list of needed tools
-       for ( i = 0, len = list.length; i < len; i++ ) {
-               name = list[i];
-               if (
-                       // Tool exists
-                       toolFactory.lookup( name ) &&
-                       // Tool is available or is already in this group
-                       ( this.toolbar.isToolAvailable( name ) || this.tools[name] )
-               ) {
-                       tool = this.tools[name];
-                       if ( !tool ) {
-                               // Auto-initialize tools on first use
-                               this.tools[name] = tool = toolFactory.create( name, this );
-                               tool.updateTitle();
-                       }
-                       this.toolbar.reserveTool( tool );
-                       add.push( tool );
-                       names[name] = true;
-               }
-       }
-       // Remove tools that are no longer needed
-       for ( name in this.tools ) {
-               if ( !names[name] ) {
-                       this.tools[name].destroy();
-                       this.toolbar.releaseTool( this.tools[name] );
-                       remove.push( this.tools[name] );
-                       delete this.tools[name];
-               }
-       }
-       if ( remove.length ) {
-               this.removeItems( remove );
-       }
-       // Update emptiness state
-       if ( add.length ) {
-               this.$element.removeClass( 'oo-ui-toolGroup-empty' );
-       } else {
-               this.$element.addClass( 'oo-ui-toolGroup-empty' );
-       }
-       // Re-add tools (moving existing ones to new locations)
-       this.addItems( add );
-};
-
-/**
- * Destroy tool group.
- *
- * @method
- */
-OO.ui.ToolGroup.prototype.destroy = function () {
-       var name;
-
-       this.clearItems();
-       this.toolbar.getToolFactory().disconnect( this );
-       for ( name in this.tools ) {
-               this.toolbar.releaseTool( this.tools[name] );
-               this.tools[name].disconnect( this ).destroy();
-               delete this.tools[name];
-       }
-       this.$element.remove();
-};
-/**
- * Layout made of a fieldset and optional legend.
- *
- * @class
- * @extends OO.ui.Layout
- * @mixins OO.ui.LabeledElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [icon] Symbolic icon name
- */
-OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {
-       // Config initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Layout.call( this, config );
-
-       // Mixin constructors
-       OO.ui.LabeledElement.call( this, this.$( '<legend>' ), config );
-
-       // Initialization
-       if ( config.icon ) {
-               this.$element.addClass( 'oo-ui-fieldsetLayout-decorated' );
-               this.$label.addClass( 'oo-ui-icon-' + config.icon );
-       }
-       this.$element.addClass( 'oo-ui-fieldsetLayout' );
-       if ( config.icon || config.label ) {
-               this.$element
-                       .addClass( 'oo-ui-fieldsetLayout-labeled' )
-                       .append( this.$label );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.FieldsetLayout, OO.ui.Layout );
-
-OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.LabeledElement );
-
-/* Static Properties */
-
-OO.ui.FieldsetLayout.static.tagName = 'fieldset';
-/**
- * Layout made of proportionally sized columns and rows.
- *
- * @class
- * @extends OO.ui.Layout
- *
- * @constructor
- * @param {OO.ui.PanelLayout[]} panels Panels in the grid
- * @param {Object} [config] Configuration options
- * @cfg {number[]} [widths] Widths of columns as ratios
- * @cfg {number[]} [heights] Heights of columns as ratios
- */
-OO.ui.GridLayout = function OoUiGridLayout( panels, config ) {
-       var i, len, widths;
-
-       // Config initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Layout.call( this, config );
-
-       // Properties
-       this.panels = [];
-       this.widths = [];
-       this.heights = [];
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-gridLayout' );
-       for ( i = 0, len = panels.length; i < len; i++ ) {
-               this.panels.push( panels[i] );
-               this.$element.append( panels[i].$element );
-       }
-       if ( config.widths || config.heights ) {
-               this.layout( config.widths || [1], config.heights || [1] );
-       } else {
-               // Arrange in columns by default
-               widths = [];
-               for ( i = 0, len = this.panels.length; i < len; i++ ) {
-                       widths[i] = 1;
-               }
-               this.layout( widths, [1] );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.GridLayout, OO.ui.Layout );
-
-/* Events */
-
-/**
- * @event layout
- */
-
-/**
- * @event update
- */
-
-/* Static Properties */
-
-OO.ui.GridLayout.static.tagName = 'div';
-
-/* Methods */
-
-/**
- * Set grid dimensions.
- *
- * @method
- * @param {number[]} widths Widths of columns as ratios
- * @param {number[]} heights Heights of rows as ratios
- * @fires layout
- * @throws {Error} If grid is not large enough to fit all panels
- */
-OO.ui.GridLayout.prototype.layout = function ( widths, heights ) {
-       var x, y,
-               xd = 0,
-               yd = 0,
-               cols = widths.length,
-               rows = heights.length;
-
-       // Verify grid is big enough to fit panels
-       if ( cols * rows < this.panels.length ) {
-               throw new Error( 'Grid is not large enough to fit ' + this.panels.length + 'panels' );
-       }
-
-       // Sum up denominators
-       for ( x = 0; x < cols; x++ ) {
-               xd += widths[x];
-       }
-       for ( y = 0; y < rows; y++ ) {
-               yd += heights[y];
-       }
-       // Store factors
-       this.widths = [];
-       this.heights = [];
-       for ( x = 0; x < cols; x++ ) {
-               this.widths[x] = widths[x] / xd;
-       }
-       for ( y = 0; y < rows; y++ ) {
-               this.heights[y] = heights[y] / yd;
-       }
-       // Synchronize view
-       this.update();
-       this.emit( 'layout' );
-};
-
-/**
- * Update panel positions and sizes.
- *
- * @method
- * @fires update
- */
-OO.ui.GridLayout.prototype.update = function () {
-       var x, y, panel,
-               i = 0,
-               left = 0,
-               top = 0,
-               dimensions,
-               width = 0,
-               height = 0,
-               cols = this.widths.length,
-               rows = this.heights.length;
-
-       for ( y = 0; y < rows; y++ ) {
-               for ( x = 0; x < cols; x++ ) {
-                       panel = this.panels[i];
-                       width = this.widths[x];
-                       height = this.heights[y];
-                       dimensions = {
-                               'width': Math.round( width * 100 ) + '%',
-                               'height': Math.round( height * 100 ) + '%',
-                               'top': Math.round( top * 100 ) + '%'
-                       };
-                       // If RTL, reverse:
-                       if ( OO.ui.Element.getDir( this.$.context ) === 'rtl' ) {
-                               dimensions.right = Math.round( left * 100 ) + '%';
-                       } else {
-                               dimensions.left = Math.round( left * 100 ) + '%';
-                       }
-                       panel.$element.css( dimensions );
-                       i++;
-                       left += width;
-               }
-               top += height;
-               left = 0;
-       }
-
-       this.emit( 'update' );
-};
-
-/**
- * Get a panel at a given position.
- *
- * The x and y position is affected by the current grid layout.
- *
- * @method
- * @param {number} x Horizontal position
- * @param {number} y Vertical position
- * @returns {OO.ui.PanelLayout} The panel at the given postion
- */
-OO.ui.GridLayout.prototype.getPanel = function ( x, y ) {
-       return this.panels[( x * this.widths.length ) + y];
-};
-/**
- * Layout containing a series of pages.
- *
- * @class
- * @extends OO.ui.Layout
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [continuous=false] Show all pages, one after another
- * @cfg {boolean} [autoFocus=false] Focus on the first focusable element when changing to a page
- * @cfg {boolean} [outlined=false] Show an outline
- * @cfg {boolean} [editable=false] Show controls for adding, removing and reordering pages
- * @cfg {Object[]} [adders] List of adders for controls, each with name, icon and title properties
- */
-OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
-       // Initialize configuration
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Layout.call( this, config );
-
-       // Properties
-       this.currentPageName = null;
-       this.pages = {};
-       this.ignoreFocus = false;
-       this.stackLayout = new OO.ui.StackLayout( { '$': this.$, 'continuous': !!config.continuous } );
-       this.autoFocus = !!config.autoFocus;
-       this.outlined = !!config.outlined;
-       if ( this.outlined ) {
-               this.editable = !!config.editable;
-               this.adders = config.adders || null;
-               this.outlineControlsWidget = null;
-               this.outlineWidget = new OO.ui.OutlineWidget( { '$': this.$ } );
-               this.outlinePanel = new OO.ui.PanelLayout( { '$': this.$, 'scrollable': true } );
-               this.gridLayout = new OO.ui.GridLayout(
-                       [this.outlinePanel, this.stackLayout], { '$': this.$, 'widths': [1, 2] }
-               );
-               if ( this.editable ) {
-                       this.outlineControlsWidget = new OO.ui.OutlineControlsWidget(
-                               this.outlineWidget,
-                               { '$': this.$, 'adders': this.adders }
-                       );
-               }
-       }
-
-       // Events
-       this.stackLayout.connect( this, { 'set': 'onStackLayoutSet' } );
-       if ( this.outlined ) {
-               this.outlineWidget.connect( this, { 'select': 'onOutlineWidgetSelect' } );
-               // Event 'focus' does not bubble, but 'focusin' does
-               this.stackLayout.onDOMEvent( 'focusin', OO.ui.bind( this.onStackLayoutFocus, this ) );
-       }
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-bookletLayout' );
-       this.stackLayout.$element.addClass( 'oo-ui-bookletLayout-stackLayout' );
-       if ( this.outlined ) {
-               this.outlinePanel.$element
-                       .addClass( 'oo-ui-bookletLayout-outlinePanel' )
-                       .append( this.outlineWidget.$element );
-               if ( this.editable ) {
-                       this.outlinePanel.$element
-                               .addClass( 'oo-ui-bookletLayout-outlinePanel-editable' )
-                               .append( this.outlineControlsWidget.$element );
-               }
-               this.$element.append( this.gridLayout.$element );
-       } else {
-               this.$element.append( this.stackLayout.$element );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.BookletLayout, OO.ui.Layout );
-
-/* Events */
-
-/**
- * @event set
- * @param {OO.ui.PageLayout} page Current page
- */
-
-/**
- * @event add
- * @param {OO.ui.PageLayout[]} page Added pages
- * @param {number} index Index pages were added at
- */
-
-/**
- * @event remove
- * @param {OO.ui.PageLayout[]} pages Removed pages
- */
-
-/* Methods */
-
-/**
- * Handle stack layout focus.
- *
- * @method
- * @param {jQuery.Event} e Focusin event
- */
-OO.ui.BookletLayout.prototype.onStackLayoutFocus = function ( e ) {
-       var name, $target;
-
-       if ( this.ignoreFocus ) {
-               // Avoid recursion from programmatic focus trigger in #onStackLayoutSet
-               return;
-       }
-
-       $target = $( e.target ).closest( '.oo-ui-pageLayout' );
-       for ( name in this.pages ) {
-               if ( this.pages[ name ].$element[0] === $target[0] ) {
-                       this.setPage( name );
-                       break;
-               }
-       }
-};
-
-/**
- * Handle stack layout set events.
- *
- * @method
- * @param {OO.ui.PanelLayout|null} page The page panel that is now the current panel
- */
-OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {
-       if ( page ) {
-               page.scrollElementIntoView( { 'complete': OO.ui.bind( function () {
-                       this.ignoreFocus = true;
-                       if ( this.autoFocus ) {
-                               page.$element.find( ':input:first' ).focus();
-                       }
-                       this.ignoreFocus = false;
-               }, this ) } );
-       }
-};
-
-/**
- * Handle outline widget select events.
- *
- * @method
- * @param {OO.ui.OptionWidget|null} item Selected item
- */
-OO.ui.BookletLayout.prototype.onOutlineWidgetSelect = function ( item ) {
-       if ( item ) {
-               this.setPage( item.getData() );
-       }
-};
-
-/**
- * Check if booklet has an outline.
- *
- * @method
- * @returns {boolean} Booklet is outlined
- */
-OO.ui.BookletLayout.prototype.isOutlined = function () {
-       return this.outlined;
-};
-
-/**
- * Check if booklet has editing controls.
- *
- * @method
- * @returns {boolean} Booklet is outlined
- */
-OO.ui.BookletLayout.prototype.isEditable = function () {
-       return this.editable;
-};
-
-/**
- * Get the outline widget.
- *
- * @method
- * @returns {OO.ui.OutlineWidget|null} Outline widget, or null if boolet has no outline
- */
-OO.ui.BookletLayout.prototype.getOutline = function () {
-       return this.outlineWidget;
-};
-
-/**
- * Get the outline controls widget. If the outline is not editable, null is returned.
- *
- * @method
- * @returns {OO.ui.OutlineControlsWidget|null} The outline controls widget.
- */
-OO.ui.BookletLayout.prototype.getOutlineControls = function () {
-       return this.outlineControlsWidget;
-};
-
-/**
- * Get a page by name.
- *
- * @method
- * @param {string} name Symbolic name of page
- * @returns {OO.ui.PageLayout|undefined} Page, if found
- */
-OO.ui.BookletLayout.prototype.getPage = function ( name ) {
-       return this.pages[name];
-};
-
-/**
- * Get the current page name.
- *
- * @method
- * @returns {string|null} Current page name
- */
-OO.ui.BookletLayout.prototype.getPageName = function () {
-       return this.currentPageName;
-};
-
-/**
- * Add a page to the layout.
- *
- * When pages are added with the same names as existing pages, the existing pages will be
- * automatically removed before the new pages are added.
- *
- * @method
- * @param {OO.ui.PageLayout[]} pages Pages to add
- * @param {number} index Index to insert pages after
- * @fires add
- * @chainable
- */
-OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {
-       var i, len, name, page,
-               items = [],
-               remove = [];
-
-       for ( i = 0, len = pages.length; i < len; i++ ) {
-               page = pages[i];
-               name = page.getName();
-               if ( name in this.pages ) {
-                       // Remove page with same name
-                       remove.push( this.pages[name] );
-               }
-               this.pages[page.getName()] = page;
-               if ( this.outlined ) {
-                       items.push( new OO.ui.BookletOutlineItemWidget( name, page, { '$': this.$ } ) );
-               }
-       }
-       if ( remove.length ) {
-               this.removePages( remove );
-       }
-
-       if ( this.outlined && items.length ) {
-               this.outlineWidget.addItems( items, index );
-               this.updateOutlineWidget();
-       }
-       this.stackLayout.addItems( pages, index );
-       this.emit( 'add', pages, index );
-
-       return this;
-};
-
-/**
- * Remove a page from the layout.
- *
- * @method
- * @fires remove
- * @chainable
- */
-OO.ui.BookletLayout.prototype.removePages = function ( pages ) {
-       var i, len, name, page,
-               items = [];
-
-       for ( i = 0, len = pages.length; i < len; i++ ) {
-               page = pages[i];
-               name = page.getName();
-               delete this.pages[name];
-               if ( this.outlined ) {
-                       items.push( this.outlineWidget.getItemFromData( name ) );
-               }
-       }
-       if ( this.outlined && items.length ) {
-               this.outlineWidget.removeItems( items );
-               this.updateOutlineWidget();
-       }
-       this.stackLayout.removeItems( pages );
-       this.emit( 'remove', pages );
-
-       return this;
-};
-
-/**
- * Clear all pages from the layout.
- *
- * @method
- * @fires remove
- * @chainable
- */
-OO.ui.BookletLayout.prototype.clearPages = function () {
-       var pages = this.stackLayout.getItems();
-
-       this.pages = {};
-       this.currentPageName = null;
-       if ( this.outlined ) {
-               this.outlineWidget.clearItems();
-       }
-       this.stackLayout.clearItems();
-
-       this.emit( 'remove', pages );
-
-       return this;
-};
-
-/**
- * Set the current page by name.
- *
- * @method
- * @fires set
- * @param {string} name Symbolic name of page
- */
-OO.ui.BookletLayout.prototype.setPage = function ( name ) {
-       var selectedItem,
-               page = this.pages[name];
-
-       if ( this.outlined ) {
-               selectedItem = this.outlineWidget.getSelectedItem();
-               if ( selectedItem && selectedItem.getData() !== name ) {
-                       this.outlineWidget.selectItem( this.outlineWidget.getItemFromData( name ) );
-               }
-       }
-
-       if ( page ) {
-               this.currentPageName = name;
-               this.stackLayout.setItem( page );
-               this.emit( 'set', page );
-       }
-};
-
-/**
- * Call this after adding or removing items from the OutlineWidget.
- *
- * @method
- * @chainable
- */
-OO.ui.BookletLayout.prototype.updateOutlineWidget = function () {
-       // Auto-select first item when nothing is selected anymore
-       if ( !this.outlineWidget.getSelectedItem() ) {
-               this.outlineWidget.selectItem( this.outlineWidget.getFirstSelectableItem() );
-       }
-
-       return this;
-};
-/**
- * Layout that expands to cover the entire area of its parent, with optional scrolling and padding.
- *
- * @class
- * @extends OO.ui.Layout
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [scrollable] Allow vertical scrolling
- * @cfg {boolean} [padded] Pad the content from the edges
- */
-OO.ui.PanelLayout = function OoUiPanelLayout( config ) {
-       // Config initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Layout.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-panelLayout' );
-       if ( config.scrollable ) {
-               this.$element.addClass( 'oo-ui-panelLayout-scrollable' );
-       }
-
-       if ( config.padded ) {
-               this.$element.addClass( 'oo-ui-panelLayout-padded' );
-       }
-
-       // Add directionality class:
-       this.$element.addClass( 'oo-ui-' + OO.ui.Element.getDir( this.$.context ) );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PanelLayout, OO.ui.Layout );
-/**
- * Page within an OO.ui.BookletLayout.
- *
- * @class
- * @extends OO.ui.PanelLayout
- *
- * @constructor
- * @param {string} name Unique symbolic name of page
- * @param {Object} [config] Configuration options
- * @param {string} [icon=''] Symbolic name of icon to display in outline
- * @param {string} [indicator=''] Symbolic name of indicator to display in outline
- * @param {string} [indicatorTitle=''] Description of indicator meaning to display in outline
- * @param {string} [label=''] Label to display in outline
- * @param {number} [level=0] Indentation level of item in outline
- * @param {boolean} [movable=false] Page should be movable using outline controls
- */
-OO.ui.PageLayout = function OoUiPageLayout( name, config ) {
-       // Configuration initialization
-       config = $.extend( { 'scrollable': true }, config );
-
-       // Parent constructor
-       OO.ui.PanelLayout.call( this, config );
-
-       // Properties
-       this.name = name;
-       this.icon = config.icon || '';
-       this.indicator = config.indicator || '';
-       this.indicatorTitle = OO.ui.resolveMsg( config.indicatorTitle ) || '';
-       this.label = OO.ui.resolveMsg( config.label ) || '';
-       this.level = config.level || 0;
-       this.movable = !!config.movable;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-pageLayout' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PageLayout, OO.ui.PanelLayout );
-
-/* Methods */
-
-/**
- * Get page name.
- *
- * @returns {string} Symbolic name of page
- */
-OO.ui.PageLayout.prototype.getName = function () {
-       return this.name;
-};
-
-/**
- * Get page icon.
- *
- * @returns {string} Symbolic name of icon
- */
-OO.ui.PageLayout.prototype.getIcon = function () {
-       return this.icon;
-};
-
-/**
- * Get page indicator.
- *
- * @returns {string} Symbolic name of indicator
- */
-OO.ui.PageLayout.prototype.getIndicator = function () {
-       return this.indicator;
-};
-
-/**
- * Get page indicator label.
- *
- * @returns {string} Description of indicator meaning
- */
-OO.ui.PageLayout.prototype.getIndicatorTitle = function () {
-       return this.indicatorTitle;
-};
-
-/**
- * Get page label.
- *
- * @returns {string} Label text
- */
-OO.ui.PageLayout.prototype.getLabel = function () {
-       return this.label;
-};
-
-/**
- * Get outline item indentation level.
- *
- * @returns {number} Indentation level
- */
-OO.ui.PageLayout.prototype.getLevel = function () {
-       return this.level;
-};
-
-/**
- * Check if page is movable using outline controls.
- *
- * @returns {boolean} Page is movable
- */
-OO.ui.PageLayout.prototype.isMovable = function () {
-       return this.movable;
-};
-/**
- * Layout containing a series of mutually exclusive pages.
- *
- * @class
- * @extends OO.ui.PanelLayout
- * @mixins OO.ui.GroupElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [continuous=false] Show all pages, one after another
- * @cfg {string} [icon=''] Symbolic icon name
- */
-OO.ui.StackLayout = function OoUiStackLayout( config ) {
-       // Config initialization
-       config = $.extend( { 'scrollable': true }, config );
-
-       // Parent constructor
-       OO.ui.PanelLayout.call( this, config );
-
-       // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$element, config );
-
-       // Properties
-       this.currentItem = null;
-       this.continuous = !!config.continuous;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-stackLayout' );
-       if ( this.continuous ) {
-               this.$element.addClass( 'oo-ui-stackLayout-continuous' );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.StackLayout, OO.ui.PanelLayout );
-
-OO.mixinClass( OO.ui.StackLayout, OO.ui.GroupElement );
-
-/* Events */
-
-/**
- * @event set
- * @param {OO.ui.PanelLayout|null} [item] Current item
- */
-
-/* Methods */
-
-/**
- * Add items.
- *
- * Adding an existing item (by value) will move it.
- *
- * @method
- * @param {OO.ui.PanelLayout[]} items Items to add
- * @param {number} [index] Index to insert items after
- * @chainable
- */
-OO.ui.StackLayout.prototype.addItems = function ( items, index ) {
-       OO.ui.GroupElement.prototype.addItems.call( this, items, index );
-
-       if ( !this.currentItem && items.length ) {
-               this.setItem( items[0] );
-       }
-
-       return this;
-};
-
-/**
- * Remove items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @param {OO.ui.PanelLayout[]} items Items to remove
- * @chainable
- */
-OO.ui.StackLayout.prototype.removeItems = function ( items ) {
-       OO.ui.GroupElement.prototype.removeItems.call( this, items );
-       if ( items.indexOf( this.currentItem ) !== -1 ) {
-               this.currentItem = null;
-               if ( !this.currentItem && this.items.length ) {
-                       this.setItem( this.items[0] );
-               }
-       }
-
-       return this;
-};
-
-/**
- * Clear all items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @chainable
- */
-OO.ui.StackLayout.prototype.clearItems = function () {
-       this.currentItem = null;
-       OO.ui.GroupElement.prototype.clearItems.call( this );
-
-       return this;
-};
-
-/**
- * Show item.
- *
- * Any currently shown item will be hidden.
- *
- * @method
- * @param {OO.ui.PanelLayout} item Item to show
- * @chainable
- */
-OO.ui.StackLayout.prototype.setItem = function ( item ) {
-       if ( !this.continuous ) {
-               this.$items.css( 'display', '' );
-       }
-       if ( this.items.indexOf( item ) !== -1 ) {
-               if ( !this.continuous ) {
-                       item.$element.css( 'display', 'block' );
-               }
-       } else {
-               item = null;
-       }
-       this.currentItem = item;
-       this.emit( 'set', item );
-
-       return this;
-};
-/**
- * Horizontal bar layout of tools as icon buttons.
- *
- * @class
- * @abstract
- * @extends OO.ui.ToolGroup
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- */
-OO.ui.BarToolGroup = function OoUiBarToolGroup( toolbar, config ) {
-       // Parent constructor
-       OO.ui.ToolGroup.call( this, toolbar, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-barToolGroup' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.BarToolGroup, OO.ui.ToolGroup );
-
-/* Static Properties */
-
-OO.ui.BarToolGroup.static.titleTooltips = true;
-
-OO.ui.BarToolGroup.static.accelTooltips = true;
-/**
- * Popup list of tools with an icon and optional label.
- *
- * @class
- * @abstract
- * @extends OO.ui.ToolGroup
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.TitledElement
- * @mixins OO.ui.ClippableElement
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- */
-OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.ToolGroup.call( this, toolbar, config );
-
-       // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.TitledElement.call( this, this.$element, config );
-       OO.ui.ClippableElement.call( this, this.$group );
-
-       // Properties
-       this.active = false;
-       this.dragging = false;
-       this.onBlurHandler = OO.ui.bind( this.onBlur, this );
-       this.$handle = this.$( '<span>' );
-
-       // Events
-       this.$handle.on( {
-               'mousedown': OO.ui.bind( this.onHandleMouseDown, this ),
-               'mouseup': OO.ui.bind( this.onHandleMouseUp, this )
-       } );
-
-       // Initialization
-       this.$handle
-               .addClass( 'oo-ui-popupToolGroup-handle' )
-               .append( this.$icon, this.$label, this.$indicator );
-       this.$element
-               .addClass( 'oo-ui-popupToolGroup' )
-               .prepend( this.$handle );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PopupToolGroup, OO.ui.ToolGroup );
-
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.TitledElement );
-OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.ClippableElement );
-
-/* Static Properties */
-
-/* Methods */
-
-/**
- * Handle focus being lost.
- *
- * The event is actually generated from a mouseup, so it is not a normal blur event object.
- *
- * @method
- * @param {jQuery.Event} e Mouse up event
- */
-OO.ui.PopupToolGroup.prototype.onBlur = function ( e ) {
-       // Only deactivate when clicking outside the dropdown element
-       if ( this.$( e.target ).closest( '.oo-ui-popupToolGroup' )[0] !== this.$element[0] ) {
-               this.setActive( false );
-       }
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.PopupToolGroup.prototype.onMouseUp = function ( e ) {
-       this.setActive( false );
-       return OO.ui.ToolGroup.prototype.onMouseUp.call( this, e );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.PopupToolGroup.prototype.onMouseDown = function ( e ) {
-       return OO.ui.ToolGroup.prototype.onMouseDown.call( this, e );
-};
-
-/**
- * Handle mouse up events.
- *
- * @method
- * @param {jQuery.Event} e Mouse up event
- */
-OO.ui.PopupToolGroup.prototype.onHandleMouseUp = function () {
-       return false;
-};
-
-/**
- * Handle mouse down events.
- *
- * @method
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.PopupToolGroup.prototype.onHandleMouseDown = function ( e ) {
-       if ( !this.disabled && e.which === 1 ) {
-               this.setActive( !this.active );
-       }
-       return false;
-};
-
-/**
- * Switch into active mode.
- *
- * When active, mouseup events anywhere in the document will trigger deactivation.
- *
- * @method
- */
-OO.ui.PopupToolGroup.prototype.setActive = function ( value ) {
-       value = !!value;
-       if ( this.active !== value ) {
-               this.active = value;
-               if ( value ) {
-                       this.setClipping( true );
-                       this.$element.addClass( 'oo-ui-popupToolGroup-active' );
-                       this.getElementDocument().addEventListener( 'mouseup', this.onBlurHandler, true );
-               } else {
-                       this.setClipping( false );
-                       this.$element.removeClass( 'oo-ui-popupToolGroup-active' );
-                       this.getElementDocument().removeEventListener( 'mouseup', this.onBlurHandler, true );
-               }
-       }
-};
-/**
- * Drop down list layout of tools as labeled icon buttons.
- *
- * @class
- * @abstract
- * @extends OO.ui.PopupToolGroup
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- */
-OO.ui.ListToolGroup = function OoUiListToolGroup( toolbar, config ) {
-       // Parent constructor
-       OO.ui.PopupToolGroup.call( this, toolbar, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-listToolGroup' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ListToolGroup, OO.ui.PopupToolGroup );
-
-/* Static Properties */
-
-OO.ui.ListToolGroup.static.accelTooltips = true;
-/**
- * Drop down menu layout of tools as selectable menu items.
- *
- * @class
- * @abstract
- * @extends OO.ui.PopupToolGroup
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- */
-OO.ui.MenuToolGroup = function OoUiMenuToolGroup( toolbar, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.PopupToolGroup.call( this, toolbar, config );
-
-       // Events
-       this.toolbar.connect( this, { 'updateState': 'onUpdateState' } );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-menuToolGroup' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.MenuToolGroup, OO.ui.PopupToolGroup );
-
-/* Static Properties */
-
-OO.ui.MenuToolGroup.static.accelTooltips = true;
-
-/* Methods */
-
-/**
- * Handle the toolbar state being updated.
- *
- * When the state changes, the title of each active item in the menu will be joined together and
- * used as a label for the group. The label will be empty if none of the items are active.
- *
- * @method
- */
-OO.ui.MenuToolGroup.prototype.onUpdateState = function () {
-       var name,
-               labelTexts = [];
-
-       for ( name in this.tools ) {
-               if ( this.tools[name].isActive() ) {
-                       labelTexts.push( this.tools[name].getTitle() );
-               }
-       }
-
-       this.setLabel( labelTexts.join( ', ' ) );
-};
-/**
- * UserInterface popup tool.
- *
- * @abstract
- * @class
- * @extends OO.ui.Tool
- * @mixins OO.ui.PopuppableElement
- *
- * @constructor
- * @param {OO.ui.Toolbar} toolbar
- * @param {Object} [config] Configuration options
- */
-OO.ui.PopupTool = function OoUiPopupTool( toolbar, config ) {
-       // Parent constructor
-       OO.ui.Tool.call( this, toolbar, config );
-
-       // Mixin constructors
-       OO.ui.PopuppableElement.call( this, config );
-
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-popupTool' )
-               .append( this.popup.$element );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PopupTool, OO.ui.Tool );
-
-OO.mixinClass( OO.ui.PopupTool, OO.ui.PopuppableElement );
-
-/* Methods */
-
-/**
- * Handle the tool being selected.
- *
- * @inheritdoc
- */
-OO.ui.PopupTool.prototype.onSelect = function () {
-       if ( !this.disabled ) {
-               if ( this.popup.isVisible() ) {
-                       this.hidePopup();
-               } else {
-                       this.showPopup();
-               }
-       }
-       this.setActive( false );
-       return false;
-};
-
-/**
- * Handle the toolbar state being updated.
- *
- * @inheritdoc
- */
-OO.ui.PopupTool.prototype.onUpdateState = function () {
-       this.setActive( false );
-};
-/**
- * Container for multiple related buttons.
- *
- * @class
- * @extends OO.ui.Widget
- * @mixin OO.ui.GroupElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.ButtonGroupWidget = function OoUiButtonGroupWidget( config ) {
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$element, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-buttonGroupWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ButtonGroupWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.ButtonGroupWidget, OO.ui.GroupElement );
-/**
- * Creates an OO.ui.ButtonWidget object.
- *
- * @class
- * @abstract
- * @extends OO.ui.Widget
- * @mixins OO.ui.ButtonedElement
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.IndicatedElement
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.TitledElement
- * @mixins OO.ui.FlaggableElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [title=''] Title text
- * @cfg {string} [href] Hyperlink to visit when clicked
- * @cfg {string} [target] Target to open hyperlink in
- */
-OO.ui.ButtonWidget = function OoUiButtonWidget( config ) {
-       // Configuration initialization
-       config = $.extend( { 'target': '_blank' }, config );
-
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.ButtonedElement.call( this, this.$( '<a>' ), config );
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.TitledElement.call( this, this.$button, config );
-       OO.ui.FlaggableElement.call( this, config );
-
-       // Properties
-       this.isHyperlink = typeof config.href === 'string';
-
-       // Events
-       this.$button.on( {
-               'click': OO.ui.bind( this.onClick, this ),
-               'keypress': OO.ui.bind( this.onKeyPress, this )
-       } );
-
-       // Initialization
-       this.$button
-               .append( this.$icon, this.$label, this.$indicator )
-               .attr( { 'href': config.href, 'target': config.target } );
-       this.$element
-               .addClass( 'oo-ui-buttonWidget' )
-               .append( this.$button );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ButtonWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.ButtonedElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.IndicatedElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.TitledElement );
-OO.mixinClass( OO.ui.ButtonWidget, OO.ui.FlaggableElement );
-
-/* Events */
-
-/**
- * @event click
- */
-
-/* Methods */
-
-/**
- * Handles mouse click events.
- *
- * @method
- * @param {jQuery.Event} e Mouse click event
- * @fires click
- */
-OO.ui.ButtonWidget.prototype.onClick = function () {
-       if ( !this.disabled ) {
-               this.emit( 'click' );
-               if ( this.isHyperlink ) {
-                       return true;
-               }
-       }
-       return false;
-};
-
-/**
- * Handles keypress events.
- *
- * @method
- * @param {jQuery.Event} e Keypress event
- * @fires click
- */
-OO.ui.ButtonWidget.prototype.onKeyPress = function ( e ) {
-       if ( !this.disabled && e.which === OO.ui.Keys.SPACE ) {
-               if ( this.isHyperlink ) {
-                       this.onClick();
-                       return true;
-               }
-       }
-       return false;
-};
-/**
- * Creates an OO.ui.InputWidget object.
- *
- * @class
- * @abstract
- * @extends OO.ui.Widget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [name=''] HTML input name
- * @cfg {string} [value=''] Input value
- * @cfg {boolean} [readOnly=false] Prevent changes
- * @cfg {Function} [inputFilter] Filter function to apply to the input. Takes a string argument and returns a string.
- */
-OO.ui.InputWidget = function OoUiInputWidget( config ) {
-       // Config intialization
-       config = $.extend( { 'readOnly': false }, config );
-
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Properties
-       this.$input = this.getInputElement( config );
-       this.value = '';
-       this.readOnly = false;
-       this.inputFilter = config.inputFilter;
-
-       // Events
-       this.$input.on( 'keydown mouseup cut paste change input select', OO.ui.bind( this.onEdit, this ) );
-
-       // Initialization
-       this.$input
-               .attr( 'name', config.name )
-               .prop( 'disabled', this.disabled );
-       this.setReadOnly( config.readOnly );
-       this.$element.addClass( 'oo-ui-inputWidget' ).append( this.$input );
-       this.setValue( config.value );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.InputWidget, OO.ui.Widget );
-
-/* Events */
-
-/**
- * @event change
- * @param value
- */
-
-/* Methods */
-
-/**
- * Get input element.
- *
- * @method
- * @param {Object} [config] Configuration options
- * @returns {jQuery} Input element
- */
-OO.ui.InputWidget.prototype.getInputElement = function () {
-       return this.$( '<input>' );
-};
-
-/**
- * Handle potentially value-changing events.
- *
- * @method
- * @param {jQuery.Event} e Key down, mouse up, cut, paste, change, input, or select event
- */
-OO.ui.InputWidget.prototype.onEdit = function () {
-       if ( !this.disabled ) {
-               // Allow the stack to clear so the value will be updated
-               setTimeout( OO.ui.bind( function () {
-                       this.setValue( this.$input.val() );
-               }, this ) );
-       }
-};
-
-/**
- * Get the value of the input.
- *
- * @method
- * @returns {string} Input value
- */
-OO.ui.InputWidget.prototype.getValue = function () {
-       return this.value;
-};
-
-/**
- * Sets the direction of the current input, either RTL or LTR
- *
- * @method
- * @param {boolean} isRTL
- */
-OO.ui.InputWidget.prototype.setRTL = function ( isRTL ) {
-       if ( isRTL ) {
-               this.$input.removeClass( 'oo-ui-ltr' );
-               this.$input.addClass( 'oo-ui-rtl' );
-       } else {
-               this.$input.removeClass( 'oo-ui-rtl' );
-               this.$input.addClass( 'oo-ui-ltr' );
-       }
-};
-
-/**
- * Set the value of the input.
- *
- * @method
- * @param {string} value New value
- * @fires change
- * @chainable
- */
-OO.ui.InputWidget.prototype.setValue = function ( value ) {
-       value = this.sanitizeValue( value );
-       if ( this.value !== value ) {
-               this.value = value;
-               this.emit( 'change', this.value );
-       }
-       // Update the DOM if it has changed. Note that with sanitizeValue, it
-       // is possible for the DOM value to change without this.value changing.
-       if ( this.$input.val() !== this.value ) {
-               this.$input.val( this.value );
-       }
-       return this;
-};
-
-/**
- * Sanitize incoming value.
- *
- * Ensures value is a string, and converts undefined and null to empty strings.
- *
- * @method
- * @param {string} value Original value
- * @returns {string} Sanitized value
- */
-OO.ui.InputWidget.prototype.sanitizeValue = function ( value ) {
-       if ( value === undefined || value === null ) {
-               return '';
-       } else if ( this.inputFilter ) {
-               return this.inputFilter( String( value ) );
-       } else {
-               return String( value );
-       }
-};
-
-/**
- * Check if the widget is read-only.
- *
- * @method
- * @param {boolean} Input is read-only
- */
-OO.ui.InputWidget.prototype.isReadOnly = function () {
-       return this.readOnly;
-};
-
-/**
- * Set the read-only state of the widget.
- *
- * This should probably change the widgets's appearance and prevent it from being used.
- *
- * @method
- * @param {boolean} state Make input read-only
- * @chainable
- */
-OO.ui.InputWidget.prototype.setReadOnly = function ( state ) {
-       this.readOnly = !!state;
-       this.$input.prop( 'readonly', this.readOnly );
-       return this;
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.InputWidget.prototype.setDisabled = function ( state ) {
-       OO.ui.Widget.prototype.setDisabled.call( this, state );
-       if ( this.$input ) {
-               this.$input.prop( 'disabled', this.disabled );
-       }
-       return this;
-};/**
- * Creates an OO.ui.CheckboxInputWidget object.
- *
- * @class
- * @extends OO.ui.InputWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.CheckboxInputWidget = function OoUiCheckboxInputWidget( config ) {
-       // Parent constructor
-       OO.ui.InputWidget.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-checkboxInputWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.CheckboxInputWidget, OO.ui.InputWidget );
-
-/* Events */
-
-/* Methods */
-
-/**
- * Get input element.
- *
- * @returns {jQuery} Input element
- */
-OO.ui.CheckboxInputWidget.prototype.getInputElement = function () {
-       return this.$( '<input type="checkbox" />' );
-};
-
-/**
- * Get checked state of the checkbox
- *
- * @returns {boolean} If the checkbox is checked
- */
-OO.ui.CheckboxInputWidget.prototype.getValue = function () {
-       return this.value;
-};
-
-/**
- * Set value
- */
-OO.ui.CheckboxInputWidget.prototype.setValue = function ( value ) {
-       value = !!value;
-       if ( this.value !== value ) {
-               this.value = value;
-               this.$input.prop( 'checked', this.value );
-               this.emit( 'change', this.value );
-       }
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.CheckboxInputWidget.prototype.onEdit = function () {
-       if ( !this.disabled ) {
-               // Allow the stack to clear so the value will be updated
-               setTimeout( OO.ui.bind( function () {
-                       this.setValue( this.$input.prop( 'checked' ) );
-               }, this ) );
-       }
-};
-/**
- * Creates an OO.ui.CheckboxWidget object.
- *
- * @class
- * @extends OO.ui.CheckboxInputWidget
- * @mixins OO.ui.LabeledElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [label=''] Label
- */
-OO.ui.CheckboxWidget = function OoUiCheckboxWidget( config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.CheckboxInputWidget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ) , config );
-
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-checkboxWidget' )
-               .append( this.$( '<label>' ).append( this.$input, this.$label ) );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.CheckboxWidget, OO.ui.CheckboxInputWidget );
-
-OO.mixinClass( OO.ui.CheckboxWidget, OO.ui.LabeledElement );
-/**
- * Creates an OO.ui.InputLabelWidget object.
- *
- * CSS classes will be added to the button for each flag, each prefixed with 'oo-ui-InputLabelWidget-'
- *
- * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.LabeledElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {OO.ui.InputWidget|null} [input] Related input widget
- */
-OO.ui.InputLabelWidget = function OoUiInputLabelWidget( config ) {
-       // Config intialization
-       config = $.extend( { 'input': null }, config );
-
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.LabeledElement.call( this, this.$element, config );
-
-       // Properties
-       this.input = config.input;
-
-       // Events
-       this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-inputLabelWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.InputLabelWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.InputLabelWidget, OO.ui.LabeledElement );
-
-/* Static Properties */
-
-OO.ui.InputLabelWidget.static.tagName = 'label';
-
-/* Methods */
-
-/**
- * Handles mouse click events.
- *
- * @method
- * @param {jQuery.Event} e Mouse click event
- */
-OO.ui.InputLabelWidget.prototype.onClick = function () {
-       if ( !this.disabled && this.input ) {
-               this.input.$input.focus();
-       }
-       return false;
-};
-/**
- * Lookup input widget.
- *
- * Mixin that adds a menu showing suggested values to a text input. Subclasses must handle `select`
- * events on #lookupMenu to make use of selections.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {OO.ui.TextInputWidget} input Input widget
- * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$overlay=this.$( 'body' )] Overlay layer
- */
-OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Properties
-       this.lookupInput = input;
-       this.$overlay = config.$overlay || this.$( 'body,.oo-ui-window-overlay' ).last();
-       this.lookupMenu = new OO.ui.TextInputMenuWidget( this, {
-               '$': OO.ui.Element.getJQuery( this.$overlay ),
-               'input': this.lookupInput,
-               '$container': config.$container
-       } );
-       this.lookupCache = {};
-       this.lookupQuery = null;
-       this.lookupRequest = null;
-       this.populating = false;
-
-       // Events
-       this.$overlay.append( this.lookupMenu.$element );
-
-       this.lookupInput.$input.on( {
-               'focus': OO.ui.bind( this.onLookupInputFocus, this ),
-               'blur': OO.ui.bind( this.onLookupInputBlur, this ),
-               'mousedown': OO.ui.bind( this.onLookupInputMouseDown, this )
-       } );
-       this.lookupInput.connect( this, { 'change': 'onLookupInputChange' } );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-lookupWidget' );
-       this.lookupMenu.$element.addClass( 'oo-ui-lookupWidget-menu' );
-};
-
-/* Methods */
-
-/**
- * Handle input focus event.
- *
- * @method
- * @param {jQuery.Event} e Input focus event
- */
-OO.ui.LookupInputWidget.prototype.onLookupInputFocus = function () {
-       this.openLookupMenu();
-};
-
-/**
- * Handle input blur event.
- *
- * @method
- * @param {jQuery.Event} e Input blur event
- */
-OO.ui.LookupInputWidget.prototype.onLookupInputBlur = function () {
-       this.lookupMenu.hide();
-};
-
-/**
- * Handle input mouse down event.
- *
- * @method
- * @param {jQuery.Event} e Input mouse down event
- */
-OO.ui.LookupInputWidget.prototype.onLookupInputMouseDown = function () {
-       this.openLookupMenu();
-};
-
-/**
- * Handle input change event.
- *
- * @method
- * @param {string} value New input value
- */
-OO.ui.LookupInputWidget.prototype.onLookupInputChange = function () {
-       this.openLookupMenu();
-};
-
-/**
- * Open the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.LookupInputWidget.prototype.openLookupMenu = function () {
-       var value = this.lookupInput.getValue();
-
-       if ( this.lookupMenu.$input.is( ':focus' ) && $.trim( value ) !== '' ) {
-               this.populateLookupMenu();
-               if ( !this.lookupMenu.isVisible() ) {
-                       this.lookupMenu.show();
-               }
-       } else {
-               this.lookupMenu.clearItems();
-               this.lookupMenu.hide();
-       }
-
-       return this;
-};
-
-/**
- * Populate lookup menu with current information.
- *
- * @method
- * @chainable
- */
-OO.ui.LookupInputWidget.prototype.populateLookupMenu = function () {
-       if ( !this.populating ) {
-               this.populating = true;
-               this.getLookupMenuItems()
-                       .done( OO.ui.bind( function ( items ) {
-                               this.lookupMenu.clearItems();
-                               if ( items.length ) {
-                                       this.lookupMenu.show();
-                                       this.lookupMenu.addItems( items );
-                                       this.initializeLookupMenuSelection();
-                                       this.openLookupMenu();
-                               } else {
-                                       this.lookupMenu.hide();
-                               }
-                               this.populating = false;
-                       }, this ) )
-                       .fail( OO.ui.bind( function () {
-                               this.lookupMenu.clearItems();
-                               this.populating = false;
-                       }, this ) );
-       }
-
-       return this;
-};
-
-/**
- * Set selection in the lookup menu with current information.
- *
- * @method
- * @chainable
- */
-OO.ui.LookupInputWidget.prototype.initializeLookupMenuSelection = function () {
-       if ( !this.lookupMenu.getSelectedItem() ) {
-               this.lookupMenu.intializeSelection( this.lookupMenu.getFirstSelectableItem() );
-       }
-       this.lookupMenu.highlightItem( this.lookupMenu.getSelectedItem() );
-};
-
-/**
- * Get lookup menu items for the current query.
- *
- * @method
- * @returns {jQuery.Promise} Promise object which will be passed menu items as the first argument
- * of the done event
- */
-OO.ui.LookupInputWidget.prototype.getLookupMenuItems = function () {
-       var value = this.lookupInput.getValue(),
-               deferred = $.Deferred();
-
-       if ( value && value !== this.lookupQuery ) {
-               // Abort current request if query has changed
-               if ( this.lookupRequest ) {
-                       this.lookupRequest.abort();
-                       this.lookupQuery = null;
-                       this.lookupRequest = null;
-               }
-               if ( value in this.lookupCache ) {
-                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
-               } else {
-                       this.lookupQuery = value;
-                       this.lookupRequest = this.getLookupRequest()
-                               .always( OO.ui.bind( function () {
-                                       this.lookupQuery = null;
-                                       this.lookupRequest = null;
-                               }, this ) )
-                               .done( OO.ui.bind( function ( data ) {
-                                       this.lookupCache[value] = this.getLookupCacheItemFromData( data );
-                                       deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) );
-                               }, this ) )
-                               .fail( function () {
-                                       deferred.reject();
-                               } );
-                       this.pushPending();
-                       this.lookupRequest.always( OO.ui.bind( function () {
-                               this.popPending();
-                       }, this ) );
-               }
-       }
-       return deferred.promise();
-};
-
-/**
- * Get a new request object of the current lookup query value.
- *
- * @method
- * @abstract
- * @returns {jqXHR} jQuery AJAX object, or promise object with an .abort() method
- */
-OO.ui.LookupInputWidget.prototype.getLookupRequest = function () {
-       // Stub, implemented in subclass
-       return null;
-};
-
-/**
- * Handle successful lookup request.
- *
- * Overriding methods should call #populateLookupMenu when results are available and cache results
- * for future lookups in #lookupCache as an array of #OO.ui.MenuItemWidget objects.
- *
- * @method
- * @abstract
- * @param {Mixed} data Response from server
- */
-OO.ui.LookupInputWidget.prototype.onLookupRequestDone = function () {
-       // Stub, implemented in subclass
-};
-
-/**
- * Get a list of menu item widgets from the data stored by the lookup request's done handler.
- *
- * @method
- * @abstract
- * @param {Mixed} data Cached result data, usually an array
- * @returns {OO.ui.MenuItemWidget[]} Menu items
- */
-OO.ui.LookupInputWidget.prototype.getLookupMenuItemsFromData = function () {
-       // Stub, implemented in subclass
-       return [];
-};
-/**
- * Creates an OO.ui.OptionWidget object.
- *
- * @class
- * @abstract
- * @extends OO.ui.Widget
- * @mixins OO.ui.IconedElement
- * @mixins OO.ui.LabeledElement
- * @mixins OO.ui.IndicatedElement
- *
- * @constructor
- * @param {Mixed} data Option data
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [selected=false] Select option
- * @cfg {boolean} [highlighted=false] Highlight option
- * @cfg {string} [rel] Value for `rel` attribute in DOM, allowing per-option styling
- */
-OO.ui.OptionWidget = function OoUiOptionWidget( data, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.IconedElement.call( this, this.$( '<span>' ), config );
-       OO.ui.LabeledElement.call( this, this.$( '<span>' ), config );
-       OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config );
-
-       // Properties
-       this.data = data;
-       this.selected = false;
-       this.highlighted = false;
-
-       // Initialization
-       this.$element
-               .data( 'oo-ui-optionWidget', this )
-               .attr( 'rel', config.rel )
-               .addClass( 'oo-ui-optionWidget' )
-               .append( this.$label );
-       this.setSelected( config.selected );
-       this.setHighlighted( config.highlighted );
-
-       // Options
-       this.$element
-               .prepend( this.$icon )
-               .append( this.$indicator );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.OptionWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.IconedElement );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.LabeledElement );
-OO.mixinClass( OO.ui.OptionWidget, OO.ui.IndicatedElement );
-
-/* Static Properties */
-
-OO.ui.OptionWidget.static.tagName = 'li';
-
-OO.ui.OptionWidget.static.selectable = true;
-
-OO.ui.OptionWidget.static.highlightable = true;
-
-OO.ui.OptionWidget.static.scrollIntoViewOnSelect = false;
-
-/* Methods */
-
-/**
- * Check if option can be selected.
- *
- * @method
- * @returns {boolean} Item is selectable
- */
-OO.ui.OptionWidget.prototype.isSelectable = function () {
-       return this.constructor.static.selectable && !this.disabled;
-};
-
-/**
- * Check if option can be highlighted.
- *
- * @method
- * @returns {boolean} Item is highlightable
- */
-OO.ui.OptionWidget.prototype.isHighlightable = function () {
-       return this.constructor.static.highlightable && !this.disabled;
-};
-
-/**
- * Check if option is selected.
- *
- * @method
- * @returns {boolean} Item is selected
- */
-OO.ui.OptionWidget.prototype.isSelected = function () {
-       return this.selected;
-};
-
-/**
- * Check if option is highlighted.
- *
- * @method
- * @returns {boolean} Item is highlighted
- */
-OO.ui.OptionWidget.prototype.isHighlighted = function () {
-       return this.highlighted;
-};
-
-/**
- * Set selected state.
- *
- * @method
- * @param {boolean} [state=false] Select option
- * @chainable
- */
-OO.ui.OptionWidget.prototype.setSelected = function ( state ) {
-       if ( !this.disabled && this.constructor.static.selectable ) {
-               this.selected = !!state;
-               if ( this.selected ) {
-                       this.$element.addClass( 'oo-ui-optionWidget-selected' );
-                       if ( this.constructor.static.scrollIntoViewOnSelect ) {
-                               this.scrollElementIntoView();
-                       }
-               } else {
-                       this.$element.removeClass( 'oo-ui-optionWidget-selected' );
-               }
-       }
-       return this;
-};
-
-/**
- * Set highlighted state.
- *
- * @method
- * @param {boolean} [state=false] Highlight option
- * @chainable
- */
-OO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {
-       if ( !this.disabled && this.constructor.static.highlightable ) {
-               this.highlighted = !!state;
-               if ( this.highlighted ) {
-                       this.$element.addClass( 'oo-ui-optionWidget-highlighted' );
-               } else {
-                       this.$element.removeClass( 'oo-ui-optionWidget-highlighted' );
-               }
-       }
-       return this;
-};
-
-/**
- * Make the option's highlight flash.
- *
- * @method
- * @param {Function} [done] Callback to execute when flash effect is complete.
- */
-OO.ui.OptionWidget.prototype.flash = function ( done ) {
-       var $this = this.$element;
-
-       if ( !this.disabled && this.constructor.static.highlightable ) {
-               $this.removeClass( 'oo-ui-optionWidget-highlighted' );
-               setTimeout( OO.ui.bind( function () {
-                       $this.addClass( 'oo-ui-optionWidget-highlighted' );
-                       if ( done ) {
-                               setTimeout( done, 100 );
-                       }
-               }, this ), 100 );
-       }
-};
-
-/**
- * Get option data.
- *
- * @method
- * @returns {Mixed} Option data
- */
-OO.ui.OptionWidget.prototype.getData = function () {
-       return this.data;
-};
-/**
- * Create an OO.ui.SelectWidget object.
- *
- * @class
- * @abstract
- * @extends OO.ui.Widget
- * @mixin OO.ui.GroupElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.SelectWidget = function OoUiSelectWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.GroupElement.call( this, this.$element, config );
-
-       // Properties
-       this.pressed = false;
-       this.selecting = null;
-       this.hashes = {};
-
-       // Events
-       this.$element.on( {
-               'mousedown': OO.ui.bind( this.onMouseDown, this ),
-               'mouseup': OO.ui.bind( this.onMouseUp, this ),
-               'mousemove': OO.ui.bind( this.onMouseMove, this ),
-               'mouseover': OO.ui.bind( this.onMouseOver, this ),
-               'mouseleave': OO.ui.bind( this.onMouseLeave, this )
-       } );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-selectWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.SelectWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupElement );
-
-/* Events */
-
-/**
- * @event highlight
- * @param {OO.ui.OptionWidget|null} item Highlighted item
- */
-
-/**
- * @event select
- * @param {OO.ui.OptionWidget|null} item Selected item
- */
-
-/**
- * @event add
- * @param {OO.ui.OptionWidget[]} items Added items
- * @param {number} index Index items were added at
- */
-
-/**
- * @event remove
- * @param {OO.ui.OptionWidget[]} items Removed items
- */
-
-/* Static Properties */
-
-OO.ui.SelectWidget.static.tagName = 'ul';
-
-/* Methods */
-
-/**
- * Handle mouse down events.
- *
- * @method
- * @private
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.SelectWidget.prototype.onMouseDown = function ( e ) {
-       var item;
-
-       if ( !this.disabled && e.which === 1 ) {
-               this.pressed = true;
-               item = this.getTargetItem( e );
-               if ( item && item.isSelectable() ) {
-                       this.intializeSelection( item );
-                       this.selecting = item;
-                       this.$( this.$.context ).one( 'mouseup', OO.ui.bind( this.onMouseUp, this ) );
-               }
-       }
-       return false;
-};
-
-/**
- * Handle mouse up events.
- *
- * @method
- * @private
- * @param {jQuery.Event} e Mouse up event
- */
-OO.ui.SelectWidget.prototype.onMouseUp = function ( e ) {
-       var item;
-       this.pressed = false;
-       if ( !this.selecting ) {
-               item = this.getTargetItem( e );
-               if ( item && item.isSelectable() ) {
-                       this.selecting = item;
-               }
-       }
-       if ( !this.disabled && e.which === 1 && this.selecting ) {
-               this.selectItem( this.selecting );
-               this.selecting = null;
-       }
-       return false;
-};
-
-/**
- * Handle mouse move events.
- *
- * @method
- * @private
- * @param {jQuery.Event} e Mouse move event
- */
-OO.ui.SelectWidget.prototype.onMouseMove = function ( e ) {
-       var item;
-
-       if ( !this.disabled && this.pressed ) {
-               item = this.getTargetItem( e );
-               if ( item && item !== this.selecting && item.isSelectable() ) {
-                       this.intializeSelection( item );
-                       this.selecting = item;
-               }
-       }
-       return false;
-};
-
-/**
- * Handle mouse over events.
- *
- * @method
- * @private
- * @param {jQuery.Event} e Mouse over event
- */
-OO.ui.SelectWidget.prototype.onMouseOver = function ( e ) {
-       var item;
-
-       if ( !this.disabled ) {
-               item = this.getTargetItem( e );
-               if ( item && item.isHighlightable() ) {
-                       this.highlightItem( item );
-               }
-       }
-       return false;
-};
-
-/**
- * Handle mouse leave events.
- *
- * @method
- * @private
- * @param {jQuery.Event} e Mouse over event
- */
-OO.ui.SelectWidget.prototype.onMouseLeave = function () {
-       if ( !this.disabled ) {
-               this.highlightItem();
-       }
-       return false;
-};
-
-/**
- * Get the closest item to a jQuery.Event.
- *
- * @method
- * @private
- * @param {jQuery.Event} e
- * @returns {OO.ui.OptionWidget|null} Outline item widget, `null` if none was found
- */
-OO.ui.SelectWidget.prototype.getTargetItem = function ( e ) {
-       var $item = this.$( e.target ).closest( '.oo-ui-optionWidget' );
-       if ( $item.length ) {
-               return $item.data( 'oo-ui-optionWidget' );
-       }
-       return null;
-};
-
-/**
- * Get selected item.
- *
- * @method
- * @returns {OO.ui.OptionWidget|null} Selected item, `null` if no item is selected
- */
-OO.ui.SelectWidget.prototype.getSelectedItem = function () {
-       var i, len;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               if ( this.items[i].isSelected() ) {
-                       return this.items[i];
-               }
-       }
-       return null;
-};
-
-/**
- * Get highlighted item.
- *
- * @method
- * @returns {OO.ui.OptionWidget|null} Highlighted item, `null` if no item is highlighted
- */
-OO.ui.SelectWidget.prototype.getHighlightedItem = function () {
-       var i, len;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               if ( this.items[i].isHighlighted() ) {
-                       return this.items[i];
-               }
-       }
-       return null;
-};
-
-/**
- * Get an existing item with equivilant data.
- *
- * @method
- * @param {Object} data Item data to search for
- * @returns {OO.ui.OptionWidget|null} Item with equivilent value, `null` if none exists
- */
-OO.ui.SelectWidget.prototype.getItemFromData = function ( data ) {
-       var hash = OO.getHash( data );
-
-       if ( hash in this.hashes ) {
-               return this.hashes[hash];
-       }
-
-       return null;
-};
-
-/**
- * Highlight an item.
- *
- * Highlighting is mutually exclusive.
- *
- * @method
- * @param {OO.ui.OptionWidget} [item] Item to highlight, omit to deselect all
- * @fires highlight
- * @chainable
- */
-OO.ui.SelectWidget.prototype.highlightItem = function ( item ) {
-       var i, len;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               this.items[i].setHighlighted( this.items[i] === item );
-       }
-       this.emit( 'highlight', item );
-
-       return this;
-};
-
-/**
- * Select an item.
- *
- * @method
- * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
- * @fires select
- * @chainable
- */
-OO.ui.SelectWidget.prototype.selectItem = function ( item ) {
-       var i, len;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               this.items[i].setSelected( this.items[i] === item );
-       }
-       this.emit( 'select', item );
-
-       return this;
-};
-
-/**
- * Setup selection and highlighting.
- *
- * This should be used to synchronize the UI with the model without emitting events that would in
- * turn update the model.
- *
- * @param {OO.ui.OptionWidget} [item] Item to select
- * @chainable
- */
-OO.ui.SelectWidget.prototype.intializeSelection = function( item ) {
-       var i, len, selected;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               selected = this.items[i] === item;
-               this.items[i].setSelected( selected );
-               this.items[i].setHighlighted( selected );
-       }
-
-       return this;
-};
-
-/**
- * Get an item relative to another one.
- *
- * @method
- * @param {OO.ui.OptionWidget} item Item to start at
- * @param {number} direction Direction to move in
- * @returns {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the menu
- */
-OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direction ) {
-       var inc = direction > 0 ? 1 : -1,
-               len = this.items.length,
-               index = item instanceof OO.ui.OptionWidget ?
-                       this.items.indexOf( item ) : ( inc > 0 ? -1 : 0 ),
-               stopAt = Math.max( Math.min( index, len - 1 ), 0 ),
-               i = inc > 0 ?
-                       // Default to 0 instead of -1, if nothing is selected let's start at the beginning
-                       Math.max( index, -1 ) :
-                       // Default to n-1 instead of -1, if nothing is selected let's start at the end
-                       Math.min( index, len );
-
-       while ( true ) {
-               i = ( i + inc + len ) % len;
-               item = this.items[i];
-               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
-                       return item;
-               }
-               // Stop iterating when we've looped all the way around
-               if ( i === stopAt ) {
-                       break;
-               }
-       }
-       return null;
-};
-
-/**
- * Get the next selectable item.
- *
- * @method
- * @returns {OO.ui.OptionWidget|null} Item, `null` if ther aren't any selectable items
- */
-OO.ui.SelectWidget.prototype.getFirstSelectableItem = function () {
-       var i, len, item;
-
-       for ( i = 0, len = this.items.length; i < len; i++ ) {
-               item = this.items[i];
-               if ( item instanceof OO.ui.OptionWidget && item.isSelectable() ) {
-                       return item;
-               }
-       }
-
-       return null;
-};
-
-/**
- * Add items.
- *
- * When items are added with the same values as existing items, the existing items will be
- * automatically removed before the new items are added.
- *
- * @method
- * @param {OO.ui.OptionWidget[]} items Items to add
- * @param {number} [index] Index to insert items after
- * @fires add
- * @chainable
- */
-OO.ui.SelectWidget.prototype.addItems = function ( items, index ) {
-       var i, len, item, hash,
-               remove = [];
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               hash = OO.getHash( item.getData() );
-               if ( hash in this.hashes ) {
-                       // Remove item with same value
-                       remove.push( this.hashes[hash] );
-               }
-               this.hashes[hash] = item;
-       }
-       if ( remove.length ) {
-               this.removeItems( remove );
-       }
-
-       OO.ui.GroupElement.prototype.addItems.call( this, items, index );
-
-       // Always provide an index, even if it was omitted
-       this.emit( 'add', items, index === undefined ? this.items.length - items.length - 1 : index );
-
-       return this;
-};
-
-/**
- * Remove items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @param {OO.ui.OptionWidget[]} items Items to remove
- * @fires remove
- * @chainable
- */
-OO.ui.SelectWidget.prototype.removeItems = function ( items ) {
-       var i, len, item, hash;
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               hash = OO.getHash( item.getData() );
-               if ( hash in this.hashes ) {
-                       // Remove existing item
-                       delete this.hashes[hash];
-               }
-               if ( item.isSelected() ) {
-                       this.selectItem( null );
-               }
-       }
-       OO.ui.GroupElement.prototype.removeItems.call( this, items );
-
-       this.emit( 'remove', items );
-
-       return this;
-};
-
-/**
- * Clear all items.
- *
- * Items will be detached, not removed, so they can be used later.
- *
- * @method
- * @fires remove
- * @chainable
- */
-OO.ui.SelectWidget.prototype.clearItems = function () {
-       var items = this.items.slice();
-
-       // Clear all items
-       this.hashes = {};
-       OO.ui.GroupElement.prototype.clearItems.call( this );
-       this.selectItem( null );
-
-       this.emit( 'remove', items );
-
-       return this;
-};
-/**
- * Creates an OO.ui.MenuItemWidget object.
- *
- * @class
- * @extends OO.ui.OptionWidget
- *
- * @constructor
- * @param {Mixed} data Item data
- * @param {Object} [config] Configuration options
- */
-OO.ui.MenuItemWidget = function OoUiMenuItemWidget( data, config ) {
-       // Configuration initialization
-       config = $.extend( { 'icon': 'check' }, config );
-
-       // Parent constructor
-       OO.ui.OptionWidget.call( this, data, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-menuItemWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.MenuItemWidget, OO.ui.OptionWidget );
-/**
- * Create an OO.ui.MenuWidget object.
- *
- * @class
- * @extends OO.ui.SelectWidget
- * @mixins OO.ui.ClippableElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {OO.ui.InputWidget} [input] Input to bind keyboard handlers to
- */
-OO.ui.MenuWidget = function OoUiMenuWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.SelectWidget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.ClippableElement.call( this, this.$group );
-
-       // Properties
-       this.newItems = [];
-       this.$input = config.input ? config.input.$input : null;
-       this.$previousFocus = null;
-       this.isolated = !config.input;
-       this.visible = false;
-       this.onKeyDownHandler = OO.ui.bind( this.onKeyDown, this );
-
-       // Initialization
-       this.$element.hide().addClass( 'oo-ui-menuWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.MenuWidget, OO.ui.SelectWidget );
-
-OO.mixinClass( OO.ui.MenuWidget, OO.ui.ClippableElement );
-
-/* Methods */
-
-/**
- * Handles key down events.
- *
- * @method
- * @param {jQuery.Event} e Key down event
- */
-OO.ui.MenuWidget.prototype.onKeyDown = function ( e ) {
-       var nextItem,
-               handled = false,
-               highlightItem = this.getHighlightedItem();
-
-       if ( !this.disabled && this.visible ) {
-               if ( !highlightItem ) {
-                       highlightItem = this.getSelectedItem();
-               }
-               switch ( e.keyCode ) {
-                       case OO.ui.Keys.ENTER:
-                               this.selectItem( highlightItem );
-                               handled = true;
-                               break;
-                       case OO.ui.Keys.UP:
-                               nextItem = this.getRelativeSelectableItem( highlightItem, -1 );
-                               handled = true;
-                               break;
-                       case OO.ui.Keys.DOWN:
-                               nextItem = this.getRelativeSelectableItem( highlightItem, 1 );
-                               handled = true;
-                               break;
-                       case OO.ui.Keys.ESCAPE:
-                               if ( highlightItem ) {
-                                       highlightItem.setHighlighted( false );
-                               }
-                               this.hide();
-                               handled = true;
-                               break;
-               }
-
-               if ( nextItem ) {
-                       this.highlightItem( nextItem );
-                       nextItem.scrollElementIntoView();
-               }
-
-               if ( handled ) {
-                       e.preventDefault();
-                       e.stopPropagation();
-                       return false;
-               }
-       }
-};
-
-/**
- * Check if the menu is visible.
- *
- * @method
- * @returns {boolean} Menu is visible
- */
-OO.ui.MenuWidget.prototype.isVisible = function () {
-       return this.visible;
-};
-
-/**
- * Bind key down listener
- *
- * @method
- */
-OO.ui.MenuWidget.prototype.bindKeyDownListener = function () {
-       if ( this.$input ) {
-               this.$input.on( 'keydown', this.onKeyDownHandler );
-       } else {
-               // Capture menu navigation keys
-               this.getElementWindow().addEventListener( 'keydown', this.onKeyDownHandler, true );
-       }
-};
-
-/**
- * Unbind key down listener
- *
- * @method
- */
-OO.ui.MenuWidget.prototype.unbindKeyDownListener = function () {
-       if ( this.$input ) {
-               this.$input.off( 'keydown' );
-       } else {
-               this.getElementWindow().removeEventListener( 'keydown', this.onKeyDownHandler, true );
-       }
-};
-
-/**
- * Select an item.
- *
- * The menu will stay open if an item is silently selected.
- *
- * @method
- * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
- * @chainable
- */
-OO.ui.MenuWidget.prototype.selectItem = function ( item ) {
-       // Parent method
-       OO.ui.SelectWidget.prototype.selectItem.call( this, item );
-
-       if ( !this.disabled ) {
-               if ( item ) {
-                       this.disabled = true;
-                       item.flash( OO.ui.bind( function () {
-                               this.hide();
-                               this.disabled = false;
-                       }, this ) );
-               } else {
-                       this.hide();
-               }
-       }
-
-       return this;
-};
-
-/**
- * Add items.
- *
- * Adding an existing item (by value) will move it.
- *
- * @method
- * @param {OO.ui.MenuItemWidget[]} items Items to add
- * @param {number} [index] Index to insert items after
- * @chainable
- */
-OO.ui.MenuWidget.prototype.addItems = function ( items, index ) {
-       var i, len, item;
-
-       // Parent method
-       OO.ui.SelectWidget.prototype.addItems.call( this, items, index );
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               item = items[i];
-               if ( this.visible ) {
-                       // Defer fitting label until
-                       item.fitLabel();
-               } else {
-                       this.newItems.push( item );
-               }
-       }
-
-       return this;
-};
-
-/**
- * Show the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.MenuWidget.prototype.show = function () {
-       var i, len;
-
-       if ( this.items.length ) {
-               this.$element.show();
-               this.visible = true;
-               this.bindKeyDownListener();
-
-               // Change focus to enable keyboard navigation
-               if ( this.isolated && this.$input && !this.$input.is( ':focus' ) ) {
-                       this.$previousFocus = this.$( ':focus' );
-                       this.$input.focus();
-               }
-               if ( this.newItems.length ) {
-                       for ( i = 0, len = this.newItems.length; i < len; i++ ) {
-                               this.newItems[i].fitLabel();
-                       }
-                       this.newItems = [];
-               }
-
-               this.setClipping( true );
-       }
-
-       return this;
-};
-
-/**
- * Hide the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.MenuWidget.prototype.hide = function () {
-       this.$element.hide();
-       this.visible = false;
-       this.unbindKeyDownListener();
-
-       if ( this.isolated && this.$previousFocus ) {
-               this.$previousFocus.focus();
-               this.$previousFocus = null;
-       }
-
-       this.setClipping( false );
-
-       return this;
-};
-/**
- * Creates an OO.ui.MenuSectionItemWidget object.
- *
- * @class
- * @extends OO.ui.OptionWidget
- *
- * @constructor
- * @param {Mixed} data Item data
- * @param {Object} [config] Configuration options
- */
-OO.ui.MenuSectionItemWidget = function OoUiMenuSectionItemWidget( data, config ) {
-       // Parent constructor
-       OO.ui.OptionWidget.call( this, data, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-menuSectionItemWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.MenuSectionItemWidget, OO.ui.OptionWidget );
-
-OO.ui.MenuSectionItemWidget.static.selectable = false;
-
-OO.ui.MenuSectionItemWidget.static.highlightable = false;
-/**
- * Create an OO.ui.OutlineWidget object.
- *
- * @class
- * @extends OO.ui.SelectWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.OutlineWidget = function OoUiOutlineWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.SelectWidget.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-outlineWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.OutlineWidget, OO.ui.SelectWidget );
-/**
- * Creates an OO.ui.OutlineControlsWidget object.
- *
- * @class
- *
- * @constructor
- * @param {OO.ui.OutlineWidget} outline Outline to control
- * @param {Object} [config] Configuration options
- * @cfg {Object[]} [adders] List of icons to show as addable item types, each an object with
- *  name, title and icon properties
- */
-OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Properties
-       this.outline = outline;
-       this.adders = {};
-       this.$adders = this.$( '<div>' );
-       this.$movers = this.$( '<div>' );
-       this.addButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'add-item'
-       } );
-       this.upButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'collapse',
-               'title': OO.ui.msg( 'ooui-outline-control-move-up' )
-       } );
-       this.downButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'expand',
-               'title': OO.ui.msg( 'ooui-outline-control-move-down' )
-       } );
-
-       // Events
-       outline.connect( this, {
-               'select': 'onOutlineChange',
-               'add': 'onOutlineChange',
-               'remove': 'onOutlineChange'
-       } );
-       this.upButton.connect( this, { 'click': ['emit', 'move', -1] } );
-       this.downButton.connect( this, { 'click': ['emit', 'move', 1] } );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-outlineControlsWidget' );
-       this.$adders.addClass( 'oo-ui-outlineControlsWidget-adders' );
-       this.$movers
-               .addClass( 'oo-ui-outlineControlsWidget-movers' )
-               .append( this.upButton.$element, this.downButton.$element );
-       this.$element.append( this.$adders, this.$movers );
-       if ( config.adders && config.adders.length ) {
-               this.setupAdders( config.adders );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );
-
-/* Events */
-
-/**
- * @event move
- * @param {number} places Number of places to move
- */
-
-/* Methods */
-
-/**
- * Handle outline change events.
- *
- * @method
- */
-OO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {
-       var i, len, firstMovable, lastMovable,
-               movable = false,
-               items = this.outline.getItems(),
-               selectedItem = this.outline.getSelectedItem();
-
-       if ( selectedItem && selectedItem.isMovable() ) {
-               movable = true;
-               i = -1;
-               len = items.length;
-               while ( ++i < len ) {
-                       if ( items[i].isMovable() ) {
-                               firstMovable = items[i];
-                               break;
-                       }
-               }
-               i = len;
-               while ( i-- ) {
-                       if ( items[i].isMovable() ) {
-                               lastMovable = items[i];
-                               break;
-                       }
-               }
-       }
-       this.upButton.setDisabled( !movable || selectedItem === firstMovable );
-       this.downButton.setDisabled( !movable || selectedItem === lastMovable );
-};
-
-/**
- * Setup adders icons.
- *
- * @method
- * @param {Object[]} adders List of configuations for adder buttons, each containing a name, title
- *  and icon property
- */
-OO.ui.OutlineControlsWidget.prototype.setupAdders = function ( adders ) {
-       var i, len, addition, button,
-               $buttons = this.$( [] );
-
-       this.$adders.append( this.addButton.$element );
-       for ( i = 0, len = adders.length; i < len; i++ ) {
-               addition = adders[i];
-               button = new OO.ui.ButtonWidget( {
-                       '$': this.$, 'frameless': true, 'icon': addition.icon, 'title': addition.title
-               } );
-               button.connect( this, { 'click': ['emit', 'add', addition.name] } );
-               this.adders[addition.name] = button;
-               this.$adders.append( button.$element );
-               $buttons = $buttons.add( button.$element );
-       }
-};
-/**
- * Creates an OO.ui.OutlineItemWidget object.
- *
- * @class
- * @extends OO.ui.OptionWidget
- *
- * @constructor
- * @param {Mixed} data Item data
- * @param {Object} [config] Configuration options
- * @cfg {number} [level] Indentation level
- * @cfg {boolean} [movable] Allow modification from outline controls
- */
-OO.ui.OutlineItemWidget = function OoUiOutlineItemWidget( data, config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.OptionWidget.call( this, data, config );
-
-       // Properties
-       this.level = 0;
-       this.movable = !!config.movable;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-outlineItemWidget' );
-       this.setLevel( config.level );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.OutlineItemWidget, OO.ui.OptionWidget );
-
-/* Static Properties */
-
-OO.ui.OutlineItemWidget.static.highlightable = false;
-
-OO.ui.OutlineItemWidget.static.scrollIntoViewOnSelect = true;
-
-OO.ui.OutlineItemWidget.static.levelClass = 'oo-ui-outlineItemWidget-level-';
-
-OO.ui.OutlineItemWidget.static.levels = 3;
-
-/* Methods */
-
-/**
- * Check if item is movable.
- *
- * Moveablilty is used by outline controls.
- *
- * @returns {boolean} Item is movable
- */
-OO.ui.OutlineItemWidget.prototype.isMovable = function () {
-       return this.movable;
-};
-
-/**
- * Get indentation level.
- *
- * @returns {number} Indentation level
- */
-OO.ui.OutlineItemWidget.prototype.getLevel = function () {
-       return this.level;
-};
-
-/**
- * Set indentation level.
- *
- * @method
- * @param {number} [level=0] Indentation level, in the range of [0,#maxLevel]
- * @chainable
- */
-OO.ui.OutlineItemWidget.prototype.setLevel = function ( level ) {
-       var levels = this.constructor.static.levels,
-               levelClass = this.constructor.static.levelClass,
-               i = levels;
-
-       this.level = level ? Math.max( 0, Math.min( levels - 1, level ) ) : 0;
-       while ( i-- ) {
-               if ( this.level === i ) {
-                       this.$element.addClass( levelClass + i );
-               } else {
-                       this.$element.removeClass( levelClass + i );
-               }
-       }
-
-       return this;
-};
-/**
- * Creates an OO.ui.BookletOutlineItemWidget object.
- *
- * @class
- * @extends OO.ui.OutlineItemWidget
- *
- * @constructor
- * @param {Mixed} data Item data
- * @param {Object} [config] Configuration options
- */
-OO.ui.BookletOutlineItemWidget = function OoUiBookletOutlineItemWidget( data, page, config ) {
-       // Configuration intialization
-       config = $.extend( {
-               'label': page.getLabel() || data,
-               'level': page.getLevel(),
-               'icon': page.getIcon(),
-               'indicator': page.getIndicator(),
-               'indicatorTitle': page.getIndicatorTitle(),
-               'movable': page.isMovable()
-       }, config );
-
-       // Parent constructor
-       OO.ui.OutlineItemWidget.call( this, data, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-bookletOutlineItemWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.BookletOutlineItemWidget, OO.ui.OutlineItemWidget );
-/**
- * Create an OO.ui.ButtonSelect object.
- *
- * @class
- * @extends OO.ui.OptionWidget
- * @mixins OO.ui.ButtonedElement
- * @mixins OO.ui.FlaggableElement
- *
- * @constructor
- * @param {Mixed} data Option data
- * @param {Object} [config] Configuration options
- */
-OO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( data, config ) {
-       // Parent constructor
-       OO.ui.OptionWidget.call( this, data, config );
-
-       // Mixin constructors
-       OO.ui.ButtonedElement.call( this, this.$( '<a>' ), config );
-       OO.ui.FlaggableElement.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-buttonOptionWidget' );
-       this.$button.append( this.$element.contents() );
-       this.$element.append( this.$button );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ButtonOptionWidget, OO.ui.OptionWidget );
-
-OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.ButtonedElement );
-OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.FlaggableElement );
-
-/* Methods */
-
-/**
- * @inheritdoc
- */
-OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
-       OO.ui.OptionWidget.prototype.setSelected.call( this, state );
-
-       this.setActive( state );
-
-       return this;
-};
-/**
- * Create an OO.ui.ButtonSelect object.
- *
- * @class
- * @extends OO.ui.SelectWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.ButtonSelectWidget = function OoUiButtonSelectWidget( config ) {
-       // Parent constructor
-       OO.ui.SelectWidget.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-buttonSelectWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ButtonSelectWidget, OO.ui.SelectWidget );
-/**
- * Creates an OO.ui.PopupWidget object.
- *
- * @class
- * @extends OO.ui.Widget
- * @mixins OO.ui.LabeledElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [tail=true] Show tail pointing to origin of popup
- * @cfg {string} [align='center'] Alignment of popup to origin
- * @cfg {jQuery} [$container] Container to prevent popup from rendering outside of
- * @cfg {boolean} [autoClose=false] Popup auto-closes when it loses focus
- * @cfg {jQuery} [$autoCloseIgnore] Elements to not auto close when clicked
- * @cfg {boolean} [head] Show label and close button at the top
- */
-OO.ui.PopupWidget = function OoUiPopupWidget( config ) {
-       // Config intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.LabeledElement.call( this, this.$( '<div>' ), config );
-
-       // Properties
-       this.visible = false;
-       this.$popup = this.$( '<div>' );
-       this.$head = this.$( '<div>' );
-       this.$body = this.$( '<div>' );
-       this.$tail = this.$( '<div>' );
-       this.$container = config.$container || this.$( 'body' );
-       this.autoClose = !!config.autoClose;
-       this.$autoCloseIgnore = config.$autoCloseIgnore;
-       this.transitionTimeout = null;
-       this.tail = false;
-       this.align = config.align || 'center';
-       this.closeButton = new OO.ui.ButtonWidget( { '$': this.$, 'frameless': true, 'icon': 'close' } );
-       this.onMouseDownHandler = OO.ui.bind( this.onMouseDown, this );
-
-       // Events
-       this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
-
-       // Initialization
-       this.useTail( config.tail !== undefined ? !!config.tail : true );
-       this.$body.addClass( 'oo-ui-popupWidget-body' );
-       this.$tail.addClass( 'oo-ui-popupWidget-tail' );
-       this.$head
-               .addClass( 'oo-ui-popupWidget-head' )
-               .append( this.$label, this.closeButton.$element );
-       if ( !config.head ) {
-               this.$head.hide();
-       }
-       this.$popup
-               .addClass( 'oo-ui-popupWidget-popup' )
-               .append( this.$head, this.$body );
-       this.$element.hide()
-               .addClass( 'oo-ui-popupWidget' )
-               .append( this.$popup, this.$tail );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PopupWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.PopupWidget, OO.ui.LabeledElement );
-
-/* Events */
-
-/**
- * @event hide
- */
-
-/**
- * @event show
- */
-
-/* Methods */
-
-/**
- * Handles mouse down events.
- *
- * @method
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.PopupWidget.prototype.onMouseDown = function ( e ) {
-       if (
-               this.visible &&
-               !$.contains( this.$element[0], e.target ) &&
-               ( !this.$autoCloseIgnore || !this.$autoCloseIgnore.has( e.target ).length )
-       ) {
-               this.hide();
-       }
-};
-
-/**
- * Bind mouse down listener
- *
- * @method
- */
-OO.ui.PopupWidget.prototype.bindMouseDownListener = function () {
-       // Capture clicks outside popup
-       this.getElementWindow().addEventListener( 'mousedown', this.onMouseDownHandler, true );
-};
-
-/**
- * Handles close button click events.
- *
- * @method
- */
-OO.ui.PopupWidget.prototype.onCloseButtonClick = function () {
-       if ( this.visible ) {
-               this.hide();
-       }
-};
-
-/**
- * Unbind mouse down listener
- *
- * @method
- */
-OO.ui.PopupWidget.prototype.unbindMouseDownListener = function () {
-       this.getElementWindow().removeEventListener( 'mousedown', this.onMouseDownHandler, true );
-};
-
-/**
- * Check if the popup is visible.
- *
- * @method
- * @returns {boolean} Popup is visible
- */
-OO.ui.PopupWidget.prototype.isVisible = function () {
-       return this.visible;
-};
-
-/**
- * Set whether to show a tail.
- *
- * @method
- * @returns {boolean} Make tail visible
- */
-OO.ui.PopupWidget.prototype.useTail = function ( value ) {
-       value = !!value;
-       if ( this.tail !== value ) {
-               this.tail = value;
-               if ( value ) {
-                       this.$element.addClass( 'oo-ui-popupWidget-tailed' );
-               } else {
-                       this.$element.removeClass( 'oo-ui-popupWidget-tailed' );
-               }
-       }
-};
-
-/**
- * Check if showing a tail.
- *
- * @method
- * @returns {boolean} tail is visible
- */
-OO.ui.PopupWidget.prototype.hasTail = function () {
-       return this.tail;
-};
-
-/**
- * Show the context.
- *
- * @method
- * @fires show
- * @chainable
- */
-OO.ui.PopupWidget.prototype.show = function () {
-       if ( !this.visible ) {
-               this.$element.show();
-               this.visible = true;
-               this.emit( 'show' );
-               if ( this.autoClose ) {
-                       this.bindMouseDownListener();
-               }
-       }
-       return this;
-};
-
-/**
- * Hide the context.
- *
- * @method
- * @fires hide
- * @chainable
- */
-OO.ui.PopupWidget.prototype.hide = function () {
-       if ( this.visible ) {
-               this.$element.hide();
-               this.visible = false;
-               this.emit( 'hide' );
-               if ( this.autoClose ) {
-                       this.unbindMouseDownListener();
-               }
-       }
-       return this;
-};
-
-/**
- * Updates the position and size.
- *
- * @method
- * @param {number} width Width
- * @param {number} height Height
- * @param {boolean} [transition=false] Use a smooth transition
- * @chainable
- */
-OO.ui.PopupWidget.prototype.display = function ( width, height, transition ) {
-       var padding = 10,
-               originOffset = Math.round( this.$element.offset().left ),
-               containerLeft = Math.round( this.$container.offset().left ),
-               containerWidth = this.$container.innerWidth(),
-               containerRight = containerLeft + containerWidth,
-               popupOffset = width * ( { 'left': 0, 'center': -0.5, 'right': -1 } )[this.align],
-               popupLeft = popupOffset - padding,
-               popupRight = popupOffset + padding + width + padding,
-               overlapLeft = ( originOffset + popupLeft ) - containerLeft,
-               overlapRight = containerRight - ( originOffset + popupRight );
-
-       // Prevent transition from being interrupted
-       clearTimeout( this.transitionTimeout );
-       if ( transition ) {
-               // Enable transition
-               this.$element.addClass( 'oo-ui-popupWidget-transitioning' );
-       }
-
-       if ( overlapRight < 0 ) {
-               popupOffset += overlapRight;
-       } else if ( overlapLeft < 0 ) {
-               popupOffset -= overlapLeft;
-       }
-
-       // Position body relative to anchor and resize
-       this.$popup.css( {
-               'left': popupOffset,
-               'width': width,
-               'height': height === undefined ? 'auto' : height
-       } );
-
-       if ( transition ) {
-               // Prevent transitioning after transition is complete
-               this.transitionTimeout = setTimeout( OO.ui.bind( function () {
-                       this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
-               }, this ), 200 );
-       } else {
-               // Prevent transitioning immediately
-               this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
-       }
-
-       return this;
-};
-/**
- * Button that shows and hides a popup.
- *
- * @class
- * @extends OO.ui.ButtonWidget
- * @mixins OO.ui.PopuppableElement
- *
- * @constructor
- * @param {Object} [config] Configuration options
- */
-OO.ui.PopupButtonWidget = function OoUiPopupButtonWidget( config ) {
-       // Parent constructor
-       OO.ui.ButtonWidget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.PopuppableElement.call( this, config );
-
-       // Initialization
-       this.$element
-               .addClass( 'oo-ui-popupButtonWidget' )
-               .append( this.popup.$element );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.PopupButtonWidget, OO.ui.ButtonWidget );
-
-OO.mixinClass( OO.ui.PopupButtonWidget, OO.ui.PopuppableElement );
-
-/* Methods */
-
-/**
- * Handles mouse click events.
- *
- * @method
- * @param {jQuery.Event} e Mouse click event
- */
-OO.ui.PopupButtonWidget.prototype.onClick = function ( e ) {
-       // Skip clicks within the popup
-       if ( $.contains( this.popup.$element[0], e.target ) ) {
-               return;
-       }
-
-       if ( !this.disabled ) {
-               if ( this.popup.isVisible() ) {
-                       this.hidePopup();
-               } else {
-                       this.showPopup();
-               }
-               OO.ui.ButtonWidget.prototype.onClick.call( this );
-       }
-       return false;
-};
-/**
- * Creates an OO.ui.SearchWidget object.
- *
- * @class
- * @extends OO.ui.Widget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string|jQuery} [placeholder] Placeholder text for query input
- * @cfg {string} [value] Initial query value
- */
-OO.ui.SearchWidget = function OoUiSearchWidget( config ) {
-       // Configuration intialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Properties
-       this.query = new OO.ui.TextInputWidget( {
-               '$': this.$,
-               'icon': 'search',
-               'placeholder': config.placeholder,
-               'value': config.value
-       } );
-       this.results = new OO.ui.SelectWidget( { '$': this.$ } );
-       this.$query = this.$( '<div>' );
-       this.$results = this.$( '<div>' );
-
-       // Events
-       this.query.connect( this, {
-               'change': 'onQueryChange',
-               'enter': 'onQueryEnter'
-       } );
-       this.results.connect( this, {
-               'highlight': 'onResultsHighlight',
-               'select': 'onResultsSelect'
-       } );
-       this.query.$input.on( 'keydown', OO.ui.bind( this.onQueryKeydown, this ) );
-
-       // Initialization
-       this.$query
-               .addClass( 'oo-ui-searchWidget-query' )
-               .append( this.query.$element );
-       this.$results
-               .addClass( 'oo-ui-searchWidget-results' )
-               .append( this.results.$element );
-       this.$element
-               .addClass( 'oo-ui-searchWidget' )
-               .append( this.$results, this.$query );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.SearchWidget, OO.ui.Widget );
-
-/* Events */
-
-/**
- * @event highlight
- * @param {Object|null} item Item data or null if no item is highlighted
- */
-
-/**
- * @event select
- * @param {Object|null} item Item data or null if no item is selected
- */
-
-/* Methods */
-
-/**
- * Handle query key down events.
- *
- * @method
- * @param {jQuery.Event} e Key down event
- */
-OO.ui.SearchWidget.prototype.onQueryKeydown = function ( e ) {
-       var highlightedItem, nextItem,
-               dir = e.which === OO.ui.Keys.DOWN ? 1 : ( e.which === OO.ui.Keys.UP ? -1 : 0 );
-
-       if ( dir ) {
-               highlightedItem = this.results.getHighlightedItem();
-               if ( !highlightedItem ) {
-                       highlightedItem = this.results.getSelectedItem();
-               }
-               nextItem = this.results.getRelativeSelectableItem( highlightedItem, dir );
-               this.results.highlightItem( nextItem );
-               nextItem.scrollElementIntoView();
-       }
-};
-
-/**
- * Handle select widget select events.
- *
- * Clears existing results. Subclasses should repopulate items according to new query.
- *
- * @method
- * @param {string} value New value
- */
-OO.ui.SearchWidget.prototype.onQueryChange = function () {
-       // Reset
-       this.results.clearItems();
-};
-
-/**
- * Handle select widget enter key events.
- *
- * Selects highlighted item.
- *
- * @method
- * @param {string} value New value
- */
-OO.ui.SearchWidget.prototype.onQueryEnter = function () {
-       // Reset
-       this.results.selectItem( this.results.getHighlightedItem() );
-};
-
-/**
- * Handle select widget highlight events.
- *
- * @method
- * @param {OO.ui.OptionWidget} item Highlighted item
- * @fires highlight
- */
-OO.ui.SearchWidget.prototype.onResultsHighlight = function ( item ) {
-       this.emit( 'highlight', item ? item.getData() : null );
-};
-
-/**
- * Handle select widget select events.
- *
- * @method
- * @param {OO.ui.OptionWidget} item Selected item
- * @fires select
- */
-OO.ui.SearchWidget.prototype.onResultsSelect = function ( item ) {
-       this.emit( 'select', item ? item.getData() : null );
-};
-
-/**
- * Get the query input.
- *
- * @method
- * @returns {OO.ui.TextInputWidget} Query input
- */
-OO.ui.SearchWidget.prototype.getQuery = function () {
-       return this.query;
-};
-
-/**
- * Get the results list.
- *
- * @method
- * @returns {OO.ui.SelectWidget} Select list
- */
-OO.ui.SearchWidget.prototype.getResults = function () {
-       return this.results;
-};
-/**
- * Creates an OO.ui.TextInputWidget object.
- *
- * @class
- * @extends OO.ui.InputWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {string} [placeholder] Placeholder text
- * @cfg {string} [icon] Symbolic name of icon
- * @cfg {boolean} [multiline=false] Allow multiple lines of text
- */
-OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.InputWidget.call( this, config );
-
-       // Properties
-       this.pending = 0;
-       this.multiline = !!config.multiline;
-
-       // Events
-       this.$input.on( 'keypress', OO.ui.bind( this.onKeyPress, this ) );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-textInputWidget' );
-       if ( config.icon ) {
-               this.$element.addClass( 'oo-ui-textInputWidget-decorated' );
-               this.$element.append(
-                       this.$( '<span>' )
-                               .addClass( 'oo-ui-textInputWidget-icon oo-ui-icon-' + config.icon )
-                               .mousedown( OO.ui.bind( function () {
-                                       this.$input.focus();
-                                       return false;
-                               }, this ) )
-               );
-       }
-       if ( config.placeholder ) {
-               this.$input.attr( 'placeholder', config.placeholder );
-       }
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.TextInputWidget, OO.ui.InputWidget );
-
-/* Events */
-
-/**
- * User presses enter inside the text box.
- *
- * Not called if input is multiline.
- *
- * @event enter
- */
-
-/* Methods */
-
-/**
- * Handles key press events.
- *
- * @param {jQuery.Event} e Key press event
- * @fires enter If enter key is pressed and input is not multiline
- */
-OO.ui.TextInputWidget.prototype.onKeyPress = function ( e ) {
-       if ( e.which === OO.ui.Keys.ENTER && !this.multiline ) {
-               this.emit( 'enter' );
-       }
-};
-
-/**
- * Get input element.
- *
- * @method
- * @param {Object} [config] Configuration options
- * @returns {jQuery} Input element
- */
-OO.ui.TextInputWidget.prototype.getInputElement = function ( config ) {
-       return config.multiline ? this.$( '<textarea>' ) : this.$( '<input type="text" />' );
-};
-
-/* Methods */
-
-/**
- * Checks if input is pending.
- *
- * @method
- * @returns {boolean} Input is pending
- */
-OO.ui.TextInputWidget.prototype.isPending = function () {
-       return !!this.pending;
-};
-
-/**
- * Increases the pending stack.
- *
- * @method
- * @chainable
- */
-OO.ui.TextInputWidget.prototype.pushPending = function () {
-       this.pending++;
-       this.$element.addClass( 'oo-ui-textInputWidget-pending' );
-       this.$input.addClass( 'oo-ui-texture-pending' );
-       return this;
-};
-
-/**
- * Reduces the pending stack.
- *
- * Clamped at zero.
- *
- * @method
- * @chainable
- */
-OO.ui.TextInputWidget.prototype.popPending = function () {
-       this.pending = Math.max( 0, this.pending - 1 );
-       if ( !this.pending ) {
-               this.$element.removeClass( 'oo-ui-textInputWidget-pending' );
-               this.$input.removeClass( 'oo-ui-texture-pending' );
-       }
-       return this;
-};
-/**
- * Creates an OO.ui.TextInputMenuWidget object.
- *
- * @class
- * @extends OO.ui.MenuWidget
- *
- * @constructor
- * @param {OO.ui.TextInputWidget} input Text input widget to provide menu for
- * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$container=input.$element] Element to render menu under
- */
-OO.ui.TextInputMenuWidget = function OoUiTextInputMenuWidget( input, config ) {
-       // Parent constructor
-       OO.ui.MenuWidget.call( this, config );
-
-       // Properties
-       this.input = input;
-       this.$container = config.$container || this.input.$element;
-       this.onWindowResizeHandler = OO.ui.bind( this.onWindowResize, this );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-textInputMenuWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.TextInputMenuWidget, OO.ui.MenuWidget );
-
-/* Methods */
-
-/**
- * Handle window resize event.
- *
- * @method
- * @param {jQuery.Event} e Window resize event
- */
-OO.ui.TextInputMenuWidget.prototype.onWindowResize = function () {
-       this.position();
-};
-
-/**
- * Shows the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.TextInputMenuWidget.prototype.show = function () {
-       // Parent method
-       OO.ui.MenuWidget.prototype.show.call( this );
-
-       this.position();
-       this.$( this.getElementWindow() ).on( 'resize', this.onWindowResizeHandler );
-       return this;
-};
-
-/**
- * Hides the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.TextInputMenuWidget.prototype.hide = function () {
-       // Parent method
-       OO.ui.MenuWidget.prototype.hide.call( this );
-
-       this.$( this.getElementWindow() ).off( 'resize', this.onWindowResizeHandler );
-       return this;
-};
-
-/**
- * Positions the menu.
- *
- * @method
- * @chainable
- */
-OO.ui.TextInputMenuWidget.prototype.position = function () {
-       var frameOffset,
-               $container = this.$container,
-               dimensions = $container.offset();
-
-       // Position under input
-       dimensions.top += $container.height();
-
-       // Compensate for frame position if in a differnt frame
-       if ( this.input.$.frame && this.input.$.context !== this.$element[0].ownerDocument ) {
-               frameOffset = OO.ui.Element.getRelativePosition(
-                       this.input.$.frame.$element, this.$element.offsetParent()
-               );
-               dimensions.left += frameOffset.left;
-               dimensions.top += frameOffset.top;
-       } else {
-               // Fix for RTL (for some reason, no need to fix if the frameoffset is set)
-               if ( this.$element.css( 'direction' ) === 'rtl' ) {
-                       dimensions.right = this.$element.parent().position().left -
-                               dimensions.width - dimensions.left;
-                       // Erase the value for 'left':
-                       delete dimensions.left;
-               }
-       }
-
-       this.$element.css( dimensions );
-       this.setIdealSize( $container.width() );
-       return this;
-};
-/**
- * Mixin for widgets with a boolean state.
- *
- * @class
- * @abstract
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [value=false] Initial value
- */
-OO.ui.ToggleWidget = function OoUiToggleWidget( config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Properties
-       this.value = null;
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-toggleWidget' );
-       this.setValue( !!config.value );
-};
-
-/* Events */
-
-/**
- * @event change
- * @param {boolean} value Changed value
- */
-
-/* Methods */
-
-/**
- * Get the value of the toggle.
- *
- * @method
- * @returns {boolean} Toggle value
- */
-OO.ui.ToggleWidget.prototype.getValue = function () {
-       return this.value;
-};
-
-/**
- * Set the value of the toggle.
- *
- * @method
- * @param {boolean} value New value
- * @fires change
- * @chainable
- */
-OO.ui.ToggleWidget.prototype.setValue = function ( value ) {
-       value = !!value;
-       if ( this.value !== value ) {
-               this.value = value;
-               this.emit( 'change', value );
-               this.$element.toggleClass( 'oo-ui-toggleWidget-on', value );
-               this.$element.toggleClass( 'oo-ui-toggleWidget-off', !value );
-       }
-       return this;
-};
-/**
- * @class
- * @extends OO.ui.ButtonWidget
- * @mixins OO.ui.ToggleWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [value=false] Initial value
- */
-OO.ui.ToggleButtonWidget = function OoUiToggleButtonWidget( config ) {
-       // Configuration initialization
-       config = config || {};
-
-       // Parent constructor
-       OO.ui.ButtonWidget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.ToggleWidget.call( this, config );
-
-       // Initialization
-       this.$element.addClass( 'oo-ui-toggleButtonWidget' );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ToggleButtonWidget, OO.ui.ButtonWidget );
-
-OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.ToggleWidget );
-
-/* Methods */
-
-/**
- * @inheritdoc
- */
-OO.ui.ToggleButtonWidget.prototype.onClick = function () {
-       if ( !this.disabled ) {
-               this.setValue( !this.value );
-       }
-
-       // Parent method
-       return OO.ui.ButtonWidget.prototype.onClick.call( this );
-};
-
-/**
- * @inheritdoc
- */
-OO.ui.ToggleButtonWidget.prototype.setValue = function ( value ) {
-       value = !!value;
-       if ( value !== this.value ) {
-               this.setActive( value );
-       }
-
-       // Parent method
-       OO.ui.ToggleWidget.prototype.setValue.call( this, value );
-
-       return this;
-};
-/**
- * @class
- * @abstract
- * @extends OO.ui.Widget
- * @mixins OO.ui.ToggleWidget
- *
- * @constructor
- * @param {Object} [config] Configuration options
- * @cfg {boolean} [value=false] Initial value
- */
-OO.ui.ToggleSwitchWidget = function OoUiToggleSwitchWidget( config ) {
-       // Parent constructor
-       OO.ui.Widget.call( this, config );
-
-       // Mixin constructors
-       OO.ui.ToggleWidget.call( this, config );
-
-       // Properties
-       this.dragging = false;
-       this.dragStart = null;
-       this.sliding = false;
-       this.$on = this.$( '<span>' );
-       this.$grip = this.$( '<span>' );
-
-       // Events
-       this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
-
-       // Initialization
-       this.$on.addClass( 'oo-ui-toggleSwitchWidget-on' );
-       this.$grip.addClass( 'oo-ui-toggleSwitchWidget-grip' );
-       this.$element
-               .addClass( 'oo-ui-toggleSwitchWidget' )
-               .append( this.$on, this.$grip );
-};
-
-/* Inheritance */
-
-OO.inheritClass( OO.ui.ToggleSwitchWidget, OO.ui.Widget );
-
-OO.mixinClass( OO.ui.ToggleSwitchWidget, OO.ui.ToggleWidget );
-
-/* Methods */
-
-/**
- * Handles mouse down events.
- *
- * @method
- * @param {jQuery.Event} e Mouse down event
- */
-OO.ui.ToggleSwitchWidget.prototype.onClick = function ( e ) {
-       if ( !this.disabled && e.which === 1 ) {
-               this.setValue( !this.value );
-       }
-};
-}() );
diff --git a/resources/oojs/oojs-ui.svg.css b/resources/oojs/oojs-ui.svg.css
deleted file mode 100644 (file)
index 185bcf0..0000000
+++ /dev/null
@@ -1,1880 +0,0 @@
-/*!
- * OOjs UI v0.1.0-pre-svg (a290673bbd)
- * https://www.mediawiki.org/wiki/OOjs_UI
- *
- * Copyright 2011–2014 OOjs Team and other contributors.
- * Released under the MIT license
- * http://oojs.mit-license.org
- *
- * Date: Wed Feb 12 2014 13:52:08 GMT-0800 (PST)
- */
-/*csslint vendor-prefix:false */
-
-/* Textures */
-
-.oo-ui-texture-pending {
-       /* @embed */
-       background-image: url(images/textures/pending.gif);
-}
-
-.oo-ui-texture-transparency {
-       /* @embed */
-       background-image: url(images/textures/transparency.png);
-}
-
-/* Animation */
-
-@-webkit-keyframes oo-ui-zoom-in {
-       from { -webkit-transform: scale(0.5); }
-       to { -webkit-transform: scale(1); }
-}
-
-@-moz-keyframes oo-ui-zoom-in {
-       from { -moz-transform: scale(0.5); }
-       to { -moz-transform: scale(1); }
-}
-
-@-o-keyframes oo-ui-zoom-in {
-       from { -o-transform: scale(0.5); }
-       to { -o-transform: scale(1); }
-}
-
-@keyframes oo-ui-zoom-in {
-       from { transform: scale(0.5); }
-       to { transform: scale(1); }
-}
-
-@-webkit-keyframes oo-ui-fade-in {
-       from { opacity: 0; }
-       to { opacity: 1; }
-}
-
-@-moz-keyframes oo-ui-fade-in {
-       from { opacity: 0; }
-       to { opacity: 1; }
-}
-
-@-o-keyframes oo-ui-fade-in {
-       from { opacity: 0; }
-       to { opacity: 1; }
-}
-
-@keyframes oo-ui-fade-in {
-       from { opacity: 0; }
-       to { opacity: 1; }
-}
-
-/* RTL Definitions */
-
-/* @noflip */
-.oo-ui-rtl {
-       direction: rtl;
-}
-/* @noflip */
-.oo-ui-ltr {
-       direction: ltr;
-}
-.oo-ui-dialog {
-       position: fixed;
-       top: 0;
-       right: 0;
-       bottom: 0;
-       left: 0;
-       padding: 1em;
-       line-height: 1em;
-       background-color: #fff;
-       background-color: rgba(255,255,255,0.5);
-       -webkit-animation: oo-ui-fade-in 250ms ease-in-out 0 1 normal;
-       -moz-animation: oo-ui-fade-in 250ms ease-in-out 0 1 normal;
-       -o-animation: oo-ui-fade-in 250ms ease-in-out 0 1 normal;
-       animation: oo-ui-fade-in 250ms ease-in-out 0 1 normal;
-}
-
-.oo-ui-dialog-closing {
-       -webkit-animation: oo-ui-fade-in 250ms ease-in-out 0 1 reverse;
-       -moz-animation: oo-ui-fade-in 250ms ease-in-out 0 1 reverse;
-       -o-animation: oo-ui-fade-in 250ms ease-in-out 0 1 reverse;
-       animation: oo-ui-fade-in 250ms ease-in-out 0 1 reverse;
-}
-
-.oo-ui-dialog .oo-ui-window-frame {
-       position: fixed;
-       top: 1em;
-       right: 0;
-       bottom: 1em;
-       left: 0;
-       margin: auto;
-       width: 800px;
-       min-height: 12em;
-       max-height: 600px;
-       background-color: #fff;
-       border: solid 1px #ccc;
-       border-radius: 0.5em;
-       box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
-       overflow: hidden;
-       -webkit-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 normal;
-       -moz-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 normal;
-       -o-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 normal;
-       animation: oo-ui-zoom-in 250ms ease-in-out 0 1 normal;
-}
-
-.oo-ui-dialog .oo-ui-window-frame.oo-ui-window-frame-small {
-       max-width: 600px;
-       max-height: 400px;
-}
-
-.oo-ui-dialog-closing .oo-ui-window-frame {
-       -webkit-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 reverse;
-       -moz-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 reverse;
-       -o-animation: oo-ui-zoom-in 250ms ease-in-out 0 1 reverse;
-       animation: oo-ui-zoom-in 250ms ease-in-out 0 1 reverse;
-}
-
-.oo-ui-dialog .oo-ui-frame {
-       width: 100%;
-       height: 100%;
-}
-
-.oo-ui-dialog-content .oo-ui-window-head,
-.oo-ui-dialog-content .oo-ui-window-body,
-.oo-ui-dialog-content .oo-ui-window-foot {
-       position: absolute;
-       left: 0;
-       right: 0;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       overflow: hidden;
-}
-
-.oo-ui-dialog-content .oo-ui-window-head {
-       top: 0;
-       height: 3.8em;
-       padding: 0.5em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot {
-       bottom: 0;
-       height: 4.8em;
-       padding: 1em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-body {
-       box-shadow: 0 0 0.66em rgba(0,0,0,0.25);
-       top: 3.8em;
-       bottom: 4.8em;
-}
-
-.oo-ui-dialog-content-footless .oo-ui-window-body {
-       bottom: 0;
-}
-
-.oo-ui-dialog-content-footless .oo-ui-window-foot {
-       display: none;
-}
-
-.oo-ui-dialog-content .oo-ui-window-icon {
-       width: 2.4em;
-       height: 2.8em;
-       line-height: 2.8em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-title {
-       line-height: 2.8em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed {
-       float: left;
-       margin: 0.125em 0.25em;
-}
-
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary,
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive,
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed.oo-ui-flaggableElement-destructive {
-       float: right;
-}
-
-.oo-ui-dialog-content .oo-ui-window-closeButton {
-       float: right;
-       margin: 0.25em 0.25em;
-}
-
-/* OO.ui.ButtonedElement */
-
-a.oo-ui-buttonedElement-button {
-       color: #333;
-       cursor: pointer;
-       display: inline-block;
-       vertical-align: middle;
-       -webkit-touch-callout: none;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-}
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       display: none;
-}
-
-.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
-.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       opacity: 0.8;
-       display: inline-block;
-       vertical-align: middle;
-       background-position: center center;
-       background-repeat: no-repeat;
-       width: 1.9em;
-       height: 1.9em;
-}
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       margin-left: 0;
-}
-
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator {
-       margin-right: -0.75em;
-}
-
-.oo-ui-buttonedElement-frameless {
-       display: inline-block;
-       position: relative;
-       -webkit-transition: opacity 200ms;
-       -moz-transition: opacity 200ms;
-       -o-transition: opacity 200ms;
-       transition: opacity 200ms;
-}
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-iconedElement-icon,
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-iconedElement-icon {
-       opacity: 1;
-}
-
-.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       opacity: 0.2;
-}
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-       display: inline-block;
-       vertical-align: middle;
-       margin-left: 0.25em;
-       color: #333;
-}
-
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-labeledElement-label,
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-labeledElement-label {
-       color: #000;
-}
-
-.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-       color: #ccc;
-}
-
-/* OO.ui.ButtonWidget */
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-       display: inline-block;
-       font-size: 1em;
-       margin: 0.1em 0;
-       padding: 0.2em 0.8em;
-       border-radius: 0.3em;
-       vertical-align: top;
-       text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
-       box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
-       text-align: center;
-
-       /* Animation */
-       -webkit-transition: border-color 100ms;
-       -moz-transition: border-color 100ms;
-       -o-transition: border-color 100ms;
-       transition: border-color 100ms;
-
-       /* Gray */
-       border: 1px #c9c9c9 solid;
-       background-color: #dddddd;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#ffffff, endColorstr=#dddddd
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#ffffff), color-stop(100%,#dddddd)
-       );
-       background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:focus {
-       border-color: #aaa;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:active,
-.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active .oo-ui-buttonedElement-button {
-       box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
-       color: black;
-
-       /* Gray */
-       border-color: #c9c9c9;
-       background-color: #dddddd;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#dddddd, endColorstr=#ffffff
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#dddddd), color-stop(100%,#ffffff)
-       );
-       background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       margin-left: -0.5em;
-       margin-right: -0.5em;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-iconedElement.oo-ui-labeledElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       margin-left: -0.5em;
-       margin-right: 0;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-       display: inline-block;
-       vertical-align: middle;
-       line-height: 1.9em;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-destructive .oo-ui-buttonedElement-button {
-       /* Red text */
-       color: #d45353;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button {
-       /* Green */
-       border: solid 1px #b8d892;
-       background-color: #f0fbe1;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#f0fbe1, endColorstr=#c3e59a
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#f0fbe1), color-stop(100%,#c3e59a)
-       );
-       background-image: -webkit-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-       background-image: -moz-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-       background-image: -ms-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-       background-image: -o-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-       background-image: linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:focus {
-       border-color: #adcb89;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:active,
-.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button {
-       /* Green */
-       border: solid 1px #b8d892;
-       background-color: #c3e59a;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#c3e59a, endColorstr=#f0fbe1
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#c3e59a), color-stop(100%,#f0fbe1)
-       );
-       background-image: -webkit-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-       background-image: -moz-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-       background-image: -ms-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-       background-image: -o-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-       background-image: linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
-       /* Blue */
-       border: solid 1px #a6cee1;
-       background-color: #eaf4fa;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#eaf4fa, endColorstr=#b0d9ee
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#eaf4fa), color-stop(100%,#b0d9ee)
-       );
-       background-image: -webkit-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-       background-image: -moz-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-       background-image: -ms-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-       background-image: -o-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-       background-image: linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:focus {
-       border-color: #9dc2d4;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:active,
-.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
-       /* Blue */
-       border: solid 1px #a6cee1;
-       background-color: #b0d9ee;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#b0d9ee, endColorstr=#eaf4fa
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#b0d9ee), color-stop(100%,#eaf4fa)
-       );
-       background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:active,
-.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active.oo-ui-widget-disabled .oo-ui-buttonedElement-button:active {
-       opacity: 0.5;
-       cursor: default;
-       box-shadow: none;
-       color: #333;
-       background: #eee;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:focus {
-       border-color: #ccc;
-       box-shadow: none;
-}
-
-/* OO.ui.LabeledElement */
-
-.oo-ui-labeledElement-label {
-       display: block;
-}
-
-.oo-ui-clippableElement-clippable {
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-}
-.oo-ui-frame {
-       margin: 0;
-       padding: 0;
-}
-
-.oo-ui-frame-body {
-       margin: 0;
-       padding: 0;
-       background: none;
-}
-
-.oo-ui-frame-content {
-       font-family: sans-serif;
-       font-size: 0.8em;
-}
-/* OO.ui.GridLayout */
-/* OO.ui.PanelLayout */
-
-.oo-ui-gridLayout,
-.oo-ui-panelLayout {
-       position: absolute;
-       top: 0;
-       left: 0;
-       right: 0;
-       bottom: 0;
-}
-
-.oo-ui-panelLayout-scrollable {
-       overflow-y: auto;
-}
-
-.oo-ui-panelLayout-padded {
-       padding: 2em;
-}
-
-/* OO.ui.FieldsetLayout */
-
-.oo-ui-fieldsetLayout {
-       border: none;
-       margin: 0;
-       padding: 0;
-}
-
-.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
-       margin-top: 2em;
-}
-
-.oo-ui-fieldsetLayout-labeled {
-       margin-top: -0.75em;
-}
-
-.oo-ui-fieldsetLayout > legend.oo-ui-labeledElement-label {
-       font-size: 1.5em;
-       margin-bottom: 0.5em;
-}
-
-.oo-ui-fieldsetLayout-decorated > legend.oo-ui-labeledElement-label {
-       padding-left: 1.75em;
-       background-position: left center;
-       background-repeat: no-repeat;
-}
-
-/* OO.ui.BookletLayout */
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
-       padding: 1.5em;
-       width: 100%;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
-       overflow-y: auto;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
-       padding: 2em;
-}
-
-.oo-ui-bookletLayout-outlinePanel {
-       border-right: solid 1px #ddd;
-}
-
-.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
-       position: absolute;
-       top: 0;
-       left: 0;
-       right: 0;
-       bottom: 3em;
-       overflow-y: auto;
-}
-
-.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
-       position: absolute;
-       bottom: 0;
-       left: 0;
-       right: 0;
-       box-shadow: 0 0 0.25em rgba(0,0,0,0.25);
-}
-
-.oo-ui-stackLayout > .oo-ui-panelLayout {
-       display: none;
-}
-
-.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
-       display: block;
-       position: relative;
-       margin-bottom: 1em;
-       box-shadow: 0 0 0.5em rgba(0,0,0,0.25);
-}
-
-.oo-ui-stackLayout-continuous > .oo-ui-panelLayout:last-child {
-       margin-bottom: 0;
-}
-/* OO.ui.PopupTool */
-
-.oo-ui-popupTool .oo-ui-popupWidget {
-       margin-left: 1.25em;
-       font-size: 0.8em;
-}
-
-.oo-ui-popupTool .oo-ui-popupWidget-popup,
-.oo-ui-popupTool .oo-ui-popupWidget-tail {
-       z-index: 4;
-}
-.oo-ui-toolbar {
-       clear: both;
-}
-
-.oo-ui-toolbar-bar {
-       border-bottom: solid 1px #ccc;
-       background-color: white;
-       /* @embed */
-       background-image: url(images/fade-up.png);
-       background-position: left bottom;
-       background-repeat: repeat-x;
-       padding-bottom: 1px;
-       line-height: 1em;
-}
-
-.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
-       border: none;
-       background: none;
-}
-
-.oo-ui-toolbar-bottom .oo-ui-toolbar-bar {
-       position: absolute;
-}
-
-.oo-ui-toolbar-actions {
-       float: right;
-}
-
-.oo-ui-toolbar-tools {
-       float: left;
-}
-
-.oo-ui-toolbar-tools,
-.oo-ui-toolbar-actions,
-.oo-ui-toolbar-shadow {
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       -o-user-select: none;
-       user-select: none;
-}
-
-.oo-ui-toolbar-actions .oo-ui-popupWidget {
-       -webkit-touch-callout: default;
-       -webkit-user-select: all;
-       -moz-user-select: all;
-       -ms-user-select: all;
-       user-select: all;
-}
-
-.oo-ui-toolbar-shadow {
-       /* @embed */
-       background-image: url(images/toolbar-shadow.png);
-       background-position: left top;
-       background-repeat: repeat-x;
-       position: absolute;
-       bottom: -9px;
-       height: 9px;
-       width: 100%;
-       pointer-events: none;
-       -webkit-transition: opacity 500ms ease-in-out;
-       -moz-transition: opacity 500ms ease-in-out;
-       -o-transition: opacity 500ms ease-in-out;
-       transition: opacity 500ms ease-in-out;
-       opacity: 0.125;
-}
-/* OO.ui.ToolGroup */
-
-.oo-ui-toolGroup {
-       display: inline-block;
-       margin: 0.3em;
-       vertical-align: middle;
-       border-radius: 0.25em;
-       border: solid 1px transparent;
-       -webkit-transition: border-color 300ms;
-       -moz-transition: border-color 300ms;
-       -o-transition: border-color 300ms;
-       transition: border-color 300ms;
-}
-
-.oo-ui-toolGroup:hover {
-       border-color: rgba(0,0,0,0.1);
-}
-
-.oo-ui-toolGroup-empty {
-       display: none;
-}
-
-.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-tool-title {
-       color: #000;
-}
-
-.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       background-position: center center;
-       background-repeat: no-repeat;
-}
-
-/* OO.ui.BarToolGroup */
-
-.oo-ui-barToolGroup > .oo-ui-iconedElement-icon,
-.oo-ui-barToolGroup > .oo-ui-iconedElement-label {
-       display: none;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool {
-       display: inline-block;
-       position: relative;
-       vertical-align: top;
-       margin: -1px 0 -1px -1px;
-       border: solid 1px transparent;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-link {
-       display: block;
-       height: 1.5em;
-       padding: 0.25em;
-       cursor: pointer;
-}
-
-.oo-ui-barToolGroup
-       .oo-ui-tool-active:not(.oo-ui-widget-disabled) +
-       .oo-ui-tool-active:not(.oo-ui-widget-disabled)
-{
-       border-left-color: rgba(0,0,0,0.1);
-}
-
-.oo-ui-barToolGroup .oo-ui-tool:first-child {
-       border-top-left-radius: 0.25em;
-       border-bottom-left-radius: 0.25em;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool:last-child {
-       margin-right: -1px;
-       border-top-right-radius: 0.25em;
-       border-bottom-right-radius: 0.25em;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) {
-       border-color: rgba(0,0,0,0.2);
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled) {
-       border-color: rgba(0,0,0,0.2);
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       display: block;
-       height: 1.5em;
-       width: 1.5em;
-       opacity: 0.8;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
-       display: none;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
-       cursor: default;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 0.2;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 0.8;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 1;
-}
-
-.oo-ui-barToolGroup .oo-ui-tool-title {
-       display: none;
-}
-
-/* OO.ui.PopupToolGroup */
-
-.oo-ui-popupToolGroup {
-       position: relative;
-       height: 2em;
-       min-width: 2.5em;
-}
-
-.oo-ui-popupToolGroup.oo-ui-indicatedElement.oo-ui-iconedElement {
-       min-width: 3.5em;
-}
-
-.oo-ui-popupToolGroup-handle {
-       display: block;
-       cursor: pointer;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator,
-.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
-       position: absolute;
-       top: 0;
-       width: 2em;
-       height: 2em;
-       background-position: center center;
-       background-repeat: no-repeat;
-       opacity: 0.8;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator {
-       right: 0;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
-       left: 0.25em;
-}
-
-.oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-       line-height: 2.6em;
-       font-size: 0.8em;
-       margin: 0 1em;
-}
-
-.oo-ui-popupToolGroup.oo-ui-iconedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-       margin-left: 3.25em;
-}
-
-.oo-ui-popupToolGroup.oo-ui-indicatedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-       margin-right: 2.25em;
-}
-
-.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
-       display: none;
-       position: absolute;
-       top: 2em;
-       left: -1px;
-       z-index: 4;
-       border: solid 1px #ccc;
-       background-color: white;
-       box-shadow: 0 0.25em 1em rgba(0,0,0,0.25);
-}
-
-.oo-ui-popupToolGroup .oo-ui-toolGroup-tools .oo-ui-iconedElement-icon {
-       background-repeat: no-repeat;
-       background-position: center center;
-}
-
-.oo-ui-popupToolGroup-active:not(.oo-ui-widget-disabled) > .oo-ui-toolGroup-tools {
-       display: block;
-}
-
-.oo-ui-popupToolGroup-active:not(.oo-ui-widget-disabled) {
-       border-bottom-left-radius: 0;
-       border-bottom-right-radius: 0;
-}
-
-.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       display: inline-block;
-       vertical-align: middle;
-       height: 2em;
-       width: 2em;
-       margin-right: 0.5em;
-}
-
-.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
-       display: inline-block;
-       vertical-align: middle;
-       line-height: 2em;
-       font-size: 0.8em;
-}
-
-.oo-ui-popupToolGroup .oo-ui-tool-accel {
-       display: none;
-}
-
-/* OO.ui.ListToolGroup */
-
-.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
-       padding: 0.25em;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool {
-       display: inline-block;
-       width: 100%;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       border: solid 1px transparent;
-       margin: -1px 0;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool-link {
-       display: block;
-       cursor: pointer;
-       white-space: nowrap;
-       padding-right: 0.5em;
-}
-
-.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
-       border-color: rgba(0,0,0,0.2);
-}
-
-.oo-ui-listToolGroup
-       .oo-ui-tool-active:not(.oo-ui-widget-disabled) +
-       .oo-ui-tool-active:not(.oo-ui-widget-disabled)
-{
-       border-top-color: rgba(0,0,0,0.1);
-}
-
-.oo-ui-listToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) {
-       border-color: rgba(0,0,0,0.2);
-}
-
-.oo-ui-listToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled) {
-       border-color: rgba(0,0,0,0.2);
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
-       cursor: default;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
-       color: #ccc;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 0.2;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 0.8;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 1;
-}
-
-/* OO.ui.MenuToolGroup */
-
-.oo-ui-menuToolGroup {
-       border-color: rgba(0,0,0,0.1);
-}
-
-.oo-ui-menuToolGroup:hover {
-       border-color: rgba(0,0,0,0.2);
-}
-
-.oo-ui-menuToolGroup.oo-ui-popupToolGroup-active {
-       border-color: rgba(0,0,0,0.25);
-}
-
-.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
-       min-width: 8em;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool {
-       display: block;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-link {
-       display: block;
-       cursor: pointer;
-       white-space: nowrap;
-       padding: 0.25em 1em 0.25em 0.25em;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       background-image: none;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       /* @embed */
-       background-image: url(images/icons/check.png);
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool:hover {
-       background-color: #e1f3ff;
-}
-
-/* Common */
-
-.oo-ui-barToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled),
-.oo-ui-listToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled),
-.oo-ui-popupToolGroup-active:not(.oo-ui-widget-disabled) {
-       /* @embed */
-       background-image: url(images/fade-down.png);
-       background-position: left top;
-       background-repeat: repeat-x;
-       box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
-}
-/* OO.ui.ButtonWidget */
-
-.oo-ui-buttonWidget {
-       display: inline-block;
-       vertical-align: middle;
-}
-
-/* OO.ui.PopupButtonWidget */
-
-.oo-ui-popupButtonWidget {
-       position: relative;
-}
-
-.oo-ui-popupButtonWidget .oo-ui-popupWidget {
-       position: absolute;
-       left: 1em;
-       cursor: auto;
-}
-
-/* OO.ui.ButtonGroupWidget */
-
-.oo-ui-buttonGroupWidget {
-       display: inline-block;
-       border-radius: 0.3em;
-       box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-       border-radius: 0;
-       margin-bottom: -1px;
-       margin-left: -1px;
-       box-shadow: none;
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:first-child .oo-ui-buttonedElement-button {
-       border-bottom-left-radius: 0.3em;
-       border-top-left-radius: 0.3em;
-       margin-left: 0;
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:last-child .oo-ui-buttonedElement-button {
-       border-bottom-right-radius: 0.3em;
-       border-top-right-radius: 0.3em;
-}
-
-/* OO.ui.SelectWidget */
-
-.oo-ui-selectWidget {
-       list-style: none;
-       margin: 0;
-       padding: 0;
-}
-
-/* OO.ui.OptionWidget */
-
-.oo-ui-optionWidget {
-       position: relative;
-       display: block;
-       border: none;
-       list-style: none;
-       margin: 0;
-       padding: 0.5em 2em 0.5em 3em;
-       cursor: pointer;
-}
-
-.oo-ui-optionWidget .oo-ui-labeledElement-label {
-       line-height: 1.5em;
-       white-space: nowrap;
-       text-overflow: ellipsis;
-       overflow: hidden;
-}
-
-.oo-ui-optionWidget-highlighted {
-       background-color: #e1f3ff;
-}
-
-.oo-ui-optionWidget-selected {
-       background-color: #a7dcff;
-}
-
-.oo-ui-optionWidget.oo-ui-widget-disabled {
-       cursor: default;
-}
-
-.oo-ui-optionWidget .oo-ui-iconedElement-icon,
-.oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
-       position: absolute;
-       top: 50%;
-       width: 2em;
-       height: 2em;
-       margin-top: -1em;
-       background-repeat: no-repeat;
-       background-position: center center;
-}
-
-.oo-ui-optionWidget .oo-ui-iconedElement-icon {
-       left: 0.5em;
-}
-
-.oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
-       right: 0.5em;
-}
-
-/* OO.ui.OutlineItemWidget */
-
-.oo-ui-outlineItemWidget {
-       position: relative;
-       padding: 0.75em 0.75em 0.75em 3.5em;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-       cursor: pointer;
-       font-size: 1.1em;
-}
-
-.oo-ui-outlineItemWidget-level-1 {
-       padding-left: 5em;
-}
-
-.oo-ui-outlineItemWidget-level-2 {
-       padding-left: 6.5em;
-}
-
-.oo-ui-outlineItemWidget.oo-ui-optionWidget-selected {
-       background-color: #a7dcff;
-       text-shadow: 0 1px 1px rgba(255,255,255,0.5);
-}
-
-.oo-ui-outlineItemWidget-level-0 .oo-ui-iconedElement-icon {
-       left: 1em;
-}
-
-.oo-ui-outlineItemWidget-level-1 .oo-ui-iconedElement-icon {
-       left: 2.5em;
-}
-
-.oo-ui-outlineItemWidget-level-2 .oo-ui-iconedElement-icon {
-       left: 4em;
-}
-
-/* OO.ui.OutlineControlsWidget */
-
-.oo-ui-outlineControlsWidget {
-       height: 3em;
-       background-color: #fff;
-}
-
-.oo-ui-outlineControlsWidget-adders,
-.oo-ui-outlineControlsWidget-movers {
-       float: left;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       height: 3em;
-       padding: 0.5em;
-}
-
-.oo-ui-outlineControlsWidget-adders {
-       float: left;
-}
-.oo-ui-outlineControlsWidget-movers {
-       float: right;
-}
-
-.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget {
-       float: left;
-}
-
-.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
-       float: right;
-}
-
-.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget:first-child,
-.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget:first-child:hover {
-       opacity: 0.25;
-       cursor: default;
-}
-
-/* OO.ui.InputLabelWidget */
-
-.oo-ui-inputLabelWidget {
-       padding: 0.5em 0;
-}
-
-/* OO.ui.TextInputWidget */
-
-.oo-ui-textInputWidget {
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       width: 20em;
-       position: relative;
-}
-
-.oo-ui-textInputWidget input,
-.oo-ui-textInputWidget input:focus[readonly],
-.oo-ui-widget-disabled.oo-ui-textInputWidget input:focus,
-.oo-ui-textInputWidget textarea,
-.oo-ui-textInputWidget textarea:focus[readonly],
-.oo-ui-widget-disabled.oo-ui-textInputWidget textarea:focus {
-       display: inline-block;
-       font-size: 1em;
-       font-family: sans-serif;
-       background-color: #f7f7f7;
-       border: solid 1px #ccc;
-       box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
-       padding: 0.5em;
-       border-radius: 0.25em;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       width: 100%;
-       resize: none;
-
-       /* Animation */
-       -webkit-transition: border-color 200ms, box-shadow 200ms, background-color 200ms;
-       -moz-transition: border-color 200ms, box-shadow 200ms, background-color 200ms;
-       -o-transition: border-color 200ms, box-shadow 200ms, background-color 200ms;
-       transition: border-color 200ms, box-shadow 200ms, background-color 200ms;
-}
-
-.oo-ui-textInputWidget-pending input,
-.oo-ui-textInputWidget-pending textarea {
-       background-color: transparent;
-}
-
-.oo-ui-textInputWidget input:focus,
-.oo-ui-textInputWidget textarea:focus {
-       outline: none;
-       border-color: #a7dcff;
-       box-shadow: 0 0 0.3em #a7dcff, 0 0 0 white;
-       background-color: #fff;
-}
-
-.oo-ui-textInputWidget input[readonly],
-.oo-ui-textInputWidget textarea[readonly] {
-       color: #777;
-       text-shadow: 0 1px 1px #fff;
-}
-
-.oo-ui-widget-disabled.oo-ui-textInputWidget input,
-.oo-ui-widget-disabled.oo-ui-textInputWidget input:focus,
-.oo-ui-widget-disabled.oo-ui-textInputWidget textarea,
-.oo-ui-widget-disabled.oo-ui-textInputWidget textarea:focus {
-       color: #ccc;
-       text-shadow: 0 1px 1px #fff;
-}
-
-.oo-ui-textInputWidget-decorated input,
-.oo-ui-textInputWidget-decorated textarea {
-       padding-left: 2em;
-}
-
-.oo-ui-textInputWidget-icon {
-       position: absolute;
-       top: 0;
-       left: 0;
-       width: 2em;
-       height: 100%;
-       background-position: right center;
-       background-repeat: no-repeat;
-}
-
-/* OO.ui.CheckboxWidget */
-.oo-ui-checkboxWidget .oo-ui-labeledElement-label {
-       display: inline-block;
-       vertical-align: middle;
-       padding-left: 0.5em;
-}
-
-.oo-ui-checkboxWidget input {
-       vertical-align: middle;
-}
-
-.oo-ui-checkboxWidget.oo-ui-widget-disabled .oo-ui-labeledElement-label {
-       opacity: 0.5;
-}
-
-/* OO.ui.MenuWidget */
-
-.oo-ui-menuWidget {
-       position: absolute;
-       background: #fff;
-       margin-top: -1px;
-       border: solid 1px #ccc;
-       border-radius: 0 0 0.25em 0.25em;
-       box-shadow: 0 0.15em 1em 0 rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-menuWidget input {
-       position: absolute;
-       width: 0;
-       height: 0;
-       overflow: hidden;
-       opacity: 0;
-}
-
-/* OO.ui.MenuItemWidget */
-
-.oo-ui-menuItemWidget {
-       position: relative;
-}
-
-.oo-ui-menuItemWidget .oo-ui-iconedElement-icon {
-       display: none;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconedElement-icon {
-       display: block;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
-       background-color: transparent;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted {
-       background-color: #e1f3ff;
-}
-
-/* OO.ui.MenuSectionItemWidget */
-
-.oo-ui-menuSectionItemWidget {
-       padding: 0.33em 0.75em;
-       color: #888;
-       cursor: default;
-}
-
-/* OO.ui.ButtonSelectWidget */
-
-.oo-ui-buttonSelectWidget {
-       display: inline-block;
-       border-radius: 0.3em;
-       box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
-}
-
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
-       border-radius: 0;
-       margin-left: -1px;
-       box-shadow: none;
-}
-
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonedElement-button {
-       border-bottom-left-radius: 0.3em;
-       border-top-left-radius: 0.3em;
-       margin-left: 0;
-}
-
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonedElement-button {
-       border-bottom-right-radius: 0.3em;
-       border-top-right-radius: 0.3em;
-}
-
-/* OO.ui.ButtonOptionWidget */
-
-.oo-ui-buttonOptionWidget {
-       display: inline-block;
-       padding: 0;
-       background-color: transparent;
-}
-
-.oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
-       position: relative;
-       height: 1.9em;
-}
-
-.oo-ui-buttonOptionWidget.oo-ui-iconedElement .oo-ui-iconedElement-icon,
-.oo-ui-buttonOptionWidget.oo-ui-indicatedElement .oo-ui-indicatedElement-indicator {
-       position: static;
-       display: inline-block;
-       vertical-align: middle;
-       height: 1.9em;
-       margin-top: 0;
-}
-
-/* OO.ui.PopupWidget */
-
-.oo-ui-popupWidget-popup {
-       position: absolute;
-       overflow: hidden;
-       border: solid 1px #ccc;
-       border-radius: 0.25em;
-       background-color: #fff;
-       box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
-}
-
-.oo-ui-popupWidget-tail {
-       display: none;
-}
-
-.oo-ui-popupWidget-tailed .oo-ui-popupWidget-popup {
-       margin-top: 7px;
-}
-
-.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
-       display: block;
-       position: absolute;
-       /* @embed */
-       background-image: url(images/tail.svg);
-       background-repeat: no-repeat;
-       width: 15px;
-       height: 8px;
-       margin-left: -7px;
-}
-
-.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
-       -webkit-transition: width 100ms, height 100ms, left 100ms;
-       -moz-transition: width 100ms, height 100ms, left 100ms;
-       -o-transition: width 100ms, height 100ms, left 100ms;
-       transition: width 100ms, height 100ms, left 100ms;
-       -webkit-transition-timing-function: ease-in-out;
-       -moz-transition-timing-function: ease-in-out;
-       -o-transition-timing-function: ease-in-out;
-       transition-timing-function: ease-in-out;
-}
-
-.oo-ui-popupWidget-head {
-       height: 2.5em;
-       -webkit-touch-callout: none;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-}
-
-.oo-ui-popupWidget-head .oo-ui-buttonWidget {
-       float: right;
-       margin: 0.25em;
-}
-
-.oo-ui-popupWidget-head .oo-ui-labeledElement-label {
-       float: left;
-       margin: 0.75em 1em;
-       cursor: default;
-}
-
-.oo-ui-popupWidget-body {
-       box-shadow: 0 0 0.66em rgba(0,0,0,0.25);
-}
-
-/* OO.ui.SearchWidget */
-
-.oo-ui-searchWidget-query {
-       position: absolute;
-       top: 0;
-       left: 0;
-       right: 0;
-       height: 4em;
-       padding: 0 1em;
-       box-shadow: 0 0 0.5em rgba(0,0,0,0.2);
-}
-
-.oo-ui-searchWidget-query .oo-ui-textInputWidget {
-       width: 100%;
-       margin: 0.75em 0;
-}
-
-.oo-ui-searchWidget-results {
-       position: absolute;
-       top: 4em;
-       bottom: 0;
-       left: 0;
-       right: 0;
-       padding: 1em;
-       overflow-x: hidden;
-       overflow-y: auto;
-       line-height: 0;
-}
-
-/* OO.ui.ToggleSwitchWidget */
-
-.oo-ui-toggleSwitchWidget {
-       position: relative;
-       display: inline-block;
-       vertical-align: middle;
-       height: 2em;
-       width: 3em;
-       border-radius: 1em;
-       overflow: hidden;
-       box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
-       border: solid 1px #ccc;
-       cursor: pointer;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       -webkit-transform: translateZ(0px);
-       -moz-transform: translateZ(0px);
-       -ms-transform: translateZ(0px);
-       -o-transform: translateZ(0px);
-       transform: translateZ(0px);
-
-       /* Gray */
-       background-color: #dddddd;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#dddddd, endColorstr=#ffffff
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#dddddd), color-stop(100%,#ffffff)
-       );
-       background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
-}
-
-.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
-       opacity: 0.5;
-}
-
-.oo-ui-toggleSwitchWidget-grip {
-       -webkit-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-       -moz-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-       -o-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-       transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-}
-
-.oo-ui-toggleSwitchWidget-grip {
-       position: absolute;
-       display: block;
-       top: 0.25em;
-       left: 0.25em;
-       width: 1.5em;
-       height: 1.5em;
-       border-radius: 1em;
-       box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-
-       /* Gray */
-       border: 1px #c9c9c9 solid;
-       background-color: #ffffff;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#ffffff, endColorstr=#dddddd
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#ffffff), color-stop(100%,#dddddd)
-       );
-       background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
-}
-
-.oo-ui-toggleSwitchWidget:not(.oo-ui-widget-disabled):hover,
-.oo-ui-toggleSwitchWidget:not(.oo-ui-widget-disabled):hover .oo-ui-toggleSwitchWidget-grip {
-       border-color: #aaa;
-}
-
-.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
-       left: 1.25em;
-       margin-left: -2px;
-}
-
-.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
-       left: 0.25em;
-       margin-left: 0;
-}
-
-.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-on {
-       position: absolute;
-       top: 0;
-       bottom: 0;
-       right: 0;
-       left: 0;
-       border-radius: 1em;
-       box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
-       cursor: pointer;
-       -webkit-touch-callout: none;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-
-       -webkit-transition: opacity 200ms ease-in-out;
-       -moz-transition: opacity 200ms ease-in-out;
-       -o-transition: opacity 200ms ease-in-out;
-       transition: opacity 200ms ease-in-out;
-
-       /* Blue */
-       background-color: #eaf4fa;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#b0d9ee, endColorstr=#eaf4fa
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#b0d9ee), color-stop(100%,#eaf4fa)
-       );
-       background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-}
-
-.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-on {
-       opacity: 1;
-}
-
-.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-on {
-       opacity: 0;
-}
-.oo-ui-window-head {
-       -webkit-touch-callout: none;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-}
-
-.oo-ui-window-body {
-       padding: 0 0.75em;
-}
-
-.oo-ui-window-icon {
-       float: left;
-       width: 2em;
-       height: 2em;
-       line-height: 2em;
-       margin-right: 0.5em;
-       background-position: right center;
-       background-repeat: no-repeat;
-}
-
-.oo-ui-window-title {
-       float: left;
-       line-height: 2em;
-       color: #333;
-       white-space: nowrap;
-       cursor: default;
-}
-
-.oo-ui-window-overlay {
-       font-family: sans-serif;
-       line-height: 1.5em;
-       font-size: 1em;
-       position: absolute;
-       top: 0;
-       left: 0;
-}
-/* Icons */
-
-.oo-ui-icon-add-item {
-       /* @embed */
-       background-image: url(images/icons/add-item.png);
-}
-
-.oo-ui-icon-advanced {
-       /* @embed */
-       background-image: url(images/icons/advanced.png);
-}
-
-.oo-ui-icon-alert {
-       /* @embed */
-       background-image: url(images/icons/alert.png);
-}
-
-.oo-ui-icon-check {
-       /* @embed */
-       background-image: url(images/icons/check.png);
-}
-
-.oo-ui-icon-clear {
-       /* @embed */
-       background-image: url(images/icons/clear.png);
-}
-
-.oo-ui-icon-close {
-       /* @embed */
-       background-image: url(images/icons/close.png);
-}
-
-.oo-ui-icon-code {
-       /* @embed */
-       background-image: url(images/icons/code.png);
-}
-
-.oo-ui-icon-collapse {
-       /* @embed */
-       background-image: url(images/icons/collapse.png);
-}
-
-.oo-ui-icon-comment {
-       /* @embed */
-       background-image: url(images/icons/comment.png);
-}
-
-.oo-ui-icon-expand {
-       /* @embed */
-       background-image: url(images/icons/expand.png);
-}
-
-.oo-ui-icon-help {
-       /* @embed */
-       background-image: url(images/icons/help.png);
-}
-
-.oo-ui-icon-link {
-       /* @embed */
-       background-image: url(images/icons/link.png);
-}
-
-.oo-ui-icon-menu {
-       /* @embed */
-       background-image: url(images/icons/menu.png);
-}
-
-.oo-ui-icon-next {
-       /* @embed */
-       background-image: url(images/icons/move-ltr.png);
-}
-
-.oo-ui-icon-picture {
-       /* @embed */
-       background-image: url(images/icons/picture.png);
-}
-
-.oo-ui-icon-previous {
-       /* @embed */
-       background-image: url(images/icons/move-rtl.png);
-}
-
-.oo-ui-icon-redo {
-       /* @embed */
-       background-image: url(images/icons/arched-arrow-ltr.png);
-}
-
-.oo-ui-icon-remove {
-       /* @embed */
-       background-image: url(images/icons/remove.png);
-}
-
-.oo-ui-icon-search {
-       /* @embed */
-       background-image: url(images/icons/search.png);
-}
-
-.oo-ui-icon-settings {
-       /* @embed */
-       background-image: url(images/icons/settings.png);
-}
-
-.oo-ui-icon-tag {
-       /* @embed */
-       background-image: url(images/icons/tag.png);
-}
-
-.oo-ui-icon-undo {
-       /* @embed */
-       background-image: url(images/icons/arched-arrow-rtl.png);
-}
-
-.oo-ui-icon-window {
-       /* @embed */
-       background-image: url(images/icons/window.png);
-}
-
-/* Indicators */
-
-.oo-ui-indicator-down {
-       /* @embed */
-       background-image: url(images/indicators/down.png);
-}
-
-.oo-ui-indicator-required {
-       /* @embed */
-       background-image: url(images/indicators/required.png);
-}
-
-.oo-ui-indicator-up {
-       /* @embed */
-       background-image: url(images/indicators/up.png);
-}
-/* Icons */
-
-.oo-ui-icon-add-item {
-       /* @embed */
-       background-image: url(images/icons/add-item.svg);
-}
-
-.oo-ui-icon-advanced {
-       /* @embed */
-       background-image: url(images/icons/advanced.svg);
-}
-
-.oo-ui-icon-alert {
-       /* @embed */
-       background-image: url(images/icons/alert.svg);
-}
-
-.oo-ui-icon-check {
-       /* @embed */
-       background-image: url(images/icons/check.svg);
-}
-
-.oo-ui-icon-clear {
-       /* @embed */
-       background-image: url(images/icons/clear.svg);
-}
-
-.oo-ui-icon-close {
-       /* @embed */
-       background-image: url(images/icons/close.svg);
-}
-
-.oo-ui-icon-code {
-       /* @embed */
-       background-image: url(images/icons/code.svg);
-}
-
-.oo-ui-icon-collapse {
-       /* @embed */
-       background-image: url(images/icons/collapse.svg);
-}
-
-.oo-ui-icon-comment {
-       /* @embed */
-       background-image: url(images/icons/comment.svg);
-}
-
-.oo-ui-icon-expand {
-       /* @embed */
-       background-image: url(images/icons/expand.svg);
-}
-
-.oo-ui-icon-help {
-       /* @embed */
-       background-image: url(images/icons/help.svg);
-}
-
-.oo-ui-icon-link {
-       /* @embed */
-       background-image: url(images/icons/link.svg);
-}
-
-.oo-ui-icon-menu {
-       /* @embed */
-       background-image: url(images/icons/menu.svg);
-}
-
-.oo-ui-icon-next {
-       /* @embed */
-       background-image: url(images/icons/move-ltr.svg);
-}
-
-.oo-ui-icon-picture {
-       /* @embed */
-       background-image: url(images/icons/picture.svg);
-}
-
-.oo-ui-icon-previous {
-       /* @embed */
-       background-image: url(images/icons/move-rtl.svg);
-}
-
-.oo-ui-icon-redo {
-       /* @embed */
-       background-image: url(images/icons/arched-arrow-ltr.svg);
-}
-
-.oo-ui-icon-remove {
-       /* @embed */
-       background-image: url(images/icons/remove.svg);
-}
-
-.oo-ui-icon-search {
-       /* @embed */
-       background-image: url(images/icons/search.svg);
-}
-
-.oo-ui-icon-settings {
-       /* @embed */
-       background-image: url(images/icons/settings.svg);
-}
-
-.oo-ui-icon-tag {
-       /* @embed */
-       background-image: url(images/icons/tag.svg);
-}
-
-.oo-ui-icon-undo {
-       /* @embed */
-       background-image: url(images/icons/arched-arrow-rtl.svg);
-}
-
-.oo-ui-icon-window {
-       /* @embed */
-       background-image: url(images/icons/window.svg);
-}
-
-/* Indicators */
-
-.oo-ui-indicator-down {
-       /* @embed */
-       background-image: url(images/indicators/down.svg);
-}
-
-.oo-ui-indicator-required {
-       /* @embed */
-       background-image: url(images/indicators/required.svg);
-}
-
-.oo-ui-indicator-up {
-       /* @embed */
-       background-image: url(images/indicators/up.svg);
-}