Update OOjs UI to v0.12.9
authorJames D. Forrester <jforrester@wikimedia.org>
Tue, 22 Sep 2015 20:14:56 +0000 (21:14 +0100)
committerJames D. Forrester <jforrester@wikimedia.org>
Tue, 22 Sep 2015 20:14:56 +0000 (21:14 +0100)
Release notes:
 https://git.wikimedia.org/blob/oojs%2Fui.git/v0.12.9/History.md

Change-Id: I8780a6d31a3c9d11e42f0858bb66a39f678bf28f

32 files changed:
composer.json
resources/lib/oojs-ui/i18n/ca.json
resources/lib/oojs-ui/i18n/el.json
resources/lib/oojs-ui/i18n/en-ca.json
resources/lib/oojs-ui/i18n/en.json
resources/lib/oojs-ui/i18n/fa.json
resources/lib/oojs-ui/i18n/it.json
resources/lib/oojs-ui/i18n/ka.json
resources/lib/oojs-ui/i18n/krc.json
resources/lib/oojs-ui/i18n/krl.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/olo.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/pt.json
resources/lib/oojs-ui/i18n/qqq.json
resources/lib/oojs-ui/i18n/vec.json
resources/lib/oojs-ui/i18n/vi.json
resources/lib/oojs-ui/oojs-ui-apex-noimages.css
resources/lib/oojs-ui/oojs-ui-apex.js
resources/lib/oojs-ui/oojs-ui-mediawiki-noimages.css
resources/lib/oojs-ui/oojs-ui-mediawiki.js
resources/lib/oojs-ui/oojs-ui.js
resources/lib/oojs-ui/themes/apex/images/icons/picture.png
resources/lib/oojs-ui/themes/apex/images/icons/picture.svg
resources/lib/oojs-ui/themes/apex/images/icons/table.png
resources/lib/oojs-ui/themes/apex/images/icons/table.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/picture-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/picture-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/picture.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/picture.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/table.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/table.svg

index ed61842..e41b6c7 100644 (file)
@@ -22,7 +22,7 @@
                "liuggio/statsd-php-client": "1.0.16",
                "oyejorge/less.php": "1.7.0.5",
                "mediawiki/at-ease": "1.1.0",
-               "oojs/oojs-ui": "0.12.8.1",
+               "oojs/oojs-ui": "0.12.9",
                "php": ">=5.3.3",
                "psr/log": "1.0.0",
                "wikimedia/assert": "0.2.2",
index 33b0ce0..3077b60 100644 (file)
@@ -12,7 +12,8 @@
                        "Edustus",
                        "Davidpar",
                        "Maceleiro",
-                       "Kippelboy"
+                       "Kippelboy",
+                       "Macofe"
                ]
        },
        "ooui-outline-control-move-down": "Baixa l'element",
@@ -27,6 +28,7 @@
        "ooui-dialog-process-dismiss": "Descarta",
        "ooui-dialog-process-retry": "Torneu-ho a provar",
        "ooui-dialog-process-continue": "Continua",
+       "ooui-selectfile-button-select": "Seleccioneu un fitxer",
        "ooui-selectfile-not-supported": "El tipus de fitxer no és compatible",
        "ooui-selectfile-placeholder": "No s'ha seleccionat cap fitxer",
        "ooui-selectfile-dragdrop-placeholder": "Deixeu-hi anar el fitxer (o feu clic a navega)"
index b3c4845..8538417 100644 (file)
@@ -26,5 +26,5 @@
        "ooui-dialog-process-continue": "Συνέχεια",
        "ooui-selectfile-not-supported": "Επιλογή αρχείου δεν υποστηρίζεται",
        "ooui-selectfile-placeholder": "Κανένα αρχείο δεν είναι επιλεγμένο",
-       "ooui-selectfile-dragdrop-placeholder": "Σύρετε ένα αρχείο εδώ (ή κάντε κλικ για αναζήτηση)"
+       "ooui-selectfile-dragdrop-placeholder": "Σύρετε το αρχείο εδώ"
 }
index 218ece2..1a8e31b 100644 (file)
@@ -18,6 +18,5 @@
        "ooui-dialog-process-continue": "Continue",
        "ooui-selectfile-not-supported": "File(s) not supported",
        "ooui-selectfile-placeholder": "No file selected",
-       "ooui-selectfile-dragdrop-placeholder": "Drop file here (or click to browse your computer)",
-       "ooui-semicolon-separator": ";"
+       "ooui-selectfile-dragdrop-placeholder": "Drop file here (or click to browse your computer)"
 }
index 7cf2eb1..be00832 100644 (file)
@@ -31,6 +31,5 @@
        "ooui-selectfile-button-select": "Select a file",
        "ooui-selectfile-not-supported": "File selection is not supported",
        "ooui-selectfile-placeholder": "No file is selected",
-       "ooui-selectfile-dragdrop-placeholder": "Drop file here",
-       "ooui-semicolon-separator": "; "
+       "ooui-selectfile-dragdrop-placeholder": "Drop file here"
 }
index 11bd4b8..0375c8e 100644 (file)
@@ -29,7 +29,8 @@
        "ooui-dialog-process-dismiss": "رد",
        "ooui-dialog-process-retry": "دوباره امتحان کنید",
        "ooui-dialog-process-continue": "ادامه",
+       "ooui-selectfile-button-select": "یک فایل انتخاب کنید",
        "ooui-selectfile-not-supported": "انتخاب پرونده پشتیبانی نمی‌شود",
        "ooui-selectfile-placeholder": "هیچ پرونده‌ای انتخاب نشده است",
-       "ooui-selectfile-dragdrop-placeholder": "رها کردن فایل در اینجا (و یا کلیک کنید به فهرست)"
+       "ooui-selectfile-dragdrop-placeholder": "فایل را اینجا رها کنید"
 }
index 387d736..68a25b5 100644 (file)
                        "Raoli",
                        "Una giornata uggiosa '94",
                        "Ontsed",
-                       "Alexmar983"
+                       "Alexmar983",
+                       "Nemo bis",
+                       "Jdforrester"
                ]
        },
        "ooui-outline-control-move-down": "Sposta in basso",
        "ooui-outline-control-move-up": "Sposta in alto",
        "ooui-outline-control-remove": "Rimuovi elemento",
        "ooui-toolbar-more": "Altro",
-       "ooui-toolgroup-expand": "Più",
+       "ooui-toolgroup-expand": "Altro",
        "ooui-toolgroup-collapse": "Meno",
        "ooui-dialog-message-accept": "OK",
        "ooui-dialog-message-reject": "Annulla",
@@ -28,6 +30,8 @@
        "ooui-dialog-process-dismiss": "Nascondi",
        "ooui-dialog-process-retry": "Riprova",
        "ooui-dialog-process-continue": "Continua",
+       "ooui-selectfile-button-select": "Seleziona un file",
        "ooui-selectfile-not-supported": "La selezione del file non è supportata",
-       "ooui-selectfile-placeholder": "Nessun file è selezionato"
+       "ooui-selectfile-placeholder": "Nessun file è selezionato",
+       "ooui-selectfile-dragdrop-placeholder": "Posiziona i files qui"
 }
index efacb63..f1a1a47 100644 (file)
@@ -24,6 +24,5 @@
        "ooui-dialog-process-retry": "კიდევ სცადეთ",
        "ooui-dialog-process-continue": "გაგრძელება",
        "ooui-selectfile-not-supported": "ფაილის არჩევა არ არის მხარდაჭერილი",
-       "ooui-selectfile-placeholder": "ფაილი არ არის არჩეული",
-       "ooui-semicolon-separator": ";"
+       "ooui-selectfile-placeholder": "ფაილი არ არის არჩეული"
 }
index bc3cf0b..d4068c8 100644 (file)
@@ -17,6 +17,5 @@
        "ooui-dialog-process-retry": "Энтда сынаб кёр",
        "ooui-dialog-process-continue": "Бардыр",
        "ooui-selectfile-not-supported": "Файл сайлау тутулмайды",
-       "ooui-selectfile-placeholder": "Бир файл да сайланмагъанды",
-       "ooui-semicolon-separator": ";"
+       "ooui-selectfile-placeholder": "Бир файл да сайланмагъанды"
 }
diff --git a/resources/lib/oojs-ui/i18n/krl.json b/resources/lib/oojs-ui/i18n/krl.json
new file mode 100644 (file)
index 0000000..6ff25eb
--- /dev/null
@@ -0,0 +1,10 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Mashoi7"
+               ]
+       },
+       "ooui-toolbar-more": "Enämpi",
+       "ooui-toolgroup-expand": "Enämpi",
+       "ooui-toolgroup-collapse": "Vähempi"
+}
diff --git a/resources/lib/oojs-ui/i18n/olo.json b/resources/lib/oojs-ui/i18n/olo.json
new file mode 100644 (file)
index 0000000..855b0ea
--- /dev/null
@@ -0,0 +1,13 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Mashoi7"
+               ]
+       },
+       "ooui-toolbar-more": "Enämbi",
+       "ooui-toolgroup-expand": "Enämbi",
+       "ooui-toolgroup-collapse": "Vähembi",
+       "ooui-dialog-process-retry": "Opi vie",
+       "ooui-dialog-process-continue": "Jatka",
+       "ooui-selectfile-button-select": "Valliče failu"
+}
index 8379cac..8d9071a 100644 (file)
@@ -10,7 +10,8 @@
                        "Jdforrester",
                        "Luckas",
                        "Vitorvicentevalente",
-                       "SandroHc"
+                       "SandroHc",
+                       "Jkb8"
                ]
        },
        "ooui-outline-control-move-down": "Mover item para baixo",
@@ -27,5 +28,5 @@
        "ooui-dialog-process-continue": "Continuar",
        "ooui-selectfile-not-supported": "A seleção de ficheiros não é suportada",
        "ooui-selectfile-placeholder": "Nenhum ficheiro selecionado",
-       "ooui-selectfile-dragdrop-placeholder": "Soltar ficheiro aqui (ou clicar para navegar)"
+       "ooui-selectfile-dragdrop-placeholder": "Soltar ficheiro aqui"
 }
index cd9c0c2..1a096ef 100644 (file)
@@ -35,6 +35,5 @@
        "ooui-selectfile-button-select": "Label for the file selection widget's select file button",
        "ooui-selectfile-not-supported": "Label for the file selection widget if file selection is not supported",
        "ooui-selectfile-placeholder": "Label for the file selection widget when no file is currently selected",
-       "ooui-selectfile-dragdrop-placeholder": "Label for the file selection widget's drop target",
-       "ooui-semicolon-separator": "{{optional}} Semicolon used as a separator"
+       "ooui-selectfile-dragdrop-placeholder": "Label for the file selection widget's drop target"
 }
index 1ccc67b..ddd27c5 100644 (file)
@@ -9,9 +9,14 @@
        "ooui-outline-control-move-down": "Sposta in baso",
        "ooui-outline-control-move-up": "Sposta in sima",
        "ooui-toolbar-more": "Altro",
+       "ooui-toolgroup-expand": "Piassè",
+       "ooui-toolgroup-collapse": "Manco",
        "ooui-dialog-message-accept": "Va ben",
+       "ooui-dialog-message-reject": "Fa gnente",
        "ooui-dialog-process-error": "Xe 'ndà storto calcossa",
        "ooui-dialog-process-dismiss": "Scondi",
        "ooui-dialog-process-retry": "Proa da novo",
-       "ooui-dialog-process-continue": "Và vanti"
+       "ooui-dialog-process-continue": "Và vanti",
+       "ooui-selectfile-button-select": "Siegli un file",
+       "ooui-selectfile-dragdrop-placeholder": "Mola zo el file chì rento"
 }
index ff14801..27cef23 100644 (file)
@@ -22,5 +22,5 @@
        "ooui-dialog-process-continue": "Tiếp tục",
        "ooui-selectfile-not-supported": "Không hỗ trợ việc chọn tập tin",
        "ooui-selectfile-placeholder": "Không có tập tin nào được chọn",
-       "ooui-selectfile-dragdrop-placeholder": "Thả tập tin vào đây (hoặc nhấn chuột để duyệt)"
+       "ooui-selectfile-dragdrop-placeholder": "Thả tập tin vào đây"
 }
index ede6ea9..2db4bdb 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.12.8
+ * OOjs UI v0.12.9
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-09-08T20:56:08Z
+ * Date: 2015-09-22T20:09:59Z
  */
 @-webkit-keyframes oo-ui-progressBarWidget-slide {
        from {
        right: 18em;
        bottom: 18em;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu .oo-ui-menuLayout-menu {
+.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu .oo-ui-menuLayout-menu {
        width: 0 !important;
        height: 0 !important;
        overflow: hidden;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu .oo-ui-menuLayout-content {
+.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu .oo-ui-menuLayout-content {
        top: 0 !important;
        left: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top .oo-ui-menuLayout-menu {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top .oo-ui-menuLayout-menu {
        width: auto !important;
        left: 0;
        top: 0;
        right: 0;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top .oo-ui-menuLayout-content {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top .oo-ui-menuLayout-content {
        right: 0 !important;
        bottom: 0 !important;
        left: 0 !important;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after .oo-ui-menuLayout-menu {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after .oo-ui-menuLayout-menu {
        height: auto !important;
        top: 0;
        right: 0;
        bottom: 0;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after .oo-ui-menuLayout-content {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after .oo-ui-menuLayout-content {
        bottom: 0 !important;
        left: 0 !important;
        top: 0 !important;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom .oo-ui-menuLayout-menu {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom .oo-ui-menuLayout-menu {
        width: auto !important;
        right: 0;
        bottom: 0;
        left: 0;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom .oo-ui-menuLayout-content {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom .oo-ui-menuLayout-content {
        left: 0 !important;
        top: 0 !important;
        right: 0 !important;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before .oo-ui-menuLayout-menu {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before .oo-ui-menuLayout-menu {
        height: auto !important;
        bottom: 0;
        left: 0;
        top: 0;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before .oo-ui-menuLayout-content {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before .oo-ui-menuLayout-content {
        top: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        display: inline;
 }
 .oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link {
+       outline: 0;
        cursor: default;
 }
 .oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool {
 .oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
        border-left-color: rgba(0, 0, 0, 0.1);
 }
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link:focus {
+       outline: 0;
+}
 .oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link .oo-ui-tool-title {
        color: #cccccc;
 }
 .oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled:hover > .oo-ui-tool-link .oo-ui-iconElement-icon {
        opacity: 1;
 }
+.oo-ui-barToolGroup.oo-ui-widget-disabled > .oo-ui-toolGroup-tools > .oo-ui-tool:focus {
+       outline: 0;
+}
+.oo-ui-barToolGroup.oo-ui-widget-disabled > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link:focus {
+       outline: 0;
+}
 .oo-ui-barToolGroup.oo-ui-widget-disabled > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-tool-title {
        color: #cccccc;
 }
        position: absolute;
 }
 .oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
+       outline: 0;
        cursor: default;
 }
 .oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
        border-color: #dddddd;
        background-color: #f3f3f3;
 }
+.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle:focus {
+       outline: 0;
+}
 .oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
        opacity: 0.2;
 }
        right: 0;
        text-overflow: ellipsis;
 }
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label > .oo-ui-selectFileWidget-fileType {
+       float: right;
+}
 .oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator,
 .oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon,
 .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
 .oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon {
        left: 0.25em;
 }
-.oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label {
+.oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label {
        line-height: 2.3em;
        margin: 0;
        overflow: hidden;
        left: 0.5em;
        right: 0.5em;
 }
-.oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-clearButton {
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label > .oo-ui-selectFileWidget-fileType {
+       color: #888888;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
        top: 0;
        width: 1.875em;
        height: 1.875em;
index 83452d0..5909cd1 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.12.8
+ * OOjs UI v0.12.9
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-09-08T20:55:55Z
+ * Date: 2015-09-22T20:09:51Z
  */
 /**
  * @class
index 87ae9a5..f1f1831 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.12.8
+ * OOjs UI v0.12.9
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-09-08T20:56:08Z
+ * Date: 2015-09-22T20:09:59Z
  */
 @-webkit-keyframes oo-ui-progressBarWidget-slide {
        from {
 }
 .oo-ui-buttonElement > .oo-ui-buttonElement-button {
        font-weight: bold;
+       text-decoration: none;
 }
 .oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
        margin-left: 0;
 .oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
        width: 0.9375em;
        height: 0.9375em;
-       margin: 0.46875em;
 }
 .oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
        margin-left: 0.46875em;
 .oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
        color: #cccccc;
 }
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button:focus {
+       box-shadow: none;
+}
 .oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
 .oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
        opacity: 0.2;
 }
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button {
+       padding-left: 2.4em;
+}
 .oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
        margin: 0.1em 0;
-       padding: 0.2em 0.8em;
+       padding: 0.5em 1em;
+       min-height: 1.2em;
+       min-width: 1em;
        border-radius: 2px;
+       position: relative;
        -webkit-transition: background 100ms ease, color 100ms ease, box-shadow 100ms ease;
           -moz-transition: background 100ms ease, color 100ms ease, box-shadow 100ms ease;
            -ms-transition: background 100ms ease, color 100ms ease, box-shadow 100ms ease;
 }
 .oo-ui-buttonElement-framed > input.oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
-       line-height: 1.875em;
+       line-height: 1.2em;
+       display: inline-block;
 }
 .oo-ui-buttonElement-framed.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
-       margin-left: -0.5em;
-       margin-right: -0.5em;
+       position: absolute;
+       top: 0.2em;
+       left: 0.5625em;
 }
-.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
-       margin-right: 0.3em;
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+       margin-left: 0.3em;
 }
 .oo-ui-buttonElement-framed.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
-       /* -0.5 - 0.475 */
-       margin-left: -0.005em;
-       margin-right: -0.005em;
+       display: inline-block;
 }
 .oo-ui-buttonElement-framed.oo-ui-indicatorElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
 .oo-ui-buttonElement-framed.oo-ui-indicatorElement.oo-ui-iconElement:not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
        margin-left: 0.46875em;
        margin-right: -0.275em;
 }
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+       position: relative;
+       left: 0.2em;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
        color: #ffffff;
        background: #dddddd;
 .oo-ui-indexLayout-stackLayout > .oo-ui-panelLayout {
        padding: 1.5em;
 }
+.oo-ui-indexLayout > .oo-ui-menuLayout-menu {
+       height: 2.75em;
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-content {
+       top: 2.75em;
+}
 .oo-ui-fieldLayout {
        display: block;
        margin-bottom: 1em;
        right: 18em;
        bottom: 18em;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu .oo-ui-menuLayout-menu {
+.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu .oo-ui-menuLayout-menu {
        width: 0 !important;
        height: 0 !important;
        overflow: hidden;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu .oo-ui-menuLayout-content {
+.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu .oo-ui-menuLayout-content {
        top: 0 !important;
        left: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top .oo-ui-menuLayout-menu {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top .oo-ui-menuLayout-menu {
        width: auto !important;
        left: 0;
        top: 0;
        right: 0;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top .oo-ui-menuLayout-content {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top .oo-ui-menuLayout-content {
        right: 0 !important;
        bottom: 0 !important;
        left: 0 !important;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after .oo-ui-menuLayout-menu {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after .oo-ui-menuLayout-menu {
        height: auto !important;
        top: 0;
        right: 0;
        bottom: 0;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after .oo-ui-menuLayout-content {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after .oo-ui-menuLayout-content {
        bottom: 0 !important;
        left: 0 !important;
        top: 0 !important;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom .oo-ui-menuLayout-menu {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom .oo-ui-menuLayout-menu {
        width: auto !important;
        right: 0;
        bottom: 0;
        left: 0;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom .oo-ui-menuLayout-content {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom .oo-ui-menuLayout-content {
        left: 0 !important;
        top: 0 !important;
        right: 0 !important;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before .oo-ui-menuLayout-menu {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before .oo-ui-menuLayout-menu {
        height: auto !important;
        bottom: 0;
        left: 0;
        top: 0;
 }
-.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before .oo-ui-menuLayout-content {
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before .oo-ui-menuLayout-content {
        top: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        display: inline;
 }
 .oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link {
+       outline: 0;
        cursor: default;
 }
 .oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link {
        position: absolute;
 }
 .oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
+       outline: 0;
        cursor: default;
 }
 .oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
        display: inline-block;
        vertical-align: middle;
 }
-.oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
-       height: 1.875em;
-}
 .oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
        margin-top: 0;
 }
 .oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
        background: #dddddd;
        border-color: #dddddd;
+       outline: 0;
 }
 .oo-ui-toggleSwitchWidget.oo-ui-widget-disabled .oo-ui-toggleSwitchWidget-grip {
        background: #ffffff;
        border: 1px solid #aaaaaa;
        border-radius: 0.2em;
        background-color: #ffffff;
-       box-shadow: inset 0 -0.2em 0 0 rgba(0, 0, 0, 0.2);
+       box-shadow: 0 0.15em 0 0 rgba(204, 204, 204, 0.5);
 }
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-popup {
        margin-top: 9px;
        margin-top: -1px;
        border: 1px solid #aaaaaa;
        border-radius: 0 0 0.2em 0.2em;
-       padding-bottom: 0.25em;
-       box-shadow: inset 0 -0.2em 0 0 rgba(0, 0, 0, 0.2), 0 0.1em 0 0 rgba(0, 0, 0, 0.2);
+       box-shadow: 0 0.15em 0 0 rgba(204, 204, 204, 0.5);
 }
 .oo-ui-menuSelectWidget input {
        position: absolute;
        border-color: #dddddd;
        background-color: #f3f3f3;
 }
+.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle:focus {
+       outline: 0;
+}
 .oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
        opacity: 0.2;
 }
        right: 0;
        text-overflow: ellipsis;
 }
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label > .oo-ui-selectFileWidget-fileType {
+       float: right;
+}
 .oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator,
 .oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon,
 .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
 .oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon {
        left: 0.25em;
 }
-.oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label {
+.oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label {
        line-height: 2.3em;
        margin: 0;
        overflow: hidden;
        left: 1em;
        right: 1em;
 }
-.oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-clearButton {
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label > .oo-ui-selectFileWidget-fileType {
+       color: #888888;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
        top: 0;
        width: 1.875em;
        height: 1.875em;
        font-weight: bold;
        line-height: 1.875em;
 }
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-buttonElement-button,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-buttonElement-button,
-.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-buttonElement-button {
-       min-width: 1.875em;
-       min-height: 1.875em;
-}
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-labelElement-label,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-labelElement-label,
-.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-labelElement-label {
-       line-height: 1.875em;
-}
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
-.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
-       margin-top: -0.125em;
-}
 .oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed,
 .oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed,
 .oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed {
-       margin: 0.75em;
-}
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
-.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
-       padding: 0 1em;
-       vertical-align: middle;
-       /* Adjust for border so text aligns with title */
-       margin: -1px;
+       margin: 0.5em;
 }
 .oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless,
 .oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless,
        padding: 0.75em 1em;
        vertical-align: middle;
 }
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget:hover,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget:hover {
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-labelElement-label {
+       line-height: 1.875em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless:hover {
        background-color: rgba(0, 0, 0, 0.05);
 }
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget:active,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget:active {
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless:active {
        background-color: rgba(0, 0, 0, 0.1);
 }
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:hover,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:hover {
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:hover {
        background-color: rgba(8, 126, 204, 0.05);
 }
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:active,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:active {
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:active {
        background-color: rgba(8, 126, 204, 0.1);
 }
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label {
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label {
        font-weight: bold;
 }
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover {
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:hover {
        background-color: rgba(118, 171, 54, 0.05);
 }
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active {
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:active {
        background-color: rgba(118, 171, 54, 0.1);
 }
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover {
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:hover {
        background-color: rgba(212, 83, 83, 0.05);
 }
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active {
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:active {
        background-color: rgba(212, 83, 83, 0.1);
 }
 .oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement {
index a291570..c2f6dc5 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.12.8
+ * OOjs UI v0.12.9
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-09-08T20:55:55Z
+ * Date: 2015-09-22T20:09:51Z
  */
 /**
  * @class
index 81677ed..42bf821 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.12.8
+ * OOjs UI v0.12.9
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-09-08T20:55:55Z
+ * Date: 2015-09-22T20:09:51Z
  */
 ( function ( OO ) {
 
@@ -67,30 +67,79 @@ OO.ui.generateElementId = function () {
  * @return {boolean}
  */
 OO.ui.isFocusableElement = function ( $element ) {
-       var node = $element[ 0 ],
-               nodeName = node.nodeName.toLowerCase(),
-               // Check if the element have tabindex set
-               isInElementGroup = /^(input|select|textarea|button|object)$/.test( nodeName ),
-               // Check if the element is a link with href or if it has tabindex
-               isOtherElement = (
-                       ( nodeName === 'a' && node.href ) ||
-                       !isNaN( $element.attr( 'tabindex' ) )
-               ),
-               // Check if the element is visible
-               isVisible = (
-                       // This is quicker than calling $element.is( ':visible' )
-                       $.expr.filters.visible( node ) &&
-                       // Check that all parents are visible
-                       !$element.parents().addBack().filter( function () {
-                               return $.css( this, 'visibility' ) === 'hidden';
-                       } ).length
-               ),
-               isTabOk = isNaN( $element.attr( 'tabindex' ) ) || +$element.attr( 'tabindex' ) >= 0;
+       var nodeName,
+               element = $element[ 0 ];
 
-       return (
-               ( isInElementGroup ? !node.disabled : isOtherElement ) &&
-               isVisible && isTabOk
-       );
+       // Anything disabled is not focusable
+       if ( element.disabled ) {
+               return false;
+       }
+
+       // Check if the element is visible
+       if ( !(
+               // This is quicker than calling $element.is( ':visible' )
+               $.expr.filters.visible( element ) &&
+               // Check that all parents are visible
+               !$element.parents().addBack().filter( function () {
+                       return $.css( this, 'visibility' ) === 'hidden';
+               } ).length
+       ) ) {
+               return false;
+       }
+
+       // Check if the element is ContentEditable, which is the string 'true'
+       if ( element.contentEditable === 'true' ) {
+               return true;
+       }
+
+       // Anything with a non-negative numeric tabIndex is focusable.
+       // Use .prop to avoid browser bugs
+       if ( $element.prop( 'tabIndex' ) >= 0 ) {
+               return true;
+       }
+
+       // Some element types are naturally focusable
+       // (indexOf is much faster than regex in Chrome and about the
+       // same in FF: https://jsperf.com/regex-vs-indexof-array2)
+       nodeName = element.nodeName.toLowerCase();
+       if ( [ 'input', 'select', 'textarea', 'button', 'object' ].indexOf( nodeName ) !== -1 ) {
+               return true;
+       }
+
+       // Links and areas are focusable if they have an href
+       if ( ( nodeName === 'a' || nodeName === 'area' ) && $element.attr( 'href' ) !== undefined ) {
+               return true;
+       }
+
+       return false;
+};
+
+/**
+ * Find a focusable child
+ *
+ * @param {jQuery} $container Container to search in
+ * @param {boolean} [backwards] Search backwards
+ * @return {jQuery} Focusable child, an empty jQuery object if none found
+ */
+OO.ui.findFocusable = function ( $container, backwards ) {
+       var $focusable = $( [] ),
+               // $focusableCandidates is a superset of things that
+               // could get matched by isFocusableElement
+               $focusableCandidates = $container
+                       .find( 'input, select, textarea, button, object, a, area, [contenteditable], [tabindex]' );
+
+       if ( backwards ) {
+               $focusableCandidates = Array.prototype.reverse.call( $focusableCandidates );
+       }
+
+       $focusableCandidates.each( function () {
+               var $this = $( this );
+               if ( OO.ui.isFocusableElement( $this ) ) {
+                       $focusable = $this;
+                       return false;
+               }
+       } );
+       return $focusable;
 };
 
 /**
@@ -286,9 +335,7 @@ OO.ui.infuse = function ( idOrNode ) {
                // Label for the file selection widget when no file is currently selected
                'ooui-selectfile-placeholder': 'No file is selected',
                // Label for the file selection widget's drop target
-               'ooui-selectfile-dragdrop-placeholder': 'Drop file here',
-               // Semicolon separator
-               'ooui-semicolon-separator': '; '
+               'ooui-selectfile-dragdrop-placeholder': 'Drop file here'
        };
 
        /**
@@ -1960,7 +2007,8 @@ OO.ui.Widget.static.supportsSimpleLabel = false;
 /**
  * @event disable
  *
- * A 'disable' event is emitted when a widget is disabled.
+ * A 'disable' event is emitted when the disabled state of the widget changes
+ * (i.e. on disable **and** enable).
  *
  * @param {boolean} disabled Widget is disabled
  */
@@ -2081,6 +2129,10 @@ OO.ui.Window = function OoUiWindow( config ) {
        this.$overlay = $( '<div>' );
        this.$content = $( '<div>' );
 
+       this.$focusTrapBefore = $( '<div>' ).prop( 'tabIndex', 0 );
+       this.$focusTrapAfter = $( '<div>' ).prop( 'tabIndex', 0 );
+       this.$focusTraps = this.$focusTrapBefore.add( this.$focusTrapAfter );
+
        // Initialization
        this.$overlay.addClass( 'oo-ui-window-overlay' );
        this.$content
@@ -2088,7 +2140,7 @@ OO.ui.Window = function OoUiWindow( config ) {
                .attr( 'tabindex', 0 );
        this.$frame
                .addClass( 'oo-ui-window-frame' )
-               .append( this.$content );
+               .append( this.$focusTrapBefore, this.$content, this.$focusTrapAfter );
 
        this.$element
                .addClass( 'oo-ui-window' )
@@ -2521,6 +2573,21 @@ OO.ui.Window.prototype.initialize = function () {
        return this;
 };
 
+/**
+ * Called when someone tries to focus the hidden element at the end of the dialog.
+ * Sends focus back to the start of the dialog.
+ *
+ * @param {jQuery.Event} event Focus event
+ */
+OO.ui.Window.prototype.onFocusTrapFocused = function ( event ) {
+       if ( this.$focusTrapBefore.is( event.target ) ) {
+               OO.ui.findFocusable( this.$content, true ).focus();
+       } else {
+               // this.$content is the part of the focus cycle, and is the first focusable element
+               this.$content.focus();
+       }
+};
+
 /**
  * Open the window.
  *
@@ -2581,6 +2648,9 @@ OO.ui.Window.prototype.setup = function ( data ) {
 
        this.toggle( true );
 
+       this.focusTrapHandler = OO.ui.bind( this.onFocusTrapFocused, this );
+       this.$focusTraps.on( 'focus', this.focusTrapHandler );
+
        this.getSetupProcess( data ).execute().done( function () {
                // Force redraw by asking the browser to measure the elements' widths
                win.$element.addClass( 'oo-ui-window-active oo-ui-window-setup' ).width();
@@ -2663,6 +2733,7 @@ OO.ui.Window.prototype.teardown = function ( data ) {
                        // Force redraw by asking the browser to measure the elements' widths
                        win.$element.removeClass( 'oo-ui-window-active oo-ui-window-setup' ).width();
                        win.$content.removeClass( 'oo-ui-window-content-setup' ).width();
+                       win.$focusTraps.off( 'focus', win.focusTrapHandler );
                        win.toggle( false );
                } );
 };
@@ -6754,6 +6825,161 @@ OO.ui.mixin.ClippableElement.prototype.clip = function () {
        return this;
 };
 
+/**
+ * Element that will stick under a specified container, even when it is inserted elsewhere in the
+ * document (for example, in a OO.ui.Window's $overlay).
+ *
+ * The elements's position is automatically calculated and maintained when window is resized or the
+ * page is scrolled. If you reposition the container manually, you have to call #position to make
+ * sure the element is still placed correctly.
+ *
+ * As positioning is only possible when both the element and the container are attached to the DOM
+ * and visible, it's only done after you call #togglePositioning. You might want to do this inside
+ * the #toggle method to display a floating popup, for example.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$floatable] Node to position, assigned to #$floatable, omit to use #$element
+ * @cfg {jQuery} [$floatableContainer] Node to position below
+ */
+OO.ui.mixin.FloatableElement = function OoUiMixinFloatableElement( config ) {
+       // Configuration initialization
+       config = config || {};
+
+       // Properties
+       this.$floatable = null;
+       this.$floatableContainer = null;
+       this.$floatableWindow = null;
+       this.$floatableClosestScrollable = null;
+       this.onFloatableScrollHandler = this.position.bind( this );
+       this.onFloatableWindowResizeHandler = this.position.bind( this );
+
+       // Initialization
+       this.setFloatableContainer( config.$floatableContainer );
+       this.setFloatableElement( config.$floatable || this.$element );
+};
+
+/* Methods */
+
+/**
+ * Set floatable element.
+ *
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $floatable Element to make floatable
+ */
+OO.ui.mixin.FloatableElement.prototype.setFloatableElement = function ( $floatable ) {
+       if ( this.$floatable ) {
+               this.$floatable.removeClass( 'oo-ui-floatableElement-floatable' );
+               this.$floatable.css( { left: '', top: '' } );
+       }
+
+       this.$floatable = $floatable.addClass( 'oo-ui-floatableElement-floatable' );
+       this.position();
+};
+
+/**
+ * Set floatable container.
+ *
+ * The element will be always positioned under the specified container.
+ *
+ * @param {jQuery|null} $floatableContainer Container to keep visible, or null to unset
+ */
+OO.ui.mixin.FloatableElement.prototype.setFloatableContainer = function ( $floatableContainer ) {
+       this.$floatableContainer = $floatableContainer;
+       if ( this.$floatable ) {
+               this.position();
+       }
+};
+
+/**
+ * Toggle positioning.
+ *
+ * Do not turn positioning on until after the element is attached to the DOM and visible.
+ *
+ * @param {boolean} [positioning] Enable positioning, omit to toggle
+ * @chainable
+ */
+OO.ui.mixin.FloatableElement.prototype.togglePositioning = function ( positioning ) {
+       var closestScrollableOfContainer, closestScrollableOfFloatable;
+
+       positioning = positioning === undefined ? !this.positioning : !!positioning;
+
+       if ( this.positioning !== positioning ) {
+               this.positioning = positioning;
+
+               closestScrollableOfContainer = OO.ui.Element.static.getClosestScrollableContainer( this.$floatableContainer[ 0 ] );
+               closestScrollableOfFloatable = OO.ui.Element.static.getClosestScrollableContainer( this.$floatable[ 0 ] );
+               if ( closestScrollableOfContainer !== closestScrollableOfFloatable ) {
+                       // If the scrollable is the root, we have to listen to scroll events
+                       // on the window because of browser inconsistencies (or do we? someone should verify this)
+                       if ( $( closestScrollableOfContainer ).is( 'html, body' ) ) {
+                               closestScrollableOfContainer = OO.ui.Element.static.getWindow( closestScrollableOfContainer );
+                       }
+               }
+
+               if ( positioning ) {
+                       this.$floatableWindow = $( this.getElementWindow() );
+                       this.$floatableWindow.on( 'resize', this.onFloatableWindowResizeHandler );
+
+                       if ( closestScrollableOfContainer !== closestScrollableOfFloatable ) {
+                               this.$floatableClosestScrollable = $( closestScrollableOfContainer );
+                               this.$floatableClosestScrollable.on( 'scroll', this.onFloatableScrollHandler );
+                       }
+
+                       // Initial position after visible
+                       this.position();
+               } else {
+                       this.$floatableWindow.off( 'resize', this.onFloatableWindowResizeHandler );
+                       this.$floatableWindow = null;
+
+                       if ( this.$floatableClosestScrollable ) {
+                               this.$floatableClosestScrollable.off( 'scroll', this.onFloatableScrollHandler );
+                               this.$floatableClosestScrollable = null;
+                       }
+
+                       this.$floatable.css( { left: '', top: '' } );
+               }
+       }
+
+       return this;
+};
+
+/**
+ * Position the floatable below its container.
+ *
+ * This should only be done when both of them are attached to the DOM and visible.
+ *
+ * @chainable
+ */
+OO.ui.mixin.FloatableElement.prototype.position = function () {
+       var pos;
+
+       if ( !this.positioning ) {
+               return this;
+       }
+
+       pos = OO.ui.Element.static.getRelativePosition( this.$floatableContainer, this.$floatable.offsetParent() );
+
+       // Position under container
+       pos.top += this.$floatableContainer.height();
+       this.$floatable.css( pos );
+
+       // We updated the position, so re-evaluate the clipping state.
+       // (ClippableElement does not listen to 'scroll' events on $floatableContainer's parent, and so
+       // will not notice the need to update itself.)
+       // TODO: This is terrible, we shouldn't need to know about ClippableElement at all here. Why does
+       // it not listen to the right events in the right places?
+       if ( this.clip ) {
+               this.clip();
+       }
+
+       return this;
+};
+
 /**
  * AccessKeyedElement is mixed into other classes to provide an `accesskey` attribute.
  * Accesskeys allow an user to go to a specific element by using
@@ -8182,7 +8408,6 @@ OO.ui.MessageDialog.prototype.onResize = function () {
 /**
  * Toggle action layout between vertical and horizontal.
  *
- *
  * @private
  * @param {boolean} [value] Layout actions vertically, omit to toggle
  * @chainable
@@ -8998,7 +9223,6 @@ OO.ui.FieldLayout.prototype.setAlignment = function ( value ) {
  *
  *     $( 'body' ).append( actionFieldLayout.$element );
  *
- *
  * @class
  * @extends OO.ui.FieldLayout
  *
@@ -9589,7 +9813,7 @@ OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {
  * @param {number} [itemIndex] A specific item to focus on
  */
 OO.ui.BookletLayout.prototype.focus = function ( itemIndex ) {
-       var $input, page,
+       var page,
                items = this.stackLayout.getItems();
 
        if ( itemIndex !== undefined && items[ itemIndex ] ) {
@@ -9607,10 +9831,7 @@ OO.ui.BookletLayout.prototype.focus = function ( itemIndex ) {
        }
        // Only change the focus if is not already in the current page
        if ( !page.$element.find( ':focus' ).length ) {
-               $input = page.$element.find( ':input:first' );
-               if ( $input.length ) {
-                       $input[ 0 ].focus();
-               }
+               OO.ui.findFocusable( page.$element ).focus();
        }
 };
 
@@ -9619,28 +9840,7 @@ OO.ui.BookletLayout.prototype.focus = function ( itemIndex ) {
  * on it.
  */
 OO.ui.BookletLayout.prototype.focusFirstFocusable = function () {
-       var i, len,
-               found = false,
-               items = this.stackLayout.getItems(),
-               checkAndFocus = function () {
-                       if ( OO.ui.isFocusableElement( $( this ) ) ) {
-                               $( this ).focus();
-                               found = true;
-                               return false;
-                       }
-               };
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               if ( found ) {
-                       break;
-               }
-               // Find all potentially focusable elements in the item
-               // and check if they are focusable
-               items[ i ].$element
-                       .find( 'input, select, textarea, button, object' )
-                       /* jshint loopfunc:true */
-                       .each( checkAndFocus );
-       }
+       OO.ui.findFocusable( this.stackLayout.$element ).focus();
 };
 
 /**
@@ -9908,7 +10108,8 @@ OO.ui.BookletLayout.prototype.clearPages = function () {
 OO.ui.BookletLayout.prototype.setPage = function ( name ) {
        var selectedItem,
                $focused,
-               page = this.pages[ name ];
+               page = this.pages[ name ],
+               previousPage = this.currentPageName && this.pages[ this.currentPageName ];
 
        if ( name !== this.currentPageName ) {
                if ( this.outlined ) {
@@ -9918,21 +10119,34 @@ OO.ui.BookletLayout.prototype.setPage = function ( name ) {
                        }
                }
                if ( page ) {
-                       if ( this.currentPageName && this.pages[ this.currentPageName ] ) {
-                               this.pages[ this.currentPageName ].setActive( false );
-                               // Blur anything focused if the next page doesn't have anything focusable - this
-                               // is not needed if the next page has something focusable because once it is focused
-                               // this blur happens automatically
-                               if ( this.autoFocus && !page.$element.find( ':input' ).length ) {
-                                       $focused = this.pages[ this.currentPageName ].$element.find( ':focus' );
+                       if ( previousPage ) {
+                               previousPage.setActive( false );
+                               // Blur anything focused if the next page doesn't have anything focusable.
+                               // This is not needed if the next page has something focusable (because once it is focused
+                               // this blur happens automatically). If the layout is non-continuous, this check is
+                               // meaningless because the next page is not visible yet and thus can't hold focus.
+                               if (
+                                       this.autoFocus &&
+                                       this.stackLayout.continuous &&
+                                       OO.ui.findFocusable( page.$element ).length !== 0
+                               ) {
+                                       $focused = previousPage.$element.find( ':focus' );
                                        if ( $focused.length ) {
                                                $focused[ 0 ].blur();
                                        }
                                }
                        }
                        this.currentPageName = name;
-                       this.stackLayout.setItem( page );
                        page.setActive( true );
+                       this.stackLayout.setItem( page );
+                       if ( !this.stackLayout.continuous && previousPage ) {
+                               // This should not be necessary, since any inputs on the previous page should have been
+                               // blurred when it was hidden, but browsers are not very consistent about this.
+                               $focused = previousPage.$element.find( ':focus' );
+                               if ( $focused.length ) {
+                                       $focused[ 0 ].blur();
+                               }
+                       }
                        this.emit( 'set', page );
                }
        }
@@ -9969,20 +10183,13 @@ OO.ui.BookletLayout.prototype.selectFirstSelectablePage = function () {
  *     }
  *     OO.inheritClass( CardOneLayout, OO.ui.CardLayout );
  *     CardOneLayout.prototype.setupTabItem = function () {
- *         this.tabItem.setLabel( 'Card One' );
- *     };
- *
- *     function CardTwoLayout( name, config ) {
- *         CardTwoLayout.parent.call( this, name, config );
- *         this.$element.append( '<p>Second card</p>' );
- *     }
- *     OO.inheritClass( CardTwoLayout, OO.ui.CardLayout );
- *     CardTwoLayout.prototype.setupTabItem = function () {
- *         this.tabItem.setLabel( 'Card Two' );
+ *         this.tabItem.setLabel( 'Card one' );
  *     };
  *
  *     var card1 = new CardOneLayout( 'one' ),
- *         card2 = new CardTwoLayout( 'two' );
+ *         card2 = new CardLayout( 'two', { label: 'Card two' } );
+ *
+ *     card2.$element.append( '<p>Second card</p>' );
  *
  *     var index = new OO.ui.IndexLayout();
  *
@@ -9995,6 +10202,7 @@ OO.ui.BookletLayout.prototype.selectFirstSelectablePage = function () {
  * @constructor
  * @param {Object} [config] Configuration options
  * @cfg {boolean} [continuous=false] Show all cards, one after another
+ * @cfg {boolean} [expanded=true] Expand the content panel to fill the entire parent element.
  * @cfg {boolean} [autoFocus=true] Focus on the first focusable element when a new card is displayed.
  */
 OO.ui.IndexLayout = function OoUiIndexLayout( config ) {
@@ -10008,7 +10216,10 @@ OO.ui.IndexLayout = function OoUiIndexLayout( config ) {
        this.currentCardName = null;
        this.cards = {};
        this.ignoreFocus = false;
-       this.stackLayout = new OO.ui.StackLayout( { continuous: !!config.continuous } );
+       this.stackLayout = new OO.ui.StackLayout( {
+               continuous: !!config.continuous,
+               expanded: config.expanded
+       } );
        this.$content.append( this.stackLayout.$element );
        this.autoFocus = config.autoFocus === undefined || !!config.autoFocus;
 
@@ -10109,7 +10320,7 @@ OO.ui.IndexLayout.prototype.onStackLayoutSet = function ( card ) {
  * @param {number} [itemIndex] A specific item to focus on
  */
 OO.ui.IndexLayout.prototype.focus = function ( itemIndex ) {
-       var $input, card,
+       var card,
                items = this.stackLayout.getItems();
 
        if ( itemIndex !== undefined && items[ itemIndex ] ) {
@@ -10127,10 +10338,7 @@ OO.ui.IndexLayout.prototype.focus = function ( itemIndex ) {
        }
        // Only change the focus if is not already in the current card
        if ( !card.$element.find( ':focus' ).length ) {
-               $input = card.$element.find( ':input:first' );
-               if ( $input.length ) {
-                       $input[ 0 ].focus();
-               }
+               OO.ui.findFocusable( card.$element ).focus();
        }
 };
 
@@ -10139,27 +10347,7 @@ OO.ui.IndexLayout.prototype.focus = function ( itemIndex ) {
  * on it.
  */
 OO.ui.IndexLayout.prototype.focusFirstFocusable = function () {
-       var i, len,
-               found = false,
-               items = this.stackLayout.getItems(),
-               checkAndFocus = function () {
-                       if ( OO.ui.isFocusableElement( $( this ) ) ) {
-                               $( this ).focus();
-                               found = true;
-                               return false;
-                       }
-               };
-
-       for ( i = 0, len = items.length; i < len; i++ ) {
-               if ( found ) {
-                       break;
-               }
-               // Find all potentially focusable elements in the item
-               // and check if they are focusable
-               items[ i ].$element
-                       .find( 'input, select, textarea, button, object' )
-                       .each( checkAndFocus );
-       }
+       OO.ui.findFocusable( this.stackLayout.$element ).focus();
 };
 
 /**
@@ -10363,7 +10551,8 @@ OO.ui.IndexLayout.prototype.clearCards = function () {
 OO.ui.IndexLayout.prototype.setCard = function ( name ) {
        var selectedItem,
                $focused,
-               card = this.cards[ name ];
+               card = this.cards[ name ],
+               previousCard = this.currentCardName && this.cards[ this.currentCardName ];
 
        if ( name !== this.currentCardName ) {
                selectedItem = this.tabSelectWidget.getSelectedItem();
@@ -10371,21 +10560,34 @@ OO.ui.IndexLayout.prototype.setCard = function ( name ) {
                        this.tabSelectWidget.selectItemByData( name );
                }
                if ( card ) {
-                       if ( this.currentCardName && this.cards[ this.currentCardName ] ) {
-                               this.cards[ this.currentCardName ].setActive( false );
-                               // Blur anything focused if the next card doesn't have anything focusable - this
-                               // is not needed if the next card has something focusable because once it is focused
-                               // this blur happens automatically
-                               if ( this.autoFocus && !card.$element.find( ':input' ).length ) {
-                                       $focused = this.cards[ this.currentCardName ].$element.find( ':focus' );
+                       if ( previousCard ) {
+                               previousCard.setActive( false );
+                               // Blur anything focused if the next card doesn't have anything focusable.
+                               // This is not needed if the next card has something focusable (because once it is focused
+                               // this blur happens automatically). If the layout is non-continuous, this check is
+                               // meaningless because the next card is not visible yet and thus can't hold focus.
+                               if (
+                                       this.autoFocus &&
+                                       this.stackLayout.continuous &&
+                                       OO.ui.findFocusable( card.$element ).length !== 0
+                               ) {
+                                       $focused = previousCard.$element.find( ':focus' );
                                        if ( $focused.length ) {
                                                $focused[ 0 ].blur();
                                        }
                                }
                        }
                        this.currentCardName = name;
-                       this.stackLayout.setItem( card );
                        card.setActive( true );
+                       this.stackLayout.setItem( card );
+                       if ( !this.stackLayout.continuous && previousCard ) {
+                               // This should not be necessary, since any inputs on the previous card should have been
+                               // blurred when it was hidden, but browsers are not very consistent about this.
+                               $focused = previousCard.$element.find( ':focus' );
+                               if ( $focused.length ) {
+                                       $focused[ 0 ].blur();
+                               }
+                       }
                        this.emit( 'set', card );
                }
        }
@@ -10475,6 +10677,7 @@ OO.inheritClass( OO.ui.PanelLayout, OO.ui.Layout );
  * @constructor
  * @param {string} name Unique symbolic name of card
  * @param {Object} [config] Configuration options
+ * @cfg {jQuery|string|Function|OO.ui.HtmlSnippet} [label] Label for card's tab
  */
 OO.ui.CardLayout = function OoUiCardLayout( name, config ) {
        // Allow passing positional parameters inside the config object
@@ -10491,6 +10694,7 @@ OO.ui.CardLayout = function OoUiCardLayout( name, config ) {
 
        // Properties
        this.name = name;
+       this.label = config.label;
        this.tabItem = null;
        this.active = false;
 
@@ -10576,6 +10780,9 @@ OO.ui.CardLayout.prototype.setTabItem = function ( tabItem ) {
  * @chainable
  */
 OO.ui.CardLayout.prototype.setupTabItem = function () {
+       if ( this.label ) {
+               this.tabItem.setLabel( this.label );
+       }
        return this;
 };
 
@@ -11310,8 +11517,8 @@ OO.ui.PopupToolGroup.prototype.setActive = function ( value ) {
                        }
                        if ( this.isClippedHorizontally() ) {
                                // Anchoring to the right also caused the popup to clip, so just make it fill the container
-                               containerWidth = this.$clippableContainer.width();
-                               containerLeft = this.$clippableContainer.offset().left;
+                               containerWidth = this.$clippableScrollableContainer.width();
+                               containerLeft = this.$clippableScrollableContainer.offset().left;
 
                                this.toggleClipping( false );
                                this.$element.removeClass( 'oo-ui-popupToolGroup-right' );
@@ -12119,7 +12326,6 @@ OO.ui.OutlineControlsWidget.prototype.setAbilities = function ( abilities ) {
 };
 
 /**
- *
  * @private
  * Handle outline change events.
  */
@@ -13031,6 +13237,18 @@ OO.mixinClass( OO.ui.CapsuleMultiSelectWidget, OO.ui.mixin.IconElement );
 
 /* Methods */
 
+/**
+ * Construct a OO.ui.CapsuleItemWidget (or a subclass thereof) from given label and data.
+ *
+ * @protected
+ * @param {Mixed} data Custom data of any type.
+ * @param {string} label The label text.
+ * @return {OO.ui.CapsuleItemWidget}
+ */
+OO.ui.CapsuleMultiSelectWidget.prototype.createItemWidget = function ( data, label ) {
+       return new OO.ui.CapsuleItemWidget( { data: data, label: label } );
+};
+
 /**
  * Get the data of the items in the capsule
  * @return {Mixed[]}
@@ -13071,7 +13289,7 @@ OO.ui.CapsuleMultiSelectWidget.prototype.setItemsFromData = function ( datas ) {
                        }
                }
                if ( !item ) {
-                       item = new OO.ui.CapsuleItemWidget( { data: data, label: label } );
+                       item = widget.createItemWidget( data, label );
                }
                widget.addItems( [ item ], i );
        } );
@@ -13100,9 +13318,9 @@ OO.ui.CapsuleMultiSelectWidget.prototype.addItemsFromData = function ( datas ) {
                if ( !widget.getItemFromData( data ) ) {
                        item = menu.getItemFromData( data );
                        if ( item ) {
-                               items.push( new OO.ui.CapsuleItemWidget( { data: data, label: item.label } ) );
+                               items.push( widget.createItemWidget( data, item.label ) );
                        } else if ( widget.allowArbitrary ) {
-                               items.push( new OO.ui.CapsuleItemWidget( { data: data, label: String( data ) } ) );
+                               items.push( widget.createItemWidget( data, String( data ) ) );
                        }
                }
        } );
@@ -13549,6 +13767,10 @@ OO.ui.CapsuleItemWidget.prototype.onCloseKeyDown = function ( e ) {
  *
  *     $( 'body' ).append( dropDown.$element );
  *
+ *     dropDown.getMenu().selectItemByData( 'b' );
+ *
+ *     dropDown.getMenu().getSelectedItem().getData(); // returns 'b'
+ *
  * For more information, please see the [OOjs UI documentation on MediaWiki] [1].
  *
  * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options
@@ -13870,6 +14092,7 @@ OO.ui.SelectFileWidget.prototype.setValue = function ( file ) {
  * @protected
  */
 OO.ui.SelectFileWidget.prototype.updateUI = function () {
+       var $label;
        if ( !this.isSupported ) {
                this.$element.addClass( 'oo-ui-selectFileWidget-notsupported' );
                this.$element.removeClass( 'oo-ui-selectFileWidget-empty' );
@@ -13878,9 +14101,12 @@ OO.ui.SelectFileWidget.prototype.updateUI = function () {
                this.$element.addClass( 'oo-ui-selectFileWidget-supported' );
                if ( this.currentFile ) {
                        this.$element.removeClass( 'oo-ui-selectFileWidget-empty' );
-                       this.setLabel( this.currentFile.name +
-                               ( this.currentFile.type !== '' ? OO.ui.msg( 'ooui-semicolon-separator' ) + this.currentFile.type : '' )
-                       );
+                       $label = $( [] );
+                       if ( this.currentFile.type !== '' ) {
+                               $label = $label.add( $( '<span>' ).addClass( 'oo-ui-selectFileWidget-fileType' ).text( this.currentFile.type ) );
+                       }
+                       $label = $label.add( $( '<span>' ).text( this.currentFile.name ) );
+                       this.setLabel( $label );
                } else {
                        this.$element.addClass( 'oo-ui-selectFileWidget-empty' );
                        this.setLabel( this.placeholder );
@@ -16026,7 +16252,6 @@ OO.ui.ComboBoxWidget.prototype.onInputChange = function ( value ) {
 /**
  * Handle mouse click events.
  *
- *
  * @private
  * @param {jQuery.Event} e Mouse click event
  */
@@ -16041,7 +16266,6 @@ OO.ui.ComboBoxWidget.prototype.onClick = function ( e ) {
 /**
  * Handle key press events.
  *
- *
  * @private
  * @param {jQuery.Event} e Key press event
  */
@@ -16134,7 +16358,6 @@ OO.ui.ComboBoxWidget.prototype.setDisabled = function ( disabled ) {
  *     ] );
  *     $( 'body' ).append( fieldset.$element );
  *
- *
  * @class
  * @extends OO.ui.Widget
  * @mixins OO.ui.mixin.LabelElement
@@ -16644,7 +16867,6 @@ OO.ui.MenuOptionWidget.static.scrollIntoViewOnSelect = true;
  *     } );
  *     $( 'body' ).append( myDropdown.$element );
  *
- *
  * @class
  * @extends OO.ui.DecoratedOptionWidget
  *
@@ -16854,6 +17076,7 @@ OO.ui.TabOptionWidget.static.highlightable = false;
  * @class
  * @extends OO.ui.Widget
  * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.ClippableElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
@@ -18748,6 +18971,7 @@ OO.ui.MenuSelectWidget.prototype.toggle = function ( visible ) {
  *
  * @class
  * @extends OO.ui.MenuSelectWidget
+ * @mixins OO.ui.mixin.FloatableElement
  *
  * @constructor
  * @param {OO.ui.Widget} [inputWidget] Widget to provide the menu for.
@@ -18768,10 +18992,12 @@ OO.ui.FloatingMenuSelectWidget = function OoUiFloatingMenuSelectWidget( inputWid
        // Parent constructor
        OO.ui.FloatingMenuSelectWidget.parent.call( this, config );
 
-       // Properties
+       // Properties (must be set before mixin constructors)
        this.inputWidget = inputWidget; // For backwards compatibility
        this.$container = config.$container || this.inputWidget.$element;
-       this.onWindowResizeHandler = this.onWindowResize.bind( this );
+
+       // Mixins constructors
+       OO.ui.mixin.FloatableElement.call( this, $.extend( {}, config, { $floatableContainer: this.$container } ) );
 
        // Initialization
        this.$element.addClass( 'oo-ui-floatingMenuSelectWidget' );
@@ -18782,75 +19008,37 @@ OO.ui.FloatingMenuSelectWidget = function OoUiFloatingMenuSelectWidget( inputWid
 /* Setup */
 
 OO.inheritClass( OO.ui.FloatingMenuSelectWidget, OO.ui.MenuSelectWidget );
+OO.mixinClass( OO.ui.FloatingMenuSelectWidget, OO.ui.mixin.FloatableElement );
 
 // For backwards compatibility
 OO.ui.TextInputMenuSelectWidget = OO.ui.FloatingMenuSelectWidget;
 
 /* Methods */
 
-/**
- * Handle window resize event.
- *
- * @private
- * @param {jQuery.Event} e Window resize event
- */
-OO.ui.FloatingMenuSelectWidget.prototype.onWindowResize = function () {
-       this.position();
-};
-
 /**
  * @inheritdoc
  */
 OO.ui.FloatingMenuSelectWidget.prototype.toggle = function ( visible ) {
        var change;
        visible = visible === undefined ? !this.isVisible() : !!visible;
-
        change = visible !== this.isVisible();
 
        if ( change && visible ) {
                // Make sure the width is set before the parent method runs.
-               // After this we have to call this.position(); again to actually
-               // position ourselves correctly.
-               this.position();
+               this.setIdealSize( this.$container.width() );
        }
 
        // Parent method
+       // This will call this.clip(), which is nonsensical since we're not positioned yet...
        OO.ui.FloatingMenuSelectWidget.parent.prototype.toggle.call( this, visible );
 
        if ( change ) {
-               if ( this.isVisible() ) {
-                       this.position();
-                       $( this.getElementWindow() ).on( 'resize', this.onWindowResizeHandler );
-               } else {
-                       $( this.getElementWindow() ).off( 'resize', this.onWindowResizeHandler );
-               }
+               this.togglePositioning( this.isVisible() );
        }
 
        return this;
 };
 
-/**
- * Position the menu.
- *
- * @private
- * @chainable
- */
-OO.ui.FloatingMenuSelectWidget.prototype.position = function () {
-       var $container = this.$container,
-               pos = OO.ui.Element.static.getRelativePosition( $container, this.$element.offsetParent() );
-
-       // Position under input
-       pos.top += $container.height();
-       this.$element.css( pos );
-
-       // Set width
-       this.setIdealSize( $container.width() );
-       // We updated the position, so re-evaluate the clipping state
-       this.clip();
-
-       return this;
-};
-
 /**
  * OutlineSelectWidget is a structured list that contains {@link OO.ui.OutlineOptionWidget outline options}
  * A set of controls can be provided with an {@link OO.ui.OutlineControlsWidget outline controls} widget.
@@ -19235,7 +19423,6 @@ OO.ui.NumberInputWidget.prototype.onWheel = function ( event ) {
 /**
  * Handle key down events.
  *
- *
  * @private
  * @param {jQuery.Event} e Key down event
  */
index 2043424..d680396 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/apex/images/icons/picture.png and b/resources/lib/oojs-ui/themes/apex/images/icons/picture.png differ
index 24d7315..246e130 100644 (file)
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
     <g id="picture">
-        <path id="frame" d="M18 4H6c-2-.007-3 .993-3 2.993L3.014 16C3 18 4 18.988 6 19h12c2-.012 2.994-1 3-3.006v-9c-.006-2-1-3-3-2.994zm1 13H5V6h14v11z"/>
-        <path id="mountains" d="M6 13.5L9.5 10l2.328 2.312-1.312 1.094.875 1.032L15.5 11l2.5 2v3H6z"/>
-        <path id="sky" d="M6 12l3.516-4.156 3.046 3.172L15.5 9l2.5 2V7H6z"/>
+        <path id="frame" d="M4 5v13h16v-13zm15 12h-14v-11h14z"/>
+        <path id="mountains" d="M9.5 10l2.328 2.312-1.312 1.094.875 1.032 4.109-3.438 2.5 2v3h-12v-2.5z"/>
+        <path id="sky" d="M9.516 7.844l3.046 3.172 2.938-2.016 2.5 2v-4h-12v5z"/>
     </g>
 </svg>
index fb6b985..2eedd1e 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/apex/images/icons/table.png and b/resources/lib/oojs-ui/themes/apex/images/icons/table.png differ
index 3c901f7..b5733fb 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
     <g id="table-insert">
-        <path id="table" d="M4 5v13h16V5zm2 2h5v4H6zm7 0h5v4h-5zm-7 5h5v4H6zm7 0h5v4h-5z"/>
+        <path id="table" d="M4 6v11h15V6zm1 3h6v3H5zm7 0h6v3h-6zm-7 4h6v3H5zm7 0h6v3h-6z"/>
     </g>
 </svg>
index d6dc62c..f63756b 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/picture-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/picture-invert.png differ
index be2c66d..a969967 100644 (file)
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
     <g id="picture">
-        <path id="frame" d="M18 4H6c-2-.007-3 .993-3 2.993L3.014 16C3 18 4 18.988 6 19h12c2-.012 2.994-1 3-3.006v-9c-.006-2-1-3-3-2.994zm1 13H5V6h14v11z"/>
-        <path id="mountains" d="M6 13.5L9.5 10l2.328 2.312-1.312 1.094.875 1.032L15.5 11l2.5 2v3H6z"/>
-        <path id="sky" d="M6 12l3.516-4.156 3.046 3.172L15.5 9l2.5 2V7H6z"/>
+        <path id="frame" d="M4 5v13h16v-13zm15 12h-14v-11h14z"/>
+        <path id="mountains" d="M9.5 10l2.328 2.312-1.312 1.094.875 1.032 4.109-3.438 2.5 2v3h-12v-2.5z"/>
+        <path id="sky" d="M9.516 7.844l3.046 3.172 2.938-2.016 2.5 2v-4h-12v5z"/>
     </g>
 </svg>
index 2043424..d680396 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/picture.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/picture.png differ
index 24d7315..246e130 100644 (file)
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
     <g id="picture">
-        <path id="frame" d="M18 4H6c-2-.007-3 .993-3 2.993L3.014 16C3 18 4 18.988 6 19h12c2-.012 2.994-1 3-3.006v-9c-.006-2-1-3-3-2.994zm1 13H5V6h14v11z"/>
-        <path id="mountains" d="M6 13.5L9.5 10l2.328 2.312-1.312 1.094.875 1.032L15.5 11l2.5 2v3H6z"/>
-        <path id="sky" d="M6 12l3.516-4.156 3.046 3.172L15.5 9l2.5 2V7H6z"/>
+        <path id="frame" d="M4 5v13h16v-13zm15 12h-14v-11h14z"/>
+        <path id="mountains" d="M9.5 10l2.328 2.312-1.312 1.094.875 1.032 4.109-3.438 2.5 2v3h-12v-2.5z"/>
+        <path id="sky" d="M9.516 7.844l3.046 3.172 2.938-2.016 2.5 2v-4h-12v5z"/>
     </g>
 </svg>
index 9cc620a..ee9885f 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.png differ
index 246be85..808d8d8 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
     <g id="table-insert">
-        <path id="table" d="M4 5v13h16V5zm2 2h5v4H6zm7 0h5v4h-5zm-7 5h5v4H6zm7 0h5v4h-5z"/>
+        <path id="table" d="M4 6v11h15V6zm1 3h6v3H5zm7 0h6v3h-6zm-7 4h6v3H5zm7 0h6v3h-6z"/>
     </g>
 </svg>
index fb6b985..2eedd1e 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/table.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/table.png differ
index 3c901f7..b5733fb 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
     <g id="table-insert">
-        <path id="table" d="M4 5v13h16V5zm2 2h5v4H6zm7 0h5v4h-5zm-7 5h5v4H6zm7 0h5v4h-5z"/>
+        <path id="table" d="M4 6v11h15V6zm1 3h6v3H5zm7 0h6v3h-6zm-7 4h6v3H5zm7 0h6v3h-6z"/>
     </g>
 </svg>